EmbDev.net

Forum: FPGA, VHDL & Verilog how to use clk in fsm


Author: daniel (Guest)
Posted on:

Rate this post
0 useful
not useful
I want to build a final state machine embodies eight numbers and then 
she proceeded to tell the eighth.
For example if  the  eight number  is four I want the machine extract 
four pulses of 1 clock cycle difference between between pulses and then 
wait another 10 clock cycles and then switches to the next state( and in 
the next do the same thing).
The problem that he dosent let me use the clock in the states ..
Does anyone have an idea what to do?


The code
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;

entity pulsim is 
   port( 
    resetN, clk : in std_logic;
    da         : in std_logic_vector(3 downto 0) ;
        db         : in std_logic_vector(3 downto 0) ;
        dc         : in std_logic_vector(3 downto 0) ;
        dd         : in std_logic_vector(3 downto 0)  ;
        de         : in std_logic_vector(3 downto 0)  ;
        df         : in std_logic_vector(3 downto 0)  ;
        dg         : in std_logic_vector(3 downto 0)  ;
        dh         : in std_logic_vector(3 downto 0)  ;
    sinus      : out  std_logic);
end pulsim ; 
architecture behavioral of pulsim is 


type state_type is (s0,s1,s2,s3,s4,s5,s6,s7);
signal current_s,next_s: state_type;
signal countera : std_logic_vector(4 downto 0) :=dh &'0' ;
signal counterb : std_logic_vector(4 downto 0) :="01010" ;
signal cinout   : std_logic ;

begin 
   
process ( resetN , clk)
   begin
    if resetN = '0' then
        current_s <= s0;
  elsif (rising_edge(clk)) then
  current_s <= next_s;
  end if;
   end process;


process (current_s,dh,clk)
begin
  sinus <= cinout ;
  case current_s is
     when s0 =>        --when current state is "s0"
     if(dh ="1111") then
      cinout <= '0';
      next_s <= s0;
   else
    if clk='1' then
      if countera /= "00000" then
        countera <= countera-"00001";
        cinout<= not(cinout);
        counterb<="01010";
      
      elsif (countera = "00000") and (counterb/="00000") then
          counterb <= counterb-"00001";
          cinout <= '0' ;
      else
      counterb<="01010";
      countera<=dg &'0';
      next_s <= s1;
      end if;
    end if;
  end if;
  when s1 => 
    
    if rising_edge(clk) then
      if countera /= "00000" then
        countera <= countera-"00001";
        cinout <= not (cinout) ;
        counterb<="01010";
      
      elsif (countera = "00000") and (counterb/="00000") then
          counterb <= counterb-"00001";
          cinout <= '0' ;
      else
      counterb<="01010";
      countera<=df &'0';
      next_s <= s2;
      end if;
    end if;        
      
      
  when s2 => 
    
    if rising_edge(clk) then
      if countera /= "00000" then
        countera <= countera-"00001";
        cinout <= not (cinout) ;
        counterb<="01010";
      
      elsif (countera = "00000") and (counterb/="00000") then
          counterb <= counterb-"00001";
          cinout <= '0' ;
      else
      counterb<="01010";
      countera<=de &'0';
      next_s <= s3;
      end if;
    end if;  
    
    when s3 => 
    
    if rising_edge(clk) then
      if countera /= "00000" then
        countera <= countera-"00001";
        cinout <= not (cinout) ;
        counterb<="01010";
      
      elsif (countera = "00000") and (counterb/="00000") then
          counterb <= counterb-"00001";
          cinout <= '0' ;
      else
      counterb<="01010";
      countera<=dd &'0';
      next_s <= s4;
      end if;
    end if;              
    
    when s4 => 
    
    if rising_edge(clk) then
      if countera /= "00000" then
        countera <= countera-"00001";
        cinout <= not (cinout) ;
        counterb<="01010";
      
      elsif (countera = "00000") and (counterb/="00000") then
          counterb <= counterb-"00001";
          cinout <= '0' ;
      else
      counterb<="01010";
      countera<=dc &'0';
      next_s <= s5;
      end if;
    end if;  
    
    when s5 => 
    
    if rising_edge(clk) then
      if countera /= "00000" then
        countera <= countera-"00001";
        cinout <= not (cinout) ;
        counterb<="01010";
      
      elsif (countera = "00000") and (counterb/="00000") then
          counterb <= counterb-"00001";
          cinout <= '0' ;
      else
      counterb<="01010";
      countera<=db &'0';
      next_s <= s6;
      end if;
    end if;                  
    
    
    when s6 => 
    
    if rising_edge(clk) then
      if countera /= "00000" then
        countera <= countera-"00001";
        cinout <= not (cinout) ;
        counterb<="01010";
      
      elsif (countera = "00000") and (counterb/="00000") then
          counterb <= counterb-"00001";
          cinout <= '0' ;
      else
      counterb<="01010";
      countera<=da &'0';
      next_s <= s7;
      end if;
    end if;    
    when s7 => 
    
    if rising_edge(clk) then
      if countera /= "00000" then
        countera <= countera-"00001";
        cinout<= not (cinout) ;
        counterb<="01010";
      
      elsif (countera = "00000") and (counterb/="00000") then
          counterb <= counterb-"00001";
          cinout <= '0' ;
      else
      counterb<="01010";
      countera<=dh &'0';
      next_s <= s0;
      end if;
    end if;            
         
  
  end case;
end process;

end behavioral;


: Edited by Moderator
Author: Lothar Miller (lkmiller) (Moderator)
Posted on:

Rate this post
0 useful
not useful
daniel wrote:
> a final state machine
In fact its a "finite" state machine. That means: this machine only has 
a limited number of states. The opposite would be a machine with 
uncountable sates, a machine with "infinte states"...

> The problem that he dosent let me use the clock in the states ..
> Does anyone have an idea what to do?
You have a VERY, VERY strange way of using a clock. Can you show me any 
example doing it a similar way?

No?

Correct. The only way to use a clock for synthesis is at the very 
beginning of a process. And additionally you should (for beginners 
"must") have only one clock sensitive to the same edge throughout.

And now simply have a look how others did that thing with those FSM.
A hint: a "rising_edge(clk)" involves a flipflop. And that's the state 
memory.
Additionally you need some logic to calculate the next state.
That's all...


One is fairly easy to see: you did programming in C previously. And now 
you want to "program" with VHDL. But if that was a "programming 
language", then it would be VHPL...
So up to now you have the wrong way of thinking: you think in software, 
but you must think in hardware. And then you can "describe" your 
thoughts.


BTW: did you see the "formatting options" for VHDL code a few lines 
above the text edit box? Use it. Its magic...

: Edited by Moderator
Author: Lothar Miller (lkmiller) (Moderator)
Posted on:

Rate this post
0 useful
not useful
Initialization with a non constant values is NOT synthesizeable (the 
init value can't be predicted by the synthesizer!!!):
signal countera : std_logic_vector(4 downto 0) :=dh &'0' ;


Now lets have a second look at your code. And there its easy to see the 
usual beginners problems with the 2-process-FSM: you have a 
combinatorial process and a process for the flipflops. But when you want 
to count, then that counter itself is (the simplest way of) a FSM. And 
each FSM has: flipflops and logic. And as that counter is an FSM also, 
it must have flipflops and logic.
As i said previously you will get flipflops when you use a 
"rising_edge()" (or a "falling_edge()" or a "'event"). Yo tried to 
involve that into your combinatorial process, and now you have two 
processes generating flipflops. Thats not the intention of writing a 
2-process-FSM.

What to do now?
1. use the 2-process-FSM further on.
Then you will have to kick out the clk of the combiunatorial process, 
and to invoke some signals like countera_next and counterb_next. And you 
will have to calculate the "next" value in the combinatorial process and 
you will have to transfer the "next" counter values to countera and 
counterb in the clocked process.

2. use the 1-process-FSM.
Then you will have to kich off those "next" values and you will have to 
invoke the clock to the combinatorial process.

Heres your problem analyzed:
http://www.lothar-miller.de/s9y/archives/43-Ein-od...
Try it with Google translator, its German...

As a result it will look this way as a 1-process-FSM:
type state_type is (s0,s1,s2,s3,s4,s5,s6,s7);
signal state: state_type;

signal countera : std_logic_vector(4 downto 0) :="00000" ;
signal counterb : std_logic_vector(4 downto 0) :="01010" ;
signal cinout   : std_logic ;

begin 
   
sinus <= cinout ;

process (clk)
begin
  if (rising_edge(clk)) then  -- the one and only clock

   case state is
   when s0 =>        --when current state is "s0"
     if(dh ="1111") then
      cinout <= '0';
      next_s <= s0;
     else
      if countera /= "00000" then
        countera <= countera-"00001";
        cinout<= not(cinout);
        counterb<="01010";
      
      elsif (countera = "00000") and (counterb/="00000") then
          counterb <= counterb-"00001";
          cinout <= '0' ;
      else
      counterb<="01010";
      countera<=dg &'0';
      next <= s1;
      end if;
     end if;

   when s1 => 
      if countera /= "00000" then
        countera <= countera-"00001";
        cinout <= not (cinout) ;
        counterb<="01010";
      
      elsif (countera = "00000") and (counterb/="00000") then
          counterb <= counterb-"00001";
          cinout <= '0' ;
      else
        counterb<="01010";
        countera<=df &'0';
        next <= s2;
      end if;
    
    :      
    :      

    when s7 => 
      if countera /= "00000" then
        countera <= countera-"00001";
        cinout<= not (cinout) ;
        counterb<="01010";
      
      elsif (countera = "00000") and (counterb/="00000") then
          counterb <= counterb-"00001";
          cinout <= '0' ;
      else
        counterb<="01010";
        countera<=dh &'0';
        next_s <= s0;
      end if;
  
    end case;
  end if; -- the one and only clock
end process;

end behavioral;

BTW: I strongly recommend to use the numeric_std lib instead of that old 
Synopsis libs...
http://www.lothar-miller.de/s9y/categories/16-Numeric_Std
I also strongly recommend using integers for counting. Its FAR WAY 
easier to read this here:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
:
:
signal countera : integer range 0 to 10 := 0;
signal counterb : integer range 0 to 10 := 10;
:
    when s7 => 
      if countera /= 0 then
        countera <= countera-1;
        cinout   <= not (cinout) ;
        counterb <= 10;
      elsif (countera = 0 and (counterb /= 0) then
        counterb <= counterb-1;
        cinout   <= '0' ;
      else
        counterb <= 10;
        countera <= to_integer(unsigned(dh))*2;
        next_s   <= s0;
      end if;
:
:
And as you see I also strongly recommend to use indetion to get an 
easily readable code...

: Edited by Moderator

Reply

Entering an e-mail address is optional. If you want to receive reply notifications by e-mail, please log in.

Rules — please read before posting

  • Post long source code as attachment, not in the text
  • Posting advertisements is forbidden.

Formatting options

  • [c]C code[/c]
  • [avrasm]AVR assembler code[/avrasm]
  • [vhdl]VHDL code[/vhdl]
  • [code]code in other languages, ASCII drawings[/code]
  • [math]formula (LaTeX syntax)[/math]




Bild automatisch verkleinern, falls nötig
Note: the original post is older than 6 months. Please don't ask any new questions in this thread, but start a new one.