Blocking Assignments on SIGNALS in VHDL - vhdl

I am making an FSM with VHDL. The simplest possible when valid = 1 change from stateA to stateB.
The confusing part is the rising edge selected by the blue rectangular. When valid = '1'. At the first rising edge, the state will be calculated to be B but it won't take effect until the next rising edge BUT what happened that it took effect at the FIRST rising edge.
Because the change in the state from A to B should affect other parts ( parallel process ) in the design in the NEXT cycle. From the waveform, If valid = '1' just before CLK_1.
At, CLK_1 all other processes should see state = A | waveform correct
output
state = A
enteredlastcycle = 0
At, CLK_2 all processes start seeing state = B. another parallel
process checks if state = B then it drives ENTERED_STATEB_LASTCYCLE to
be 1 waveform correct output
state = B
enteredlastcycle = 0
Then at CLK_3, waveform correct output
state = B
enteredlastcycle = 1
Do I misunderstand something?
Library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use work.KDlib.all;
entity nearestPoint is
generic ( ARRAY_WIDTH : integer := 8);
port (
clk: in std_logic;
reset: in std_logic;
inpoint: in kdvector;
valid: in std_logic;
finished: buffer std_logic
);
end nearestPoint;
architecture behave of nearestPoint is
signal state: two_state_type;
signal stateB_entered_lastCycle: std_logic;
begin
process ( clk )
begin
if ( reset = '1' ) then
elsif ( rising_edge(clk) ) then
case state is
when stateA =>
if ( valid = '1' ) then
state <= stateB;
end if;
when stateB =>
when others =>
end case;
end if;
end process;
process(clk)
begin
if ( reset = '1' ) then
elsif ( clk = '1' ) then
case state is
when stateA =>
when stateB =>
stateB_entered_lastCycle <= '1';
when others =>
end case;
end if;
end process;
end behave;

I will give you an explanation through a digital circuit prism. It is a way of thinking that you have to keep in mind when you develop VHDL.
Your valid is at 1 before the clock edge. You are in simulation so you can imagine that all your computations are instant. At the input of your flipflop the new value of your state is already calculated.
I am used to code with only one sequential process and one or more combinational process. Maybe you will understand better with this code with same functionnality than yours (a bit simplified) :
SEQ : process(clk, rst)
begin
if rst = '1' then
current_state <= '0';
elsif rising_edge(clk) then
current_state <= next_state;
end if;
end process SEQ;
Circuit corresponding to this code :
COMB : process(current_state, valid)
begin
next_state <= current_state; -- Default value to ensure that next_state will always be affected
if current_state = '0' and valid = '1' then
next_state <= '1';
end if;
end process COMB;
Circuit correspondint to this code :
If we consider that when valid changes next_state is refreshed instant, current_state (state in your code) goes high on the very next clock rising edge.
Hope you will understand, if you need more precision, don't hesitate to ask, I can edit my post or answer in comments.
Important note : If you have an asynchronous reset in your sequential process, it has to be in sensitivity list.

VHDL has no concept of blocking/non-blocking assignments. There are signals and variables and they are assigned differently.
In your case, you need to remember that simulation runs on a series of delta cycles. 1 delta is an infinitely small space of time, but they happen sequentially. A signal assignment doesn't take effect until the end of the delta, so state = B in the delta cycle after the rising edge of the clock. The 2nd process is sensitive only the clock, so it cannot update stateB_entered_lastcycle until the clock rises again.

Related

How do I correctly implement a Finite-State Machine into VHDL without taking in multiple inputs from Basysy3 FPGA

I am new to VHDL and I am attempting to implement the following state machine into VHDL (state diagram provided below). When I press a button on my Basys3 FPGA board( P input) the output is a random state. I suspect this is because the clock is going through many cycles during a single press so more than 1 input is being taken in from a single press but I am unsure. Is there anything I can do to fix this. I want to be able to press button P and the states change one at a time.
library IEEE;
USE ieee.std_logic_1164.all;
ENTITY trasher is
PORT (
clock : IN STD_LOGIC;
P : IN STD_LOGIC;
reset : IN STD_LOGIC;
LED3, LED1,LED2,LED0 : OUT STD_LOGIC);
END ENTITY;
-- Architecture definition for the SimpleFSM entity
Architecture RTL of trasher is
TYPE State_type IS (A, B, C, D); -- Define the states
SIGNAL State : State_Type; -- Create a signal that uses
-- the different states
BEGIN
PROCESS (clock, reset)
BEGIN
IF (reset = '1') THEN -- upon reset, set the state to A
State <= A;
ELSIF rising_edge(clock) THEN -- if there is a rising edge of the
-- clock, then do the stuff below
-- The CASE statement checks the value of the State variable,
-- and based on the value and any other control signals, changes
-- to a new state.
CASE State IS
-- If the current state is A and P is set to 1, then the
-- next state is B
WHEN A =>
IF P='1' THEN
State <= B;
END IF;
-- If the current state is B and P is set to 1, then the
-- next state is C
WHEN B =>
IF P='1' THEN
State <= C;
END IF;
-- If the current state is C and P is set to 1, then the
-- next state is D
WHEN C =>
IF P='1' THEN
State <= D;
END IF;
-- If the current state is D and P is set to 1, then the
-- next state is B.
-- If the current state is D and P is set to 0, then the
-- next state is A.
WHEN D=>
IF P='1' THEN
State <= B;
ELSE
State <= A;
END IF;
WHEN others =>
State <= A;
END CASE;
END IF;
END PROCESS;
-- Decode the current state to create the output
-- if the current state is D, R is 1 otherwise R is 0
LED0 <= '1' WHEN State=A ELSE '0';
LED1 <= '1' WHEN State=B ELSE '0';
LED2 <= '1' WHEN State=C ELSE '0';
LED3 <= '1' WHEN State=D ELSE '0';
END rtl;
Do not use directly the input from your press-button. What you need to feed your state machine is the output of a rising edge detector of P, not P itself.
Moreover P is not synchronous with your master clock and there is thus a risk of meta-stability. Last but not least, if it bounces, you will get several value changes instead of just one. To solve the meta-stability issue you need a re-synchronizer, which is just a shift register. And you can also use it to generate an intermediate signal that is asserted high during only one clock period when the button is pressed, that is, the rising edge detector you need for your state machine. Example with 3-stages:
signal sync: std_ulogic_vector(0 to 2);
signal button_pressed: std_ulogic;
...
process(clock, reset)
begin
if reset = '1' then
sync <= (others => '0');
elsif rising_edge(clock) then
sync <= P & sync(0 to 1);
end if;
end process;
button_pressed <= sync(1) and (not sync(2));
Stages 1 and 2 of sync are safe to use because they have already been resynchronized (assuming 2 stages are enough for your target technology and mean time between failures; read something about meta-stability, maybe, if you don't understand this).
When the button is pressed, ones are shifted in sync. After two clock periods sync = "110" so button_pressed is asserted high. One clock period later sync = "111" and button_pressed is de-asserted. button_pressed is thus a one-clock-period-only indicator that the button was pressed. You can use it as an input of your state machine.
The second problem comes from the way press-buttons work. If your prototyping board does not already debounce its press-buttons it can be that, when the button is pressed, your P input oscillates several times between 0 and 1 before stabilizing to 1. Same when the button is released. As this is sometimes not the case do some tests before implementing a debouncer. For instance, count the number of times button_pressed is asserted high and send this to your LEDs:
signal cnt: u_unsigned(3 downto 0);
...
process(clock, reset)
begin
if reset = '1' then
cnt <= (others => '0');
elsif rising_edge(clock) then
cnt <= cnt + button_pressed;
end if;
end process;
LED0 <= std_logic(cnt(0));
LED1 <= std_logic(cnt(1));
LED2 <= std_logic(cnt(2));
LED3 <= std_logic(cnt(3));
If your button bounces you should sometimes see more than one increment when you press it. It will be time to search a bit about debouncing and, if needed, to ask a new question.

VHDL finite state machine counter with start

i pretty new of vhdl and i'm trying to learn how to do a FSM with vhdl.
At moment i need a code that after a fixed count value, it give me back a pulse, in order to start a second FSM block. (I have a recurring signal every 100 kHz, i need to count it and release this signal after a fixed number of counts).
Actually it work as free run, every time that it see this signal, it start to count, but realy i want to add a "start" signal, so it must start to count this signal after it see this start signal.
at moment my working code is:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;
entity counter is
Port (
signal_in : in STD_LOGIC := '0'; --segnale di start
clk : in STD_LOGIC; --clock di ingresso
reset : in STD_LOGIC; --ff reset
signal_out: out STD_LOGIC; --gate in uscita
count_val: in std_logic_vector (7 downto 0);
start : in STD_LOGIC := '0'
);
end counter;
architecture behavioral of counter is
type state_type is (idle, count_up);
signal state : state_type;
begin
process (reset, clk, signal_in, start)
variable index : integer :=0;
variable countlen: integer;
variable count_v: std_logic;
variable countlen2 : std_logic;
begin
countlen := to_integer(unsigned(count_val))-1;
if reset = '1' then
count_v := '0';
index := 0;
state <= idle;
else
--if start = '1' and
--if rising_edge(clk) then
if rising_edge(signal_in) then
case state is
when idle =>
count_v :='0';
index := 0;
if (signal_in = '1') then
state <= count_up;
else
state <= idle;
end if;
when count_up =>
if(index < countlen) then
state <=count_up;
index := index + 1;
elsif
index = countlen then
count_v := '1';
state <=idle;
end if;
when others => null;
end case;
end if;
end if;
signal_out <= count_v;
end process;
end Behavioral;
Any attempt to work with cose with "start = 1" will stop the count.
Please some one have some suggestion?
Kind REgards
Fulvio
Welcome om StackOverflow. Your specification is not 100% clear. What difference do you make between signal_in and start? According to your code and to your explanations, they both seem to act as a starter.
Moreover, there are several strange things with your code:
your process seems to be a synchronous one, with asynchronous reset. Its sensitivity list should contain only the clock and the reset. And its body should be:
process(clk, reset)
<variable declarations>
begin
<NOTHING HERE>
if reset = '1' then
<reset code>
elsif rising_edge(clk) then
<regular code>
end if;
<NOTHING HERE>
end process;
you are using signal_in as a clock and as a logic signal. This is extremely strange. Moreover, your if (signal_in = '1') then is always true (in the synthesis semantics) and thus useless.
You are initializing variables at declaration (index). This is not supported by some synthesizers and hardware targets. Moreover, even when supported, it works only at power up. If:
you intend to synthesize your code,
you want it to be portable across synthesizers and hardware targets,
you want to re-initialize signal and variables not only at power up but also when a reset input is asserted,
prefer a real explicit reset, instead, and guarantee that it is always asserted after power up (or at the beginning of a simulation) for proper first initialization.
you declare variable index with a full integer range, that is, 32 bits minimum, while 8 bits would suffice. This is a potential waste of hardware resources.
It is difficult to propose a solution without a clear and complete specification but assuming you want to count only after start has been asserted and only when signal_in is asserted, the following may be a starting point:
process (clk, reset)
variable index: natural range 0 to 255;
begin
if reset = '1' then
state <= idle;
signal_out <= '0';
index := 0;
elsif rising_edge(clk) then
case state is
when idle =>
signal_out <= '0';
index := 0;
if start = '1' then
state <= count_up;
end if;
when others =>
if signal_in = '1' then
if index = to_integer(unsigned(count_val)) - 1 then
state <= idle;
signal_out <= '1';
else
index := index + 1;
end if;
end if;
end case;
end if;
end process;
Note that this is really synchronous of your clock clk. I suspect that you made a very common mistake: as you wanted to increment your counter when signal_in is asserted you decided more or less to use signal_in as a clock. This is not a real synchronous and safe design. In a real safe synchronous design you do not use logic signals as clocks. You have well identified clocks and you use only these as clocks. In your case there is one single clock: clk. If you want to do something synchronously when a logic signal is asserted, wait for the rising edge of your clock and then test the logic signal and take appropriate actions.
thanks for your support.
Yes the point is that i need to "decimate" (or count) a signal.
This signal had a width of 50-100ns and it repeat itself with a frequency of 100 kHz.
so in my mind, this signal will go in to "signal in". My FPGA is an Actel proasic3 with a clock of 40 MHz.
In my setup this signal will be always on, but i don't want that my FSM will start to count as it see the first "signal in" but only when i send a "start" signal for the number of count that i indicate. (Realy they ask to me the possibility to decimate this signal up to 65000 count, so for sure i need to use a 16bit vector instead of 8bit).
The async reset is here "just in case" i need to reset the whole fsm in the middle of some data record.
Hope to be more clear now what this code should do.
For Old fart, yes indeed all my signal coming outside the fpga will be first synchronized with a simple 2 ff synchronizer with the FPGA clock

how to avoid delay in the output of simple process statement in VHDL

i am a beginner in VHDL. i want ot know why there is a delay of one cycle in the following code.and how to avoid it..at the same time in verilog the statement always #(posedge clk) dont have any delay.. how to do the same in VHDL
library IEEE;
use IEEE.std_logic_1164.all;
-- entity
entity t_ff_s is
port ( T,S,CLK : in std_logic;
Q : out std_logic);
end t_ff_s;
-- entity
architecture my_t_ff_s of t_ff_s is
signal t_tmp : std_logic; -- intermediate signal declaration
begin
tff: process (S,rising_edge(clk))
begin
if (S = '0') then
t_tmp <= '1';
--elsif (rising_edge(CLK)) then
else
t_tmp <= T XOR t_tmp; -- temp output assignment
end if;
end process tff;
Q <= t_tmp; -- final output assignment
end my_t_ff_s;
Sensitivity lists in VHDL don't take an edge specification like in Verilog. VHDL is more flexible in that you can freely use the 'event signal attribute anywhere within a process to implement edge triggered behavior. You can mix level and edge sensitive logic without resorting to split blocks/processes or hacks like negedge for resets. Function calls like rising_edge(clk) (which implements a test for clk'event) are not permitted in a sensitivity list. It only contains signal names. Your code won't compile as is.
If some other syntactically correct version of your code compiles cleanly, the delays you see are artifacts of the simulation model or having a broken sensitivity list. If you want a synchronous clock driven process then you only need the clock signal and possibly an asynchronous reset in the sensitivity list.
Consider the following process:
tff: process(S, clk)
begin
if S = '0' then -- Asynchronous reset (level sensitive)
t_tmp <= '1';
elsif rising_edge(clk) then -- Synchronous logic (edge sensitive)
t_tmp <= T xor t_tmp;
end if;
end process;
Q <= t_tmp;
This process executes when an event occurs on S or clk. If S is '0' then the reset condition is executed with priority over the elsif clause (clk is a don't-care). The assignment to t_tmp takes effect on the next delta cycle which is still the same as the current simulation time. Otherwise, if rising_edge(clk) evaluates to true then an event occurred on clk and it's state changed from '0' (or 'L') to '1' (or 'H') indicating that the event was a rising edge. The synchronous assignment takes place and the new xored t_tmp takes effect on the next delta cycle. Changes in T don't cause the process to execute since it isn't (and shouldn't be) in the sensitivity list.
Because there is no unconditional else clause the t_tmp signal retains its last assigned value if both of the two if conditions are false. It will change the next time there is an event on S or clk that causes a new assignment to t_tmp. This will either be the next clock edge or a re-application of asynchronous reset.
The assignment to Q is continuous and is effectively the same as a process with t_tmp in its sensitivity list. As a consequence, the assignment to Q takes place a delta cycle after events on t_tmp which is two delta cycles after the rising edge. If Q is feeding into logic that updates earlier than the second delta cycle of an edge, it will appear to take an extra clock cycle for it to propagate.
The behavior surrounding delta cycles can sometimes create confusing results when inspecting waveforms. You may have a rising edge that should capture a data input that appears to transition simultaneously on the same time step when, in fact, the data is transitioning on a later delta cycle and will only be captured on the next clock edge.
Similarly, if you construct a simple gated clock without any time delay, its edges will occur at the same time but on later delta cycles than the ungated version of the clock. Data driven from the "earlier" ungated clock will be captured by the gated logic a clock cycle earlier than expected as a result. Data driven the other direction will appear to have an unexpected delay by a clock cycle.
It isn't clear what is causing the problem you see without more information on how you're driving the S, T, and clk signals but it is likely connected to the delta cycle behavior of the simulation engine in some way.
The problem
A little more succinctly than Kevin, rising_edge is an expression and not a signal, a sensitivity list requires a named signal, a transaction on which you resume execution of a suspended process. Put the elsif back in and have only S and clk in the sensitivity list.
Note that because t_tmp isn't in the sensitivity list, you won't see Q follow t_tmp until the next clock event causing the delay you noted.
The fixed syntax process:
tff: process (S,clk) -- was (S, risingedge(CLK)), a syntax error)
begin
if (S = '0') then
t_tmp <= '1';
elsif (rising_edge(CLK)) then -- put back
-- else
t_tmp <= T XOR t_tmp; -- temp output assignment
end if;
Q <= t_tmp; -- final output assignment
end process tff;
Which shows the delay between t_tmp and Q:
(clickable)
Fix it by making Q a concurrent signal assignment
To cure the half clock delay you could make the assignment to Q a concurrent signal assignment statement (move it outside of the process).
tff:
process (S, clk)
begin
if S = '0' then
t_tmp <= '1';
elsif rising_edge(clk) then
t_tmp <= T xor t_tmp;
end if;
end process;
Q <= t_tmp; -- concurrent signal assignment
Which gives:
(clickable)
And you can see above that t_tmp and Q are now in phase.
Fix it by making t_tmp a variable
You could also declare t_tmp as a variable in process dff instead of a signal and switching assignments to it as variable assignments will also cure the one clock delay between t_tmp and Q.
tff:
process (S, clk)
variable t_tmp: std_logic;
begin
if S = '0' then
t_tmp := '1';
elsif rising_edge(clk) then
t_tmp := T xor t_tmp;
end if;
Q <= t_tmp;
end process;
Which shows:
(clickable)
And ghdl using gtkwave doesn't output variables or show delta cycles. You can see Q occurs on the rising edge of the clock.
Making t_tmp a variable also has the effect of eliminating a delta cycle between a transaction on t_tmp and a transaction on Q.
Eliminating delta cycles makes your model execute faster (while occurring at the current simulation time). Signal assignments don't take effect while any process is executing and variable assignments take effect immediately.
Fix it by adding t_tmp to the sensitivity list
And alternatively you could just add t_tmp to the sensitivity list (along with S and clk).
tff:
process (S, clk, t_tmp)
begin
if S = '0' then
t_tmp <= '1';
elsif rising_edge(clk) then
t_tmp <= T xor t_tmp;
end if;
Q <= t_tmp;
end process;
(clickable)
And this is slower than all the rest of the fixes because the if statement is executed each time t_tmp has an event as well as S or CLK. rising_edge is a function call which dynamically elaborates it's interface list, a significant simulator performance penalty particularly if you use a lot of these primitives.
These were done with a test bench:
library IEEE;
use IEEE.std_logic_1164.all;
-- entity
entity t_ff_s is
port ( T,S,CLK : in std_logic;
Q : out std_logic);
end entity t_ff_s;
architecture my_t_ff_s of t_ff_s is
signal t_tmp : std_logic; -- intermediate signal declaration
begin
tff: process (S,clk) -- was (S, risingedge(CLK)), a syntax error)
begin
if (S = '0') then
t_tmp <= '1';
elsif (rising_edge(CLK)) then -- put back
-- else
t_tmp <= T XOR t_tmp; -- temp output assignment
end if;
Q <= t_tmp; -- final output assignment
end process tff;
end my_t_ff_s;
architecture foe of t_ff_s is
signal t_tmp: std_logic;
begin
tff:
process (S, clk)
begin
if S = '0' then
t_tmp <= '1';
elsif rising_edge(clk) then
t_tmp <= T xor t_tmp;
end if;
end process;
Q <= t_tmp; -- concurrent signal assignment
end architecture;
architecture fie of t_ff_s is
begin
tff:
process (S, clk)
variable t_tmp: std_logic;
begin
if S = '0' then
t_tmp := '1';
elsif rising_edge(clk) then
t_tmp := T xor t_tmp;
end if;
Q <= t_tmp;
end process;
end architecture;
architecture fee of t_ff_s is
signal t_tmp: std_logic;
begin
tff:
process (S, clk, t_tmp)
begin
if S = '0' then
t_tmp <= '1';
elsif rising_edge(clk) then
t_tmp <= T xor t_tmp;
end if;
Q <= t_tmp;
end process;
end architecture;
library ieee;
use ieee.std_logic_1164.all;
entity test_tff is
end entity;
architecture foo of test_tff is
signal CLK: std_logic := '0';
signal T: std_logic := '0';
signal S: std_logic := '0';
signal Q: std_logic;
component t_ff_s is
port (
signal CLK: in std_logic;
signal T: in std_logic;
signal S: in std_logic;
signal Q: out std_logic
);
end component;
begin
DUT:
t_ff_s
port map (
T => T,
S => S,
CLK => CLK,
Q => Q
);
CLOCK:
process
begin
wait for 10 ns;
CLK <= not CLK;
if Now > 250 ns then
wait;
end if;
end process;
SET:
process
begin
S <= '0';
wait for 20 ns;
S <= '1';
wait;
end process;
TOGGLE:
process
begin
wait for 20 ns;
T <= '1';
wait for 60 ns;
T <= '0';
wait for 40 ns;
T <= '1';
wait;
end process;
end architecture;
configuration my_t_ff_s_config of test_tff is
for foo
for DUT: t_ff_s
use entity work.t_ff_s(my_t_ff_s);
end for;
end for;
end configuration;
configuration concurrent_config of test_tff is
for foo
for DUT: t_ff_s
use entity work.t_ff_s(foe);
end for;
end for;
end configuration;
configuration variable_config of test_tff is
for foo
for DUT: t_ff_s
use entity work.t_ff_s(fie);
end for;
end for;
end configuration;
configuration sensitivity_config of test_tff is
for foo
for DUT: t_ff_s
use entity work.t_ff_s(fee);
end for;
end for;
end configuration;
note the use of configuration
Using VHDL's configuration declarations to allow the use of multiple architectures. (my_t_ff_s - the original, foe - with concurrent assignment to Q, fie - with t_tmp as a variable and fee - with t_tmp in the sensitivity list).
And amazingly enough ghdl's analyzer was quite helpful getting the configuration declarations syntax right. Once you get the first one, the others are easy.
We tend to get rusty using configuration, it wasn't generally supported historically by synthesis tools. But then again, this is simulation for verification.
And for those with ghdl and gtkwave this is how it was done:
ghdl -a t_ff.vhdl
ghdl -e my_t_ff_s_config
ghdl -e concurrent_config
ghdl -e concurrent_config
ghdl -e sensitivity_config
ghdl -r my_t_ff_s_config --wave=test_tff_my_t_ff_s.ghw
ghdl -r concurrent_config --wave=test_tff_foe.ghw
ghdl -r variable_config --wave=test_tff_fie.ghw
ghdl -r sensitivity_config --wave=test_tff_fee.ghw
GHW is ghdl's native waveform dump file format, understood by gtkwave.
In gtkwave:
open t_ff_s.gtkw (reads in test_tff_my_t_ff_s.ghw)
(otherwise read in test_tff_my_t_ff_s.ghw and add signals to
waveform display, format the window, save save file to t_ff_s.gtkw)
new tab open test_tff_foe.ghw
read save file open t_ff_s.gtkw
new tab open test_tff_fie.ghw
read save file open t_ff_s.gtkw
new tab open test_tff_fee.ghw
read save file open t_ff_s.gtkw
Note ghdl doesn't save variable state or delta cycles, t_tmp won't show up in the waveform for test_ff_fie.ghw.

Strange spikes in the signal ModelSim VHDL

I'm working on a final project for school and this is my first time working with VHDL in Quartus and ModelSIM. It's supposed to be a control for an elevator that services three floors. I have these strange spikes in a few signals, and I can't seem to find their source.
The one problem I have is a spike in a signal that feeds to an up/down counter that shows the current floor. When it stops at a floor, it ends up counting one additional time and going either one floor too high or one floor too low, while the next floor display seems to show the same floor just fine until another floor is called. The next floor display comes from an FSM, while the current floor display is from an up/down counter.
It's a bit complex to post everything here, so I'm just going to post the waveform for now in case someone's come across this signal spike thing and it ends up being a minor error/easy fix.!
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
entity FSM_Elevador is
port (Up_Down, Igual, Reset, Clock: in std_logic;
Andar_Dif: out std_logic
);
end FSM_Elevador;
architecture FSM_beh of FSM_Elevador is
type Elev_States is (Start, Wait_State, Pulse_State);
signal Current_State, Next_State: Elev_States;
signal RST, CLK, Sig_Andar_Dif, Cont_Mesmo_Andar: std_logic;
begin
RST <= Reset;
CLK <= Clock;
process(RST, CLK)
begin
if RST = '0' then
Current_State <= Start;
elsif CLK'event and CLK = '1' then
Current_State <= Next_State;
end if;
end process;
process(Current_State, Igual)
begin
case Current_State is
when Start =>
Next_State <= Wait_State;
when Wait_State =>
if Igual = '1' then
Next_State <= Wait_State;
Sig_Andar_Dif <= '0';
else
Next_State <= Pulse_State;
Sig_Andar_Dif <= '1';
end if;
when Pulse_State =>
if Igual = '1' then
Sig_Andar_Dif <= '0';
Next_State <= Wait_State;
else
Sig_Andar_Dif <= '0';
Next_State <= Pulse_State;
end if;
end case;
end process;
Andar_Dif <= Sig_Andar_Dif;
end FSM_beh;
fru1tbat: I use the Elev_pulse to make the counter go up or down once, and yes it enters the counter as a clock. It was suggested by the professor.
Edit: sorry that was the wrong code earlier. Andar_Dif is what sends out the signal that ends up going to the component that has Elev_Pulse
Get rid of the reassignment of Clock and Reset to CLK and RST and just use the signals from the port directly. That is creating a delta cycle delay which is the cause of these kind of spikes. It looks like you have resets with different delays in the design which can also complicate matters. If the removal of the indirection doesn't clear things up you need to scrutinize the ordering of when events are generated on signals and when they are processed.
The outputs from your state machine are unregistered which is also potentially involved. Consider reworking the FSM so that all outputs are registered. This is a better design practice in general as it ensures that you don't have unknown combinational delays affecting downstream logic.

Make a signal wait until falling edge

I have this signal that should be zero until another signal Start = 0. How can I accomplish this? Here is the relevant code:
din<=0;
wait until falling_edge(start);
for i in 0 to 63 loop
wait until clk = '1' and clk'event;
if i = 0 then
Start <= '1','0' after clk_period;
end if;
if (i < 24) then
din <= 255;
elsif (i > 40) then
din <= 255;
else
din <= 0;
end if;
end loop;
wait;
I thought I could just make din = 0 until the falling edge of start but it stops at the rising edge of start. I want to start reading the din values when start =0. Before that din = 0.
Here is a pic:
EDIT: Actually I got it to start at the correct signal values but the dout value always has an intermediate value that isn't necessary. In this case its 78450. I know this has to do with the testbench code but I can't get it to just calculate the correct value at the correct time. What changes can be made to the code below to get rid of the intermediate value?
din<=0;
for i in 0 to 63 loop
wait until clk = '1' and clk'event;
if i = 0 then
Start <= '1','0' after clk_period;
elsif (i < 24) then
din <= 255;
elsif (i > 40) then
din <= 255;
else
din <= 0;
end if;
end loop;
First of all I assume (and hope) you are writing a testbench. If not, you should avoid using wait statements, as these have very limited support in synthesis tools.
Even in a testbench, it is best to use time-based wait or after statements only to generate the clock, and make all other signals dependent on an event (e.g. rising_edge(clk)). This avoids the problem of having multiple signals changing during delta cycle 0 along with the clock.
Consider the following code for a typical register:
process(clk) begin
if(rising_edge(clk)) then
a <= b;
end if;
end process;
and assume that clk and b are generated in a testbench as follows:
clk <= not clock after 1 ns;
process begin
b <= '1', '0' after 10 ns;
wait;
end process;
At time 0 delta 0, clk changes to '1' and b would change to '1'.
At time 0 delta 1, the register process would run since clk changed, and a would change to '1'.
No further sensitivity exists, so time would update to the next event at 1 ns.
At time 1 delta 0, clk changes to '0'.
At time 1 delta 1, the register process is run since clk changed, but nothing happens because rising_edge(clk) is false.
The above repeats for time 2-9 ns.
At time 10 delta 0, clk changes to '1' and b changes to '0'. Note that clk and b change in the same delta cycle.
At time 10 delta 1, the register process runs and a changes to '0'! As far as the result is concerned, this means that b changed before the rising clock edge!
Even if this behavior is understandable in this simple system, it can lead to some incredibly difficult to find simulation bugs. It is therefore better to base all signals off of the appropriate clock.
process begin
-- Initialize b to 1.
b <= '1';
-- Wait for 5 cycles.
for i in 1 to 5 loop
wait for rising_edge(clk);
end loop;
-- Set b to 0.
b <= '0';
-- Done.
wait;
end process;
This avoids unexpected behavior, since all signals will change at least one delta cycle after the associated clock, meaning causality is maintained throughout all of your processes.
I have this signal that should be zero until another signal Start = 0. How can I accomplish this?
Maybe you can use a handshake signal and put it in the sensitive list of the process. It will behave like a reset signal.
process (handshake_s, ...)
begin
if (handshake_s = '1') then -- failing edge of start
din <= 0;
else
-- do something
end if;
end process;
Use another process to update handshake_s.
process (start, ...)
begin
if failing_edge(start) then
handshake_s <= '1', '0' after 10 ns; -- produce a pulse
end if;
-- do something
end process;
Would you mind post all your code here so that we could understand the waveform better?
Testbench or RTL code?
For a testbench, your coding style is mostly ok, however, your signal Start has a problem and will never be '1' during a rising edge of clock. It goes to '1' just after the rising edge of clock and will return to '0' either simultaneously with clock or 1 delta cycle before clock (depending on your clock setup). Either way, anything running on rising_edge clock, such as your design, will not see it as a '1'.
A simple way to avoid this is to use nominal delays (25% of tperiod_Clk) on all of your testbench outputs that go to the DUT (Device Under Test). The pattern for a pulse is as follows.
wait until clk = '1' ; -- I recommend using rising_edge(Clk) for readability
Start <= '1' after tpd, '0' after tpd + tperiod_clk ;
Alternately, you can avoid this issue by not using waveform assignments. Such as the following. In this case, you don't need the tpd, however, if it really is a testbench, I recommend using it.
wait until clk = '1' ;
if i = 0 then
Start <= '1' after tpd ;
else
Start <= '0' after tpd ;
end if ;
For RTL code, you need to explore a different approach. Very briefly one way to approach it is as follows. Note do not use any delays, waveform assignments, or loops.
-- Counter to count from 0 to 63. Use "+ 1". Use "mod 64" if using type integer.
-- Start logic = decoder (can be coded separately)
-- Din Logic = decoder (can be coded separately)

Resources