I'm implementing an UML state diagram with VHDL using case statement. do/ and exit state activities are easy to implement. However, does anyone know how to implement the entry state activity in an efficient way?
I thought of adding a flag to execute only one time or adding an extra state called name_entry before of name state. But I dislike these options...
If I understood well you just want to describe an FSM in VHDL?
To do so you first need do declare all you possible states in a TYPE
TYPE my_state_type IS (s0, s1, s2);
Then you have to create a signal which takes my_state_type as a type.
SIGNAL my_state : my_state_type := s0; -- for initialisation
Then, in your process you indeed need a CASE for each of your state.
fsm : PROCESS (clk, rst)
BEGIN
IF (rst = '1') THEN
my_state <= s0 ; -- reset value
ELSIF (rising_edge(clk)) THEN
CASE my_state IS
WHEN s0 => output <= '1'; -- do
IF (input = '1') THEN -- condition to enter s1
my_state <= s1;
ELSE -- condition to stay in s0
my_state <= s0;
END IF;
WHEN s1 => my_state <= s2; -- stay in s1 for only one clk cycle
WHEN s2 => my_state <= s0; -- stay in s2 for only one clk cycle
WHEN OTHERS => my_state <= s0;
END CASE;
END IF;
END PROCESS;
I hope it answered your question or at least will help.
Related
I am working on a Verilog design where I am using SRAM inside a FSM. I need to synthesize it later on since I want to fabricate the IC. My question is that I have a fully working code using reg registers where I use blocking assignment for concurrent operation. Since there is no clock in this system, it works fine. Now, I want to replace these registers with SRAM based memory, which brings in clock into the system. My first thought is to use non-blocking assignment and changing the dependency list from always #(*) to always # (negedge clk).
In the code snippet below, I want to read 5 sets of data from the SRAM (SR4). So what I do is I place a counter that counts till 5 (wait_var) for this to happen. By introducing additional counter, this code ensures that at 1st clock edge it enters the counter and at subsequent clock edges, the five sets of data is read from SRAM. This technique works for simple logic such as this.
S_INIT_MEM: begin
// ******Off-Chip (External) Controller will write the data into SR4. Once data is written, init_data will be raised to 1.******
if (init_data == 1'b0) begin
CEN4 <= CEN;
WEN4 <= WEN;
RETN4 <= RETN;
EMA4 <= EMA;
A4 <= A_in;
D4 <= D_in;
end
else begin
CEN4 <= 1'b0; //SR4 is enabled
EMA4 <= 3'b0; //EMA set to 0
WEN4 <= 1'b1; //SR4 set to read mode
RETN4 <= 1'b1; //SR4 RETN is turned ON
A4 <= 8'b0000_0000;
if (wait_var < 6) begin
if (A4 == 8'b0000_0000 ) begin
NUM_DIMENSIONS <= Q4;
A4 <= 8'b0000_0001;
end
if (A4 == 8'b0000_0001 ) begin
NUM_PARTICLES <= Q4;
A4 <= 8'b0000_0010;
end
if (A4 == 8'b0000_0010 ) begin
n_gd_iterations <= Q4;
A4 <= 8'b0000_0011;
end
if (A4 == 8'b0000_0011 ) begin
iterations <= Q4;
A4 <= 8'b0000_0100;
end
if (A4 == 8'b0000_0100 ) begin
threshold_val <= Q4;
A4 <= 8'b0000_0101;
end
wait_var <= wait_var + 1;
end
//Variables have been read from SR4
if(wait_var == 6) begin
CEN4 <= 1'b1;
next_state <= S_INIT_PRNG;
wait_var <= 0;
end
else begin
next_state <= S_INIT_MEM;
end
end
end
However, when I need to write a complex logic in the similar fashion, the counter based delay method gets too complex. Eg. say I want to read data from one SRAM (SR1) and want to write it to another SRAM (SR3).
CEN1 = 1'b0;
A1 = ((particle_count-1)*NUM_DIMENSIONS) + (dimension_count-1);
if (CEN1 == 1'b0) begin
CEN3 = 1'b0;
WEN3 = 1'b0;
A3 = ((particle_count-1)*NUM_DIMENSIONS) + (dimension_count-1);
if(WEN3 == 1'b0) begin
D3 = Q1;
WEN3 = 1'b1;
CEN3 = 1'b1;
end
CEN1 = 1'b1;
end
I know this still uses blocking assignments and I need to convert them to non-blocking assignments, but if I do and I do not introduce 1 clock cycle delay manually using counter, it will not work as desired. Is there a way to get around this in a simpler manner?
Any help would be highly appreciated.
The main part is, that non-blocking assignments are a simulation only artifact and provides a way for simulation to match hardware behavior. If you use them incorrectly, you might end up with simulation time races and mismatch with hardware. In this case your verification effort goes to null.
There is a set of common practices used in the industry to handle this situation. One is to use non-blocking assignments for outputs of all sequential devices. This avoids races and makes sure that the behavior of sequential flops and latches pipes data the same way as in real hardware.
Hence, one cycle delay caused by the non-blocking assignments is a myth. If you design sequential flops when the second one latches the data from the first, then the data will be moved across flops sequentially every cycle:
clk ------v----------------v
in1 -> [flop1] -> out1 -> [flop2] -> out2
clk 1 1 1 0
clk 3 1 1 1
clk 4 0 0 1
clk 5 0 0 0
In the above example data is propagated from out1 to out2 in the every next clock cycle which can be expressed in verilog as
always #(posedge clk)
out1 <= in1;
always #(posedge clk)
out2 <= out1;
Or you can combine those
always #(posedge clk) begin
out1 <= in1;
out2 <= out1;
end
So, the task of your design is to cleanly separate sequential logic from combinatorial logic and therefore separate blocks with blocking and non-blocking assignments.
There are cases which can and must be used with blocking assignments inside sequential blocks, as mentioned in comments: if you use temporary vars to simplify your expressions inside sequential blocks assuming that those vars are never used anywhere else.
Other than above never mix blocking and non-blocking assignments in a single always block.
Also, usually due to synthesis methodologies, use if 'negedge' is discouraged. Avoid it unless your synthesis methodology does not care.
You should browse around to get more information and example of blocking/non-blocking assignments and their use.
Problem Statement:
Design and implement a control unit for a digital lock. The digital
lock has the passcode “1010”. The code should be entered via 2 Push
Buttons: one button for entering 1’s (B1) and another for entering 0’s
(B0). Use a third push button (Reset) to add reset functionality.
Based on the entered code, glow an LED for the following outputs
LED_0 will glow indicating PASS, if the entered 4-digit binary code is correct
LED_1 will glow indicating FAIL, if the entered 4-digit binary code is incorrect
We need to make sure output is given only after all four inputs are taken.
Error: My coded module won't ever show a pass or fail output.
FSM State diagram to be implemented
module lock_FSM(
input B0,
input B1,
input Reset,
input Clk,
output reg PASS,
output reg FAIL
);
reg [3:0] present_state, next_state;
parameter S0 = 4'b0000, S1 = 4'b0001, S2 = 4'b0010, S3 = 4'b0011, S4 = 4'b0100;
parameter E1 = 4'b0101, E2 = 4'b0110, E3 = 4'b0111, E4 = 4'b1000;
//State register
always #(posedge Clk, posedge Reset)
begin
if(Reset == 1)
present_state = S0;
end
always #(posedge B0, posedge B1)
begin
present_state = next_state;
end
//Input block
always # (present_state, B0, B1)
begin
if(B0 == 0 && B1 == 0)
next_state = present_state;
else
case (present_state)
S0 : next_state = B1 ? S1 : E1;
S1 : next_state = B0 ? S2 : E2;
S2 : next_state = B1 ? S3 : E3;
S3 : next_state = B0 ? S4 : E4;
E1 : next_state = E2;
E2 : next_state = E3;
E3 : next_state = E4;
endcase
end
//Output
always#(present_state)
begin
case(present_state)
S4: begin PASS = 1; FAIL = 0; end
E4: begin PASS = 0; FAIL = 1; end
default : begin PASS = 0; FAIL = 0; end
endcase
end
endmodule
The output should have been PASS = 1 after 4th posedge in (B0 or B1) and stayed there until Reset is pressed.
I need to update the states only when one of B0 or B1 is pressed (as B1 and B0 are push buttons).
There is a problem with how you coded your state register. All assignments to a signal should be made within a single always block, not from 2 blocks. Change:
always #(posedge Clk, posedge Reset)
begin
if(Reset == 1)
present_state = S0;
end
always #(posedge B0, posedge B1)
begin
present_state = next_state;
end
to:
always #(posedge Clk, posedge Reset) begin
if (Reset == 1) begin
present_state <= S0;
end else begin
present_state <= next_state;
end
end
In a typical FSM, updating the present state should be unconditional (not dependent upon signals like B0). You should account for those conditions in your next_state logic. Also, good coding practices recommend nonblocking (<=) assignments in sequential always blocks.
Another issue is that you have no way to exit the E4 state (aside from an asynchronous reset). Perhaps you should add a case to your case statement for that. Also, since you declared only 9 of the possible 16 states, the convention is to use a default statement to handle the undefined states.
What I'm designing is a moore machine that gives particular color for each state.
Here's a part of my code.
always #(*) begin
case (state)
S0 : led = 6'b111111;
S1 : led = 6'b010100; // have to blink //
S2 : led = 6'b100010;
S3 : led = 6'b110110;
default : led_output = 6'b000000;
endcase
end
endmodule
Before the code shown above, there are codes about assigning state corresponding to the input.
The code shown above is to determine the output value of moore machine. (Therefore the condition is *)
What I left is to assign led output value for each state.
However the condition for S1 is not only particular color but it has to 'blink' for period of 1s.
I already googled for 'blink LED' verilog code but they were little bit different from my situation.
I have no idea of coding block that is needed.
Can you give me some advice or answer for what to add to make S1 to blink?
To make it blink, you need to distinguish 2 states. So create a 1-bit signal, say sel, which toggles in S1 state, and its toggle speed as well as its duty meet your requirement in 'blink' for period of 1s. This is basically implemented with the help of a counter.
reg [3:0] cnt; // assume 4-bit long
reg sel;
// counter to determine the HIGH / LOW time of sel.
always#(posedge clk or negedge resetn)begin
if(!resetn)begin
cnt <= 4'h0;
end
// since you can exit S1 state at any time using push_button,
// make sure cnt is always ZERO when entering S1 state next time.
// also to save power when using clock gating, because this statement
// is only active for 1 cycle.
else if((state == S1) & ((push_button == 2'b01) | (push_button == 2'b10)))begin // S1 exit condition
cnt <= 4'h0;
end
else if(state == S1)begin
// sel HIGH lasts <HIGH_MAX_VAL>+1 cycles
// sel LOW lasts <LOW_MAX_VAL>+1 cycles
if(cnt == (sel ? <HIGH_MAX_VAL> : <LOW_MAX_VAL>))begin
cnt <= 4'h0;
end
else begin
cnt <= cnt + 4'h1;
end
end
end
always#(posedge clk or negedge resetn)begin
if(!resetn)begin
sel <= 1'h0;
end
else if((state == S1) & ((push_button == 2'b01) | (push_button == 2'b10)))begin
sel <= 1'h0;
end
else if(state == S1)begin
if(cnt == (sel ? <HIGH_MAX_VAL> : <LOW_MAX_VAL>))begin
sel <= ~sel;
end
end
end
Use sel to select between 2 led values.
always#(*)begin
case(state)
....
S1 : led = sel ? 6'b010100 : <ANOTHER_VALUE>;
....
endcase
end
So I'm trying to implement my first FSM, and I'm getting very confused.
The codes a bit long, so let me summarize:
I start with declaring inputs and outputs
Then state declarations (I have five plus three placeholders)
Then Current state assignment, which is sequential
always #(posedge clk)
begin
if (rst == 1'b1)
Current_State <= MainGreen;
else
Current_State <= Next_state;
end
And then... I get lost. I originally just had one big ol' sequential circuit that assigned next_state and outputs, but this was messy/ probably had lots of errors.
What I have right now simply has next_state logic, but nothing to do with outputs:
always #*
begin
Next_state = Current_State;
case (Current_State)
MainGreen:
begin
if (count && expired)
begin
Next_state = MainYel;
end
end
MainYel:
begin
if (WR && expired)
Next_state = AllRed;
else if (expired)
Next_state = SideGreen;
end
AllRed:
begin
if (expired)
Next_state = SideGreen;
end
SideGreen:
begin
if(sensor && expired)
Next_state = SideYel;
end
SideYel:
begin
if(expired)
Next_state = MainGreen;
end
endcase
end
I have about eight outputs based on state alone and four based on state and input. How should I assign them?
You're 90% of the way there. There are two ways to proceed (well probably more than that, but I'll give you what I think are two of the best options):
First, do you have a lot of outputs that only get asserted for a small minority of the states? If so, I'd recommend something like this in your combinatorial always block:
always #*
begin
// default output values
output1 = 1'b0;
output2 = 1'b0;
output3 = 1'b0;
....
case (Current_State)
STATE1:
begin
output2 = 1'b1;
// calculate next state
...
end
STATE2:
begin
output4 = 1'b1;
// calculate next state
...
end
...
endcase
end
This is probably the most efficient way to code your state machine since you don't need to define every output in every state. Now if you have each output active in a lot of different states, it might be easier for you to define those outputs in every state in your case statement.
A final way, which I wouldn't recommend, is to derive the sm ouputs in separate assign statements. It will work just as well, but I think keeping the outputs together with the next state logic is much easier for code maintenance and a good habit to develop. It's one thing to hack out some code quickly for an assignment, it's another to develop code for a real product that may be getting updated several times over the life of a product, and maintainability is essential (something I had to learn on the job because no one taught it in university).
i have to write in vhdl an FSM with timer.
I think that,there is no need you to get tired of understanding what my circuit will do.
I just wanted to help me with this:
Every change from a state to another state, there is one (or more) clock cycle delay.
The question is, how can i avoid it?
my vhdl code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_unsigned.ALL;
entity fsm_timers is
port( x: in bit;
clk, rst: in std_logic;
y: out bit);
end fsm_timers;
architecture Behavioral of fsm_timers is
constant T1: std_logic_vector(7 downto 0) :="00000011";
constant T2: std_logic_vector(7 downto 0) :="00000111";
signal t: std_logic_vector(7 downto 0) := (others=>'0');
signal rst_cnt: std_logic :='0';
Type state is (A,B,C);
signal pr_state, nx_state : state := A;
component counter is
port(reset,clock, inner_rst:in std_logic;
cnt:out std_logic_vector(7 downto 0));
end component;
begin
U_sum_counter: counter port map(
reset => rst,
inner_rst => rst_cnt,
clock => clk,
cnt => t);
process(clk,rst)
begin
if (rst='1') then
pr_state<= A;
elsif (rising_edge(clk)) then
pr_state<=nx_state;
end if;
end process;
process(x,t,pr_state)
begin
case pr_state is
when A =>
y<='0';
rst_cnt<='1';
if (x='1') then
nx_state<= B;
else
nx_state<= A;
end if;
when B =>
y<='0';
rst_cnt<='0';
if (x='0' and t=(T1-1)) then
nx_state<= C;
end if;
if ((x='0' and t<(T1-1)) or (x/='0' and t<(T2-1))) then
nx_state<= B;
end if;
if (t=(T2-1)) then
nx_state<= A;
end if;
when C =>
y<='1';
rst_cnt<='0';
if (t=(T2-1)) then
nx_state<= A;
else
nx_state<= C;
end if;
end case;
end process;
end Behavioral;
Thank you in advance
I think you can't avoid at least a single clock delay. The reason is that you have to remember your current state. For saving the state you have to use a register, which will cause the delay. Otherwise you can avoid this by using an asynchronous state machine, but then you will have to be careful about your input.
A usual Moore's state machine has:
\/-------------|
input --> transition logic --> state memory --> output logic --> output
^-clk ^-rst ^-enable
This structure can be nicely expressed by 3 processes. For trying to reduce the latency, you can connect the output logic directly to the transition logic, but you might need a register after that anyway.
For details see this page i googled, it is pretty detailed.