What is wrong with this design - vhdl

I have some VHDL code which behaves strangely when synthesized, but I suspect it is my basic understanding of VHDL synthesis which is wrong.
"sync" is a short pulse (about half a clk period), which is high on clk rising edge, but shortly after goes low. During synthesis only some of the signal assignments are assigned on clk rising edge when sync is high.
Do sync need to be high for some minimum period?
process(clk)
begin
if rising_edge(clk) then
if sync = '1' then
a <= '1';
y3 <= y2;
y2 <= y1;
y1 <= y0;
end if;
end if;
...
Only "a" gets its value updated, when synthesized....

I can only guess since you don't show the whole of the process.
Signal do not get updated until after a process is run. So if you are using signals as intermediate variables other signals won't be updated as you expect.
if a is a signal which has value 1 before the process.
process(clk)
...
a <= '0'
a still has value 1 here
....
end process
a's value is now updated to 0

Related

how can I understand a register correctly?

There is a problem always bothers me. I have written 3 similar functions in VHDL, code and simulation see below. out_1 and input_sig_2 are identicial with input. But out_1 is delayed for 1 clock cycle when compared with input_sig_1. Can someone tell me why is this happens? Is that because input_sig_1 is signal and input is port?
Any response will be highly appreciated!
input_sig_1 <= input;
out_2 <= input_sig_2;
process(clock)
begin
if rising_edge(clock) then
if reset = '1' then
out_0 <= '0';
out_1 <= '0';
input_sig_2 <= '0';
else
out_0 <= input;
out_1 <= input_sig_1;
input_sig_2 <= input;
end if;
end if;
end process;
You are changing the signal input at the same time, when a rising clock edge occurs. So the question is, which of both signal changes reaches first the clocked process. This depends at how many delta cycles you are inserting during the signal path from the testbench to the process. You insert by "input_sig_1 <= input;" one additional delta cycle, so the signal input_1_sig changes after the rising clock edge has reached the process. To avoid such problems you always should change input signals at the inactive clock edge, in your case at the falling clock edge (or at any other time, when no rising clock edge is assigned).

Weird simulation output

I have the following code (which is an extract on something I'm currently working on):
library ieee;
use ieee.std_logic_1164.all;
entity tb_min_example is
end entity tb_min_example;
architecture arch of tb_min_example is
signal clk1, clk2, slow_clk : std_logic;
signal y : std_logic;
procedure drive_clk(signal clk : out std_logic; constant period : time) is
begin
loop
clk <= '1';
wait for period / 2;
clk <= '0';
wait for period / 2;
end loop;
end procedure drive_clk;
begin
drive_clk(clk1, period => 4 ns);
drive_clk(slow_clk, period => (119.0 / 8.0) * 4 ns);
clk2 <= clk1;
process(slow_clk) is
begin
if rising_edge(slow_clk) then
y <= clk1 xor clk2;
end if;
end process;
end architecture arch;
I would expect the signal y to be low all the time since clk2 is assigned to clk1 and x xor x == 1. However, I'm seeing this strange waveform:
It seems that clk2 (or clk1) is sampled just a bit earlier than the other and therefore the result of clk2 xor clk1 is not zero. Why is that, is there some weird delta-cycle stuff going on?
I'm using XSim with Vivado version 2020.2
clk2 is a delayed version of clk1 - delayed by 1 simulation delta cycle.
Because slow_clk and clk1 rise at the same time initially, they will always be in sync on every 2 slow_clk rising edges (119/8 = 59.5, and hence they are both related clocks and align every 2nd rising edge of slow_clk). At this point, clk1 will be '1' while clk2 will be '0', giving you the XOR result of '1'.
This is generally why re-assigning clocks in a design can cause you simulation problems.
If you simply delay the start of slow_clock you should see y being always '0'.

Blocking Assignments on SIGNALS in 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.

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