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.
Related
I'm trying to implement a morse code display on my FPGA. I've written a lot of code but I keep getting the same error message. Before I get into that though, please take a look at the assignment. To be clear, I'm not asking for someone to do the assignment for me. I just need help debugging my code.
"Part IV
In this part of the exercise you are to implement a Morse-code encoder using an FSM. The Morse code uses patterns of short and long pulses to represent a message. Each letter is represented as a sequence of dots (a short
pulse), and dashes (a long pulse). For example, the first eight letters of the alphabet have the following representation:
A • —
B — • • •
C — • — •
D — • •
E •
F • • — •
G — — •
H • • • •
Design and implement a Morse-code encoder circuit using an FSM. Your circuit should take as input one of
the first eight letters of the alphabet and display the Morse code for it on a red LED. Use switches SW2−0 and
pushbuttons KEY1−0 as inputs. When a user presses KEY1, the circuit should display the Morse code for a letter
specified by SW2−0 (000 for A, 001 for B, etc.), using 0.5-second pulses to represent dots, and 1.5-second pulses
to represent dashes. Pushbutton KEY0 should function as an asynchronous reset.
Here is the code I have written:
module part4 (SELECT, button, CLOCK_50, RESET, led);
input [2:0]SELECT;
input RESET, button, CLOCK_50;
output reg led=0;
reg [26:0] COUNT=0; //register that keeps track of count
reg [1:0] COUNT2=0; //keeps track of half seconds
reg halfsecflag=0; //goes high every time half second passes
reg dashflag=0; // goes high every time 1 and half second passes
reg [3:0] code; //1 is dot and 0 is dash. There are 4 total
reg [1:0] c3=2'b00; //keeps track of the index we are on in the code.
reg [2:0] STATE; //register to keep track of states in the state machine
wire done=0; //a flag that goes up when one morse pulse is done.
reg ending=0; //another flag that goes up when a whole morse letter has
flashed
reg [1:0] length; //This is the length of the morse letter. It varies from 1
to 4
wire i; // if i is 1, then the state machine goes to "dot". if 0 "dash"
assign i = code[c3];
assign done= (halfsecflag)&&(~ending)&&~led;
parameter START= 3'b000, DOT= 3'b001, DASH= 3'b010, DELAY= 3'b011, IDLE=
3'b100;
parameter A= 3'b000, B=3'b001, C=3'b010, D=3'b011, E=3'b100, F=3'b101,
G=3'b110, H=3'b111;
always #(posedge CLOCK_50 or posedge RESET) //making counter
begin
if (RESET == 1)
COUNT <= 0;
else if (COUNT==25'd25000000)
begin
COUNT <= 0;
halfsecflag <= 1;
end
else
begin
COUNT <= COUNT+1;
halfsecflag <=0;
end
end
always #(posedge CLOCK_50 or posedge RESET)
begin
if (RESET == 1)
begin
COUNT2 <= 2'd00;
dashflag<=1'b0;
end
else if ((COUNT2==2)&&(halfsecflag))
begin
COUNT2 <= 2'd0;
dashflag<=1'b1;
end
else if ((halfsecflag)&&(COUNT2!=2))
begin
COUNT2<= COUNT2+2'd1;
dashflag<=1'b0;
end
end
always #(posedge button or RESET) //asynchronous reset
begin
STATE<=IDLE;
end
always#(*) begin //State machine
case (STATE)
START: begin
led <= 1;
if (i) STATE <= DOT;
else STATE <= DASH;
end
DOT: begin
if (halfsecflag && ~ending) STATE <= DELAY;
else if (ending) STATE<= IDLE;
else STATE<=DOT;
end
DASH: begin
if ((dashflag)&& (~ending))
STATE <= DELAY;
else if (ending)
STATE <= IDLE;
else STATE <= DASH;
end
DELAY: begin
led <= 0;
if ((halfsecflag)&&(ending))
STATE<=IDLE;
else if ((halfsecflag)&&(~ending))
STATE<=START;
else STATE <= DELAY;
end
IDLE: begin
c3<=2'b00;
if (button) STATE<=START;
STATE<=IDLE;
end
default: STATE <= IDLE;
endcase
end
always #(posedge button)
begin
case (SELECT)
A: length<=2'b01;
B: length<=2'b11;
C: length<=2'b11;
D: length<=2'b10;
E: length<=2'b00;
F: length<=2'b11;
G: length<=2'b10;
H: length<=2'b11;
default: length<=2'bxx;
endcase
end
always #(posedge button)
begin
case (SELECT)
A: code<= 4'b0001;
B: code<= 4'b1110;
C: code<= 4'b1010;
D: code<= 4'b0110;
E: code<= 4'b0001;
F: code<= 4'b1011;
G: code<= 4'b0100;
H: code<= 4'b1111;
default: code<=4'bxxxx;
endcase
end
always #(*)
begin
if (c3==length)
begin
c3=2'b00; ending<=1;
end
else if (done)
c3= c3+2'b01;
end
endmodule
The error code I keep getting is Error (10028): Can't resolve multiple constant drivers for net "c3[1]" at part4.v(68)
Also in green above this error code, it says inferred latch a few different times. This doesn't seem good! Can you take a look at my code and see if you can figure out why I'm getting this error message?
Update: This is not a duplicate of my previous question. Before I was asking for tips on how to create a delay using verilog. In this question I was asking for help debugging my code. The error message I got was not making sense to me. I looked at the other answers on stack exchange regarding that error code but none of them made sense to me.
You're missing a couple of (very) basic principles - you can't code hardware without them. Note that I'm using VHDL terminology here ('signal'/'process'/etc), but the idea is exactly the same in Verilog, if a little harder to find the right words.
You can only drive a signal from a single process (if you're synthesising, anyway), or you get multiple drivers. Look at c3 - where is it driven? You're driving it from 2 combinatorial always blocks. The same is true of STATE.
In a combinatorial process, if you read one of your output (driven) signals before you assign to it (drive it), you're inferring memory. This is where your inferred latches are coming from. Think about it - a process "wakes up" when something it is sensitive to changes/fires. If it then reads the value of a signal that it itself drives, this must mean that the signal has to be recorded somewhere in order for it have a current value; it must know what value it had when the process last completed. This is what memory means. You do this for both STATE and c3 (if(c3==length) must read c3, case STATE must read state).
You fix (1) by recoding so that all signals are driven from only one 'owner' process.
Fixing (2) is more difficult. In a combinatorial process (alway #*) make sure you either give all outputs default values first, or make sure that you never read anything before you've written it, so that there's no confusion about whether memory is inferred. Your combinatorial process to derive STATE is wrong. You read STATE, and then write it. You should have 2 signals: current state, and next state. You should read the current state, and create the next one.
You've got other problems, but you need to fix those 2 first.
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.
I have an example code about T-Bird Tail Lights, and it's passing states to the next module. I modified the code that it doesn't have to pass the state, but it seems the output is not changing(stays 000 all the time)
Here's my modified code:
module TBird(E,B,L,R,int_clk,L_Light,R_Light);
input E,B,L,R,int_clk;
output [2:0] L_Light;
output [0:2] R_Light;
reg [19:0] C;
wire int_clk;
One_Side U1 (E,B,R,int_clk,R_Light);
One_Side U2 (E,B,L,int_clk,L_Light);
endmodule
module One_Side(e,b,t,clk,light_eb);
input e,b,t,clk;
output reg [2:0] light_eb=3'b000;
always #(posedge clk or e or b or t)
begin
case ({e,b,t})
3'b000: light_eb=3'b000;
3'b0?1: begin
if (light_eb==3'b000) begin
light_eb=3'b001;
end else if (light_eb==3'b001) begin
light_eb=3'b011;
end else if(light_eb==3'b011) begin
light_eb=3'b111;
end else begin
light_eb=3'b000;
end
end
3'b?10: light_eb=3'b111;
3'b10?: begin
if (light_eb!==(3'b000|3'b111)) begin
light_eb=3'b000;
end
light_eb=~light_eb;
end
3'b111: begin
if (light_eb==3'b000) begin
light_eb=3'b001;
end else if (light_eb==3'b001) begin
light_eb=3'b011;
end else if(light_eb==3'b011) begin
light_eb=3'b111;
end else begin
light_eb=3'b000;
end
end
endcase
end
endmodule
I have had some experience in Java, but I don't know much about verilog, so I don't even know where goes wrong(in Java, eclipse has break points and debugger and things like that,) any suggestions/recommendations are appreciated.
A couple of mistakes in the testbench and design. Listed down as follows:
You have not provided any toggling on clock signal. So there will not be any posedge of clock detected. There are many ways for generating clock, one of them is as follows:
always #5 clk = ~clk;
Using a reset signal in design is good practice. Apply reset from testbench to set all the internal registers in design to their initial values.
The most important thing is you have not provided any input stimulus to the design. Any random stimulus must be applied to get the output. You have to provide some inputs to get the output, henceforth your output is x.
initial
begin
forever
begin
#6;
E = $random;
B = $random;
R = $random; // and so on...
end
end
Use of nonblocking (<=) assignments in design is a good coding practice. Also, donot mix blocking (=) and nonblocking (<=) assignments.
a = b; // never use this in sequential circuit.
a<= b; // use this in sequential circuit.
I have made a somewhat valid testbench for your design, have a look at EDAPlayground link.
Must refer to this, this, and this links for understanding general testbench architecture.
I am modifying a simple keyboard interface I found on the net to my use. The idea is whenever there is a new scancode, it will make the output named "Scan_Dav" go high, and then go low. So when I direct Scan_Dav to another module as a clock, that module's clock will have a rising edge whenever a new ScanCode is pressed. Is there any error in my way of thinking? Because I tried it and directed the scancode and scan_dav to the rest of my project -which writes letters side by side with the given scancodes and shows them on seven segment display- the displayed text had 2 of each character ( i.e. when I write FLY the text was like FFLLYY). If there is no errors, I will share my code and ask you why it is not working. Thanks :)
EDIT: This is where the shifting is done according to values of Scan_Dav
signal bytes : std_logic_vector(63 downto 0);
signal Scan_Dav_Sync: std_logic_vector(1 downto 0):="00";
signal Previous_Scan_Dav: std_logic:='0';
begin
process (clk) begin --, Scan_Dav) begin
if rising_edge(clk) then
Scan_Dav_Sync(0) <= Scan_Dav;
Scan_Dav_Sync(1) <= Scan_Dav_Sync(0);
Previous_Scan_Dav <= Scan_Dav_Sync(1);
if (Previous_Scan_Dav = '0') and (Scan_Dav_Sync(1) = '1') then
bytes <= bytes (bytes'high-8 downto 0) & Data_in;
end if;
end if;
end process;
This is where Scan_Dav comes from, the code is taken from here:
(You may ignore the filtering part)
Architecture Behavioral of KeyboardController is
signal PS2_Datr : std_logic;
subtype Filter_t is std_logic_vector(7 downto 0);
signal Filter : Filter_t;
signal Fall_Clk : std_logic;
signal Bit_Cnt : unsigned (3 downto 0);
signal Scan_DAVi : std_logic;
signal S_Reg : std_logic_vector(8 downto 0);
signal PS2_Clk_f : std_logic;
Type State_t is (Idle, Shifting);
signal State : State_t;
signal Scan_Code : std_logic_vector(7 downto 0);
signal Flag : std_logic:='0';
begin
process (Clk,Reset)
begin
if Reset='1' then
PS2_Datr <= '0';
PS2_Clk_f <= '0';
Filter <= (others=>'0');
Fall_Clk <= '0';
elsif rising_edge (Clk) then
PS2_Datr <= PS2_Data and PS2_Data; -- also turns 'H' into '1'
Fall_Clk <= '0';
Filter <= (PS2_Clk and PS2_CLK) & Filter(Filter'high downto 1);
if Filter = Filter_t'(others=>'1') then
PS2_Clk_f <= '1';
elsif Filter = Filter_t'(others=>'0') then
PS2_Clk_f <= '0';
if PS2_Clk_f = '1' then
Fall_Clk <= '1';
end if;
end if;
end if;
end process;
-- This simple State Machine reads in the Serial Data
-- coming from the PS/2 peripheral.
process(Clk,Reset)
begin
if Reset='1' then
State <= Idle;
Bit_Cnt <= (others => '0');
S_Reg <= (others => '0');
Scan_Code <= (others => '0');
Scan_Out <= (others => '0');
Scan_Davi <= '0';
elsif rising_edge (Clk) then
-- if Scan_Davi = '1' then
-- Scan_Davi <= '0';
-- end if;
case State is
when Idle =>
Bit_Cnt <= (others => '0');
-- note that we dont need to clear the Shift Register
if Fall_Clk='1' and PS2_Datr='0' then -- Start bit
State <= Shifting;
end if;
when Shifting =>
if Bit_Cnt >= 9 then
if Fall_Clk='1' then -- Stop Bit
Scan_Code <= S_Reg(7 downto 0);
if (Flag = '1' and Scan_Code /= "11110000") then
--to ignore makecode
Scan_Out <= Scan_Code;
Flag <= '0';
Scan_Davi <= '1';
end if;
if (Flag = '0' and Scan_Code = "11110000") then
--to ignore F0
Flag <= '1';
Scan_Davi <= '0';
end if;
State <= Idle;
end if;
elsif Fall_Clk='1' then
Bit_Cnt <= Bit_Cnt + 1;
S_Reg <= PS2_Datr & S_Reg (S_Reg'high downto 1); -- Shift right
end if;
when others => -- never reached
State <= Idle;
end case;
end if;
end process;
Scan_DAV <= Scan_DAVi;
end Behavioral;
UPDATE: The only problem that remains is the delayed display and shifting of the letter and the text. While writing VHDL, I get nothing after pressing V, then I get V when I press H and it goes like that. The last letter does not appear until another key is pressed.It seems to be an issue about Scan_Dav, yet I can not resolve what it is. Any help will be appreciated.
Driving a clock input from logic output is generally bad practice (and some FPGA fabrics will not allow it at all). Clocks run best when sourced from dedicated clock logic inside the part, and good designs should minimize the number of clocks. Ideally you'd have only one, but that's not always possible.
Instead of running a clock input from logic, consider running everything off of one clock and use "enables" to activate the logic only when needed. In this case, you would detect the rising-edge transition of scan_dav inside of the downstream module and only react when that transition occurs. The detection logic would run off of the same clock as the scan_dav module.
I don't think this explains why you're seeing double characters, you would need to post some code to analyze. However, I would recommend that you re-tool to not drive clocks from logic.
If I see it right you avoid the F0 when you release the Key but you do not filter the second scancode.
It's always like this
Scancode --- press Key
F0 --- relesase Key
Scancode
on some Keys (e.g ALT GR) you can get an E0 too.
It not complete description but the most importand thinks are shown.
http://en.wikipedia.org/wiki/Scancode
This would lead to the descripted problem. FLY -> FFLLYY.
I would like to delay a signal several cycles in vhdl, but I have problems using how to delay a signal for several cycles in vhdl
Wouldn't I need a registered signal? I mean, something like:
a_store and a_store_registered would be std_logic_vector(cycles_delayed-1 downto 0)
process(clk)
begin
if rising_edge(clk) then
a_store_registered <= a_store;
end if;
end process;
a_out <= a_store_registered(cycles_delayed-1);
process(a_store_registered, a)
begin
a_store <= a_store_registered(size-2 downto 0) & a;
end process;
The solution you link to is a registered signal - the very act of writing to a signal inside a process with a rising_edge(clk) qualifier creates registers.
An even simpler implementation of a delay-line can be had in one line of code (+ another one if you want to copy the high bit to an output)
a_store <= (a_store(a_store'high-1 downto 0) & a) when rising_edge(clk);
a_out <= a_store(a_store'high);
Not sure why I didn't mention this in my answer to the linked question!
I am not sure why you are approaching the problem as you are; there is no need for a second process here. What is wrong with the method suggested in the linked question?
if rising_edge(clk) then
a_store <= a_store(store'high-1 downto 0) & a;
a_out <= a_store(a_store'high);
end if;
In this case your input is a and your output is a_out. If you want to make the delay longer, increase the size of a_store by resizing the signal declaration.
If you want to access the intermediate signal for other reasons, you could do this:
a_store <= a_store_registered(cycles_delayed-2 downto 0) & a;
process(clk)
begin
if rising_edge(clk) then
a_store_registered <= a_store;
end if;
end process;
a_out <= a_store_registered(cycles_delayed-1);
Remember that you can use the foo'delayed(N ns) attribute or foo <= sig after N ns in simulations.