State Machine prblem in VHDL

F

fpgawizz

I have this state machine where in reset state , I assign four signals (8
bit stdlogic vecs) values..and then in the next state i try to read their
values and pass it on to a display..for some reason, i get all zeros..i
used modelsim to simulate and it looked good..

here is the snippet..

case current_state is
when RESET =>
R0 <= "11110001";
R1 <= "01010101";
R2 <= "10111100";
R3 <= "11001101";
next_state <= IDLE;
when IDLE =>
sd0 <= R0(3 downto 0);
sd1 <= R0(7 downto 4);
sd2 <= R1(3 downto 0);
sd3 <= R1(7 downto 4);
if BTN0 = '1' then
next_state <= ChkOp;
else
next_state <= IDLE;
end if;
when ChkOp =>
yada yada yada.....

sd0,sd1,sd2 and sd3 are connected to my display which is running at 1KHz.
My state machine is running at abot 250 Hz. Any ideas why my 4 outputs are
at zero and not displaying the correct values.

thanks
 
N

Neo

It is difficult to say with what you have posted. If you can, put the
complete code or atleast the complete process where the case statement
resides.
 
C

charles.elias

The code you posted looks good. Try the change below. It should not
be necessary, but I have had to do similar changes to make a certain
compiler synthesize my code properly.

when IDLE =>
sd0(3 downto 0) <= R0(3 downto 0);
sd1(3 downto 0) <= R0(7 downto 4);
sd2(3 downto 0) <= R1(3 downto 0);
sd3(3 downto 0) <= R1(7 downto 4);
if BTN0 = '1' then
next_state <= ChkOp;
else
next_state <= IDLE;
end if;
 
F

fpgawizz

Neo,
Here is the complete code.

State_Memory:process(fsmclk,Reset,BTN0,BTN1,BTN2)
begin
if reset = '1' then
current_State <= RST;
elsif BTN0 = '1' then
current_State <= ChkOp;
elsif BTN1 = '1' then
current_State <= ReadSel;
elsif BTN2 = '1' then
current_state <= ShowR2R3;
elsif fsmclk'event and fsmclk = '1' then
current_state <= next_state;
internal_databus <= Databus;
end if;
end process State_Memory;

Next_State_Logic:
Process(current_state,BTN0,BTN1,BTN2)

begin

case current_state is
when RST =>
R0 <= "00000000";
R1 <= "00000001";
R2 <= "00000010";
R3 <= "00000011";
LD7 <= '1';
LD0 <= '0';
LD6 <= '0';
next_state <= IDLE;
when IDLE =>
SramAddr2 <= "00000000"; CE2 <= '1';
CE1 <= '0';
UB <= '1';
LB <= '0';
OE <= '1';
WE <= '1';
DataBus <= "ZZZZZZZZ";
LD0 <= '1';
LD6 <= '1';
LD7 <= '0';
sd0 <= R0(3 downto 0);
sd1 <= R0(7 downto 4);
sd2 <= R1(3 downto 0);
sd3 <= R1(7 downto 4);
if BTN0 = '1' then
next_state <= Chkop;
else
next_state <= IDLE;
end if;
when ChkOp =>
instruction <= InSel;
case Instruction(7 downto 4) is
when "0001" =>
next_state <= ADD;
when "0010" =>
next_State <= SUB;
when "0011" =>
next_state <= MUL;
when "0100" =>
next_State <= SHR;
when "0101" =>
next_State <= SHL;
when "1010" =>
next_state <= LD;
when "1111" =>
next_state <= ST;
when others =>
next_State <= IDLE;
end case;

when ADD =>
LD7 <= '1';
when SUB =>
case Instruction(3 downto 0) is
when "0000" =>
R0 <= R0 - R0;
when "0100" =>
R0 <= R1 - R0;
when "1000" =>
R0 <= R2 - R0;
when "1100" =>
R0 <= R3 - R0;
when "0001" =>
R1 <= R0 - R1;
when "0101" =>
R1 <= R1 - R1;
when "1001" =>
R1 <= R2 - R1;
when "1101" =>
R1 <= R3 - R1;
when others =>
R0 <= R0;
R1 <= R1;
R2 <= R2;
R3 <= R3;
end case;
next_state <= IDLE;
when MUL =>
when SHR =>
case Instruction(3 downto 2) is
when "00" =>
R0 <= '0' & R0(7 downto 1);
when "01" =>
R1 <= '0' & R1(7 downto 1);
when "10" =>
R2 <= '0' & R2(7 downto 1);
when "11" =>
R3 <= '0' & R3(7 downto 1);
when others =>
R0 <= R0;
R1 <= R1;
R2 <= R2;
R3 <= R3;
end case;
next_state <= IDLE;

when SHL =>
case Instruction(3 downto 2) is
when "00" =>
R0 <= R0(6 downto 0) &'0';
when "01" =>
R1 <= R1(6 downto 0) & '0';
when "10" =>
R2 <= R2(6 downto 0) & '0';
when "11" =>
R3 <= R3(6 downto 0) & '0';
when others =>
R0 <= R0;
R1 <= R1;
R2 <= R2;
R3 <= R3;
end case;
next_state <= IDLE;

when LD =>
when ST =>

when SetupRead =>
when Read =>
when SetupWrite =>

when Write =>

when ReadSel =>

when SetupSelRead =>

when SelRead =>

when ShowR2R3 =>


end case;

end process Next_State_Logic;
end Behavioral;
 
R

Ralf Hildebrandt

fpgawizz wrote:

Next_State_Logic:
Process(current_state,BTN0,BTN1,BTN2)

begin

case current_state is
when RST =>
R0 <= "00000000";
R1 <= "00000001";
R2 <= "00000010";
R3 <= "00000011";
LD7 <= '1';
LD0 <= '0';
LD6 <= '0';
next_state <= IDLE;
when IDLE =>
SramAddr2 <= "00000000"; CE2 <= '1';
CE1 <= '0';
UB <= '1';
LB <= '0';
OE <= '1';
WE <= '1';
DataBus <= "ZZZZZZZZ";
LD0 <= '1';
LD6 <= '1';
LD7 <= '0';
sd0 <= R0(3 downto 0);
sd1 <= R0(7 downto 4);
sd2 <= R1(3 downto 0);
sd3 <= R1(7 downto 4);
if BTN0 = '1' then
next_state <= Chkop;
else
next_state <= IDLE;
end if;
when ChkOp => ....
when SUB =>
case Instruction(3 downto 0) is
when "0000" =>
R0 <= R0 - R0;
....

So R0 to R3 are latches and I guess you are confronted with the "muxed
latch problem". I guess so especially because you are writing in more
than one case-branch to the signals (which is not forbidden but can lead
to this problem.

Let me explain:
The latches are enabled if some conditions are met (current_state = RST
or current_state = SUB...). Now, if the state changes, the enable
signals change with a delay. The same holds for the latch-inputs and for
the muxes that select which data have to be stored. Therefore your
latches may be enabled a little bit longer than the latch-inputs and the
muxes are stable and therefore some faulty data may be stored.

For FPGAs the solution is simple: Don't use latches - take flipflops!
You got a lot of them and power dissipation is not the main fact. ;-)
Otherwise make shure that the latch-enable-signals are inactive before
the muxes and therefore the latch-inputs change their value.


Ralf
 
C

cebmisc

I think you are confusing what goes into what process.

Everything that is intended to be a latch, that is, something that will
hold the current state of your logic until the next clock cycle, should
be set in the clock process (State_Memory). Things that are decodes of
latches or primary inputs should be in separate,
combinational_logic_type processes. Combinational logic processes have
these characteristics:
1. Any signal that appears on the right-hand side of an expression
should be in the sensitivity list.
2. Any signal that is on the left-hand side of an assigment statement
must be set to the desired value by every possible path through that
process's logic. Otherwise you will get an unexpected implied latch.

In your case, it looks like you are trying to do *way* too much in the
Next_State_Logic process. I would suggest you use this process just to
compute what the next_state should be, based on the current state and
various input conditions.

Are R0, R1, R2, and R3 supposed to be registers? If so, you shouldn't
be setting them in the Next_State process. They should be set in the
clock process. Notice how you are setting them in some states of the
Next_State process, but not in others. This will create implied
latches, clocked by ???, that won't necessarily change on the rising
edge of fsmclk like you expect.

Are you trying to use sd0 ... sd3 to monitor the state of the R0 and R1
registers? If so, I would suggest moving the
sd0 <= R0(3 downto 0);
sd1 <= R0(7 downto 4);
sd2 <= R1(3 downto 0);
sd3 <= R1(7 downto 4);
statements out of the Next_State process and let them be stand-alone
concurrent assignment statements.

Charles Bailey
 
F

fpgawizz

Charles
Thanks. I will see if I can have just one process statement for my state
machine.
R0,R1,R2 and R3 need to be 4, 8-bit registers initialized to 00,01,02 and
03H.I am not sure how i can put this in the State_Memory process coz I
tried putting them under fsmclk'event and fsmclk='1' but i will be
overwriting them every clock cycle with 00,01,02and 03H. I only want them
to have these values at power up and if an asynchrounous reset happens.
Coz I need to do arithmetic ops on these 4 registers ( if you see my
states, i have add,sub..etc etc..)

sd0,sd1,sd2 and sd3 are 4 bit signals that port map to a display module
that displays them to 4 digits on a seven segment display. I could have
put those 4 statements outside then process but I also have an
asynchronous input called "BTN1", when pressed i must display contents of
R2 and R3. If i have a concurrent statement with sd0,sd1,sd2 and sd3
outside the process and then i try to assign them inside the process in a
state called ShowR2R3 when BTN1 = '1' I would get multisource errors on
sd0,sd1,sd2 and sd3 right?

The way sd0, sd1,sd2 and sd3 must work is at a default state they must
carry R0,R1 information and if asynchrounous input BTN1 = '1' then they
must carry R2,R3 info and go back to default state after BTN1 goes to
zero. Thats what I am trying to set in IDLE state bny making sd0,sd1,sd2
and sd3 display R0 and R1 contents.

comments??
 
C

cebmisc

R0,R1,R2 and R3 need to be 4, 8-bit registers initialized to 00,01,02
and
03H.I am not sure how i can put this in the State_Memory process coz I
tried putting them under fsmclk'event and fsmclk='1' but i will be
overwriting them every clock cycle with 00,01,02and 03H. I only want them
to have these values at power up and if an asynchrounous reset happens.
Coz I need to do arithmetic ops on these 4 registers ( if you see my
states, i have add,sub..etc etc..)
Consider this type of approach:

State_Memory:process(fsmclk,Reset)
begin
if reset = '1' then
current_State <= RST;
R0 <= "00000000";
R1 <= "00000001";
R2 <= "00000010";
R3 <= "00000011";
elsif fsmclk'event and fsmclk = '1' then
case current_state is
when ...
when SUB =>
case Instruction(3 downto 0) is
when "0000" => -- "XXYY" XX - Source, YY - DEST
R0 <= R0 - R0;
when "0100" =>
R0 <= R1 - R0;
when "1000" =>
R0 <= R2 - R0;
when "1100" =>
R0 <= R3 - R0;
when "0001" =>
R1 <= R0 - R1;
when "0101" =>
R1 <= R1 - R1;
when "1001" =>
R1 <= R2 - R1;
when "1101" =>
R1 <= R3 - R1;
end case;
when ...
end case;
current_state <= next_state;
internal_databus <= Databus;
end if;
end process State_Memory;

The way sd0, sd1,sd2 and sd3 must work is at a default state they must
carry R0,R1 information and if asynchrounous input BTN1 = '1' then they
must carry R2,R3 info and go back to default state after BTN1 goes to
zero. Thats what I am trying to set in IDLE state bny making sd0,sd1,sd2
and sd3 display R0 and R1 contents.

sd_proc: process(R0, R1, R2, R3, BTN1)
begin
If BTN1='1' then
sd0 <= R0(3 downto 0);
sd1 <= R0(7 downto 4);
sd2 <= R1(3 downto 0);
sd3 <= R1(7 downto 4);
else
sd0 <= R2(3 downto 0);
sd1 <= R2(7 downto 4);
sd2 <= R3(3 downto 0);
sd3 <= R3(7 downto 4);
end if;
end process;


Charles Bailey
 
F

fpgawizz

thanks charles.once i made my state machine synchronous w the clock, most
of my problems went away.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,534
Members
45,007
Latest member
OrderFitnessKetoCapsules

Latest Threads

Top