vhdl code bug counter with debouncing of push button - vhdl

I need to implement counter to 100 that increase his count every push button press, it has debouncing circuit using rising edge detector, I got mistakes in the simulation, the counter increases without syncing the push press button. I’m not sure where in the problem, please help me.
the clk is 100Mhz
here is the code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.all;
use IEEE.std_logic_unsigned.all;
entity counter is
Port ( clk : in STD_LOGIC;
reset : in STD_LOGIC;
button : in STD_LOGIC;
count : out STD_LOGIC_VECTOR (6 downto 0)
);
end counter;
architecture Behavioral of counter is
signal debounced_button : std_logic;
signal prev_debounced_button : std_logic := '0';
signal counter_value : unsigned(6 downto 0) := (others => '0');
begin
-- Debounce the button signal using a rising edge detector
process (clk)
begin
if rising_edge(clk) then
if button = '1' and prev_debounced_button = '0' then
debounced_button <= '1';
else
debounced_button <= '0';
end if;
prev_debounced_button <= debounced_button;
end if;
end process;
-- Count up when the button is pressed
process (clk, reset)
begin
if reset = '1' then
counter_value <= (others => '0');
elsif rising_edge(clk) then
if debounced_button = '1' then
if counter_value = 100 then
counter_value <= (others => '0');
else
counter_value <= counter_value + 1;
end if;
end if;
end if;
end process;
-- Convert the counter value to a std_logic_vector for output
count <= std_logic_vector(counter_value);
end Behavioral;
--test bench:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.all;
entity counter_tb is
end counter_tb;
architecture Behavioral of counter_tb is
component counter
Port ( clk : in STD_LOGIC;
reset : in STD_LOGIC;
button : in STD_LOGIC;
count : out STD_LOGIC_VECTOR (6 downto 0)
);
end component;
signal clk : std_logic := '0';
signal reset : std_logic := '0';
signal button : std_logic := '0';
signal count : std_logic_vector(6 downto 0);
-- Stimulus process to generate clock and input signals
begin
uut: counter port map (
clk => clk,
reset => reset,
button => button,
count => count
);
clk_gen: process
begin
clk <= '0';
wait for 5 ns;
clk <= '1';
wait for 5 ns;
end process clk_gen;
stim_proc: process
begin
-- hold reset state for 100 ns.
reset <= '1';
wait for 20 ns;
reset <= '0';
wait;
end process;
process
begin
button <= '0';
wait for 40ns;
button <='1';
wait for 40ns;
button <= '0';
wait for 40ns;
button <='1';
wait for 40ns;
button <= '0';
wait for 40ns;
button <='1';
wait for 40ns;
end process;
end Behavioral;
I think I have problem in the test bench, I'm not sure
the simulation attachedenter image description here

You have two processes. The second process is a simple counter with an asynchronous reset -- no issues here. But let's look at the first.
process(clk)
begin
if rising_edge(clk) then
if button = '1' and prev_debounced_button = '0' then
debounced_button <= '1';
else
debounced_button <= '0';
end if;
prev_debounced_button <= debounced_button;
end if;
end process;
You have three signals, which I'll call button, debounced and prev. Note that they're signals, declared at the architecture level, and not variables within the process. Signals and variables are fundamentally different, as we'll see.
You also declare in the process' sensitivity list that it is sensitive only to clk. The simulator will only run this process whenever clk changes.
On the first rising edge of the clock, this process checks if the button is pressed, and if prev is zero. If so, it sets debounced to 1, else, it's set to 0. But debounced is a signal, which in this process is both being set and used. In a real system, this is called a race condition, and it's indeterminate which operation happens first. Your simulator handles this by always using the value of the signal in the previous time step. At time t-1, debounced was 0, so any statement that uses debounced at time t will use 0. Even if debounced is being changed to 1.
In other words, you have button high, debounced was just set high, and prev stays low.
On the second rising edge of the clock, it's likely buttonis still high as button presses last on the order of a million clock cycles. Since prev is still 0, debounced stays at 1, but this time the last debounced was 1 so prev is now set to 1.
Third rising edge, debounced goes to 0, since prev is now 1. prev stays 1.
Fourth rising edge, prev is still reading as 1, so debounced stays 0. prev now reads the old debounced and is now set to zero.
Fifth rising edge, prev reads as zero, so debounced goes to 1. But prev stays at 0 until the next tick.
This pattern continues as long as button is pressed. Once button goes to 0, then debounced is guaranteed to go to 0 on the next rising edge, and prev will go to 0 on the following tick.
In other words, debounced goes 1-1-0-0-1-1-0-0... oscillating at half the clock frequency for as long as the button is pressed. This isn't a debouncer. It's just using a button to turn on an oscillator. Any time button is 1, debounced_button will toggle; any time button is 0, debounced stays 0.
It's worth noting at this time that the second process uses debounced_button.
On to the simulation. Your system starts with previous at 0. At 40 ns, button goes high. What happens?
Nothing, at first -- you need a rising edge, which comes at 45 ns. Simultaneously, two processes run. The debouncer sees a button press, and sets debounced to 1. The counter uses the old value of debounced, and does nothing. prev uses the old value of debounced, and stays 0.
Next rising edge (55 ns), button is still high and prev is still low, so debounced stays at '1'. prev now goes to 1. Since debounced was high, the counter uses the old value, and now it increments.
65 ns: prev reads as 1, so debounced goes low. But since it was high a moment ago, the count increments again.
75 ns: debounced reads low, the counter doesn't increment.
85-115 ns: button is low, so debounced stays low, and the counter doesn't increment.
125 ns: button is high, so debounced goes high, but as should be obvious by now, the count won't increment.
Finally, note counter_value and count: count isn't being set inside a process with a sensitivity list, so it just changes immediately after counter_value, i.e. on the next simulator time step. Your processes run only when the simulator detects a change in a signal on its sensitivity list, and runs using a "snapshot" of the state of the signals at the start of the process. If you were using variables instead of signals, those are changed immediately and used identically to how sequential logic works in a standard programming language like C.
In reality, if you synthesize this design, you'll find that the behaviour is indeterminate. Your specific FPGA chip and the results of place and route will determine whether a signal is read before or after it's written.
When you have logic that changes a value and consumes it at the same time, the behaviour is indeterminate. You don't know which will happen first. I recommend having all outputs change on one clock edge (e.g. rising), and latch your inputs on the other clock edge (e.g. falling), to ensure that your inputs are stable before you try to use them.
Finally, debugging's a lot easier if you look at the internal signals. I simulated your code for 200 ns and got this:
Here, you can see exactly what's happening with prev and debounced, and immediately understand that there's a one-clock delay in the signal propagation.
Also, you can immediately see that your simulation's different from mine. It helps if you actually run the code you post here.

Related

FSM enters impossible state

I have a FSM consisting of 3 states: STATIC, UP and DOWN.
The FSM starts in the STATIC state and if I press the up arrow key, it will move to the UP state, thereafter returning to the STATIC state. Same thing for DOWN.
At first the FSM works well but suddenly after a random amount of key presses it will enter an unspecified state. The FSM consists of two processes:
type ALL_STATES is (STATIC, UP, DOWN);
signal STATE, NEXT_STATE: ALL_STATES;
signal posBarraYTOP, posBarraYBOT: std_logic_vector(11 downto 0);
signal movTeclado: std_logic_vector(1 downto 0);
-- ...
Keybd: keyboard port map (input, movTeclado); -- keyboard output
-- ...
bar_FSM_sincrono: process(CLK, RST) -- CLK is the FPGA's clock
begin
if RST='1' then
STATE <= STATIC;
elsif (CLK'event and CLK = '1') then
STATE <= NEXT_STATE; -- in each CLK cycle we move to the next state.
end if;
end process bar_FSM_sincrono;
bar_FSM_cambioest: process(STATE)
begin
case STATE is
when STATIC=>
seg <= "1001001";
if (movTeclado = "01" and posBarraYTOP > 20) then
NEXT_STATE <= UP;
elsif (movTeclado = "10" and posBarraYBOT < 980) then
NEXT_STATE <= DOWN;
else
NEXT_STATE <= STATIC;
end if;
when UP | DOWN =>
NEXT_STATE <= STATIC;
seg <= "1111110";
when others =>
NEXT_STATE <= STATIC;
seg <= "0110111";
end case;
end process bar_FSM_cambioest;
movTeclado is a 2-bit signal that shows when the user presses the up 01 or down 10 key. It's 00 if no key is pressed. movTeclado doesn't give me any problems.
posBarraYTOP and posBarraYBOT are two signals to describe a boundary, and these conditions are always met.
I use seg as a signal for the 7-segment display to debug and find out in what state the FSM is at. At first it always displays the STATIC seg, as it should since UP seg and DOWN seg are only displayed for one cycle. But then when the error happens it's when it starts displaying the others seg, as well as the STATIC seg. It's a back-and-forth between STATIC and others, which I don't understand since when STATE = STATIC, it should only transition to UP or DOWN.
Thank you for reading this far, does anyone know what's going on?
As other comments have suggested, you should never drive a signal from more than one process block. Personally I don't like writing state machines like this, with 2 process blocks, because I find it confusing.
But regardless, your 2nd process block (the combinational one) should only be assigning NEXT_STATE, it should never make an assignment to STATE since that's taken care of by the first process block.
One issue is that your bar_FSM_cambioest sensitivity list is incomplete. It needs to include all signals who's changes will affect the process's output.
bar_FSM_cambioest: process(STATE, movTeclado, posBarraYTOP, posBarraYBOT)
My next question would be how fast is your clock? Are you trying to go from the STATIC segment display to the UP/DOWN one and back faster than the 7-segment display can reliably update?

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

State Machine with VHDL for UA(R)T

I am trying to create a state machine in vhdl for UA(R)T (Only the sending portion).
I am having an issue with the flow of the program. I know the buad rate portion does not work at the moment. I am trying to get it working with just a clock at the moment, and then will implement the baud rate divider.
When I run it through my test bench (nothing complicated, just assign a couple of initial values reset = 1 for x time, din = z, baud = y, etc), nothing happens. My output txd stays at the initial '1' value that is set in the reset stage and if I set it to '0' it will stay like that for the cycles.
My issue that I had when designing the state machine is the it has two values that it will transition on BUT not in ever state.
Basically, what it is supposed to do is:
reset: txd = 1, count = 1, busy = 0, we = 0
idle: when busy = 1 set shift = init values
wait: transition on next clock signal
trans: if count < 9, txd = shift(0), and shift shift
if count = 9, busy = 0, count = 0
and back to idle
I think my issue is somehow related to the busy signal not being properly set.
-- Universal Asynch Receiver Transmitter
---------------------
library ieee;
use ieee.std_logic_1164.all;
entity eds_uart is
generic (width : positive := 16);
port ( clk,reset: in std_logic ;
din_wen: buffer std_logic; -- state machine sets value thus buffer needed
brd : in std_logic_vector(23 downto 0); -- buad rate dividor
din : in std_logic_vector(7 downto 0); -- input value
txd: out std_logic; -- sent data bit
tx_busy : buffer std_logic -- sent data bit active
);
end entity eds_uart;
architecture behaviour of eds_uart is
type state_type is (idle_s, wait_s, transmit_s); -- three possible states of uat
signal current_s: state_type;
signal tick: std_logic; -- baud rate clock
signal count: integer := 0; -- count number of characters sent
signal shift: std_logic_vector(9 downto 0); -- intermediate vector to be shifted
begin
-- assign tick value based on baud rate
-- need to implement divisor
process(clk, brd) begin
tick <= clk;
end process;
process(tick, reset, din) begin
if (reset = '1') then
current_s <= idle_s; -- default state
count <= 0; -- reset character counter
txd <= '1';
tx_busy <= '0';
din_wen <= '0'; -- able to start sending
elsif (current_s = idle_s and din_wen = '1') then -- transition when write enable is high
current_s <= wait_s; -- transition
tx_busy <= '1';
shift <= '1' & din & '0'; -- init shift value
elsif (current_s = wait_s and rising_edge(tick)) then -- transition on clock signal
current_s <= transmit_s;
elsif (current_s = transmit_s and rising_edge(tick)) then -- test transition on clock signal
if (count < 9) then
txd <= shift(0); -- output value
shift <= '0' & shift(9 downto 1); -- shift to next value
count <= count + 1; -- increment counter
current_s <= transmit_s; -- dont change state
elsif (count = 9) then
txd <= shift(0); -- send last element
count <= 0;
tx_busy <= '0'; -- reset busy signal
current_s <= idle_s; -- start process again
end if;
end if;
end process;
end architecture behaviour ;
The comments:
-- state machine sets value thus buffer needed
and
-- transition when write enable is high
suggest that you may be expecting to have an additional external driver for din_wen. If that is the case the buffer mode is not doing you any good as it only exposes the value of the internal driver of din_wen which is only ever driving '0'. Post VHDL-2002, buffer is effectively a fancy, readable version of out without the limitations from earlier standards. It does not implement an input port. More significantly, it does not let you see the external resolved value if you have additional signal driver(s) outside this entity.
It isn't clear why you even need to drive din_wen internally since it is intended to be a control input that causes the transition into the wait_s state. Consider changing it to an in port mode and removing the reset assignment.
Style note: You are courting danger with the mixture of synchronous and asynchronous logic described here. You should stick to the pattern of having a single call to rising_edge() in a top level if block that wraps all of your synchronous 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