How to wait for a signal to be assigned new value within a process without using wait statement in vhdl - vhdl

Basically I have to code a university project in vhdl. The main issues is that during a process I need assign a std_logic signal a '1' value so that a secondary process can start. I'm aware that the assignment to a signal is at the next clock cycle. But the problem is that I need to create a synthesizable hardware component so i can't really use wait statements. So here is the question: how can I wait a cycle of clock without using wait statements?

You need to use clocked process with a structure as follows. Process_2 will start on the clock cycle after start_signal is set.
process_1 : process(clock)
begin
if rising_edge(clock) then
start_signal <= '1';
end if;
end process;
process_2 : process(clock)
begin
if rising_edge(clock) then
if start_signal then
--do stuff
end if;
end if;
end process;

Related

What is needed to make a wait statement within a process with a sensitivity list

I would like to have a process in paralel with a process that receives filter (code bellow). This filter will change if I have 16 bits in data_to_memory signal then I will in the other process store this in a variable and perform some filter calculations. I think that my code is correct but still gives me the error: A wait statement is illegal for a process with a sensitivity list.
I have this two process in a file and my testbench in a different file.
process(bits_received)
begin
if rising_edge(bits_received) then
bits_data_rec(7 downto 0)<=data_in;
filter<='0';
wait until rising_edge(bits_received);
data_to_memory<=bits_data_rec&data_in;
filter<='1';
wait for clock_period;
filter<='0';
end if;
end process;
the process in my testbench:
file_open(file_pointer,"inputs.txt",READ_MODE);
file_open(file_RESULTS,"target.txt",WRITE_MODE);
reset<='1';
wait for clock_period/2;
reset<='0';
wait for clock_period/2;
while not endfile(file_pointer) loop
readline(file_pointer, line_num);
read(line_num, data);
data_in<=data(7 downto 0);
bits_received<='1';
wait for clock_period;
bits_received<='0';
data_in<=data(15 downto 8);
bits_received<='1';
wait for clock_period;
bits_received<='0';
wait for clock_period;
WRITE(v_OLINE,out_filter);
writeline(file_RESULTS, v_OLINE);
wait for clock_period;
wait for clock_period;
end loop;
Is my testbench affecting the process(bits_received)?

VHDL: button debounce inside a Mealy State Machine

Hi I'm trying to implement a mealy machine using VHDL, but I'll need to debounce the button press. My problem is I'm not sure where should I implement the debouncing. My current work is like this:
process(clk)
begin
if(clk' event and clk = '1') then
if rst = '1' then
curr_state <= state0;
else
curr_state <= next_state;
end if;
end if;
end process;
process(curr_state, op1,op0,rst) --here op1,op0 and rst are all physical buttons and I need to debounce op1 and op0
begin
if rst = '1' then
...some implementation
else
...implement the debounce logic first
...process some input
case curr_state is
when state0=>...implementation
...similar stuff
end case;
end process;
I'm not sure whether I'm doing in the right way or not. In the second process, should I put the rst processing like this, or should I put it inside when state0 block? Also, as the processing of debounce requires counting, do I put it outside the case block like this? Thank you!
I would use a completely separate block of code to debounce any button signals, allowing your state machine process to focus on just the state machine, without having to worry about anything else.
You could use a process like this to debounce the input. You could of course exchange variables for signals in this example (with associated assignment operator replacements).
process (clk)
constant DEBOUNCE_CLK_PERIODS : integer := 256; -- Or whatever provides enough debouncing
variable next_button_state : std_logic := '0'; -- Or whatever your 'unpressed' state is
variable debounce_count : integer range 0 to DEBOUNCE_CLK_PERIODS-1 := 0;
begin
if (rising_edge(clk)) then
if (bouncy_button_in /= next_button_state) then
next_button_state := bouncy_button_in;
debounce_count := 0;
else
if (debounce_count /= DEBOUNCE_CLK_PERIODS-1) then
debounce_count := debounce_count + 1;
else
debounced_button_out <= next_button_state;
end if;
end if;
end if;
end process;
Another option would be to sample the bouncy_button_in at a slow rate:
process (clk)
constant DEBOUNCE_CLK_DIVIDER : integer := 256;
variable debounce_count : integer range 0 to DEBOUNCE_CLK_DIVIDER-1 := 0;
begin
if (rising_edge(clk)) then
if (debounce_count /= DEBOUNCE_CLK_DIVIDER-1) then
debounce_count := debounce_count + 1;
else
debounce_count := 0;
debounced_button_out <= bouncy_button_in;
end if;
end if;
end process;
The advantage of the first method is that it will reject glitches in the input. In either case, you would use the debounced_button_out (or whatever you want to call it, perhaps rst) in your state machine, whose code then contains only the core state machine functionality.
If you wanted even more debouncing, you could use another counter to create an enable signal for the processes above, to effectively divide down the clock rate. This could be better than setting the division constant to a very high number, because you may not be able to meet timing if the counter gets beyond a certain size.
You could even create a debounce entity in a separate file, which could be instantiated for each button. It could have a generic for the constant in the above process.
There's also hardware debouncing, but I suppose that's outside the scope of this question.
In the second process, should I put the rst processing like this, or
should I put it inside when state0 block?
Only put it in the State0 block
Also, as the processing of
debounce requires counting, do I put it outside the case block like
this?
Counting needs to be done in a clocked process. Since you are doing a two process statemachine, you cannot do it in the case block. I typically put these sort of resources in a separate clocked process anyway.
For states, you need: IS_0, TO_1, IS_1, TO_0.
The TO_1 and TO_0 are your transition states. I transition from TO_1 to IS_1 when I see a 1 for 16 ms. I transition from TO_0 to IS_0 when I see a 0 for 16 ms. Run your counter when you are in the TO_1 or TO_0 state. Clear your counter when you are in the IS_1 or IS_0 state.
This should get you stated.

wait on an untimed signal in VHDL testbench

I have written a simulation process that sets or changes signals sequentially as required, I use wait statements normally to wait certain time intervals or wait on signal assignments, but that is true only when I know when a signal should be coming, an example:
reset <= '1';
write <= '0';
read <= '0';
wait for 25 ns;
reset <= '0';
chipselect <= '1';
wait until clk = '1';
but now I need to do something different, I have a signal that is normally 0, and I need to pause simulation stimulus whenever it is turned to 1. the signal however is not timed. meaning I cannot do it with a simple wait statement because the simulation will wait for it only at a certain time. I want that effect to happen at all times. how to do something like this?
Based on the description, I understand that you want to pause stimuli
generation based on a signal, so stimuli time is extended corresponding to the
time of the pause.
For this a signal with the active time (named active_time below) can be
created, and stimuli can then be generated based on this time. The active time
is only running when the active_stimuli is TRUE.
A support procedure (named active_wait_for below) corresponding to wait for
can then be created to wait for the requested amount of active time, for use in
the stimuli generation process.
Suggestion for code:
architecture syn of tb is
-- Active declarations
signal active_stimuli : boolean := TRUE;
constant ACTIVE_RESOLUTION : time := 1 ps;
signal active_time : time := 0 ps;
-- Wait procedure for active delay
procedure active_wait_for(delay : time) is
variable active_time_start_v : time;
begin
active_time_start_v := active_time;
if delay > 0 ps then
wait until active_time >= active_time_start_v + delay;
end if;
end procedure;
-- Stimuli signal
signal stimuli_a : std_logic;
signal stimuli_b : std_logic;
begin
-- Active time generation
process is
begin
wait for ACTIVE_RESOLUTION;
if active_stimuli then
active_time <= active_time + ACTIVE_RESOLUTION;
else -- Save execution time in loop by wait until
wait until active_stimuli;
end if;
end process;
-- Stimuli generation
process is
begin
stimuli_a <= '0';
stimuli_b <= '0';
wait until active_time >= 2 ns;
stimuli_a <= '1';
active_wait_for(3 ns);
stimuli_b <= '1';
wait;
end process;
...
Waveform showing operation is below:
Note that polarity is different than the signal in the question, but naming was
clearer with this polarity.
Some ideas for "pausing" a stimulus process on an interrupt-type signal:
Rewrite the stimulus as a clocked process (a state machine, for example) and use the interrupt as a clock enable. This may be a pain, though.
Maybe easier, whenever you wait, wait something like this:
wait until clk = '1';
if interrupt = '1' then
wait until interrupt = '0';
wait until clk = '1';
end if;
or if it's not a synchronous wait:
wait for 100 ns;
if interrupt = '1' then
wait until interrupt = '0';
end if;
You could, of course, write a procedure to make these easier. There may be simpler/more elegant ways to code those, but what I wrote should work.
Is this what you want:
process (start) begin
if rising_edge(start) then
-- Respond to start signal rising
end if;
end process;
There is nothing stopping your from writing another process in your testbench/simulation to wait for that other condition to happen. An example of when you might want to do this is when you are simply counting the number of events of a certain condition.
For example:
Signal_Waiter : process(interrupt)
begin
if rising_edge(interrupt) then
-- do stuff here such as increment a counter
end if;
end process;
Since this process is completely independent from your "stimulus" section of code, it is always ready to wakeup and process. In this case, it will wake up whenever the signal interrupt changes.
Be careful if you are driving stimulus signals from the separate process, because you can't have two processes driving the same signal. If you need feedback to your main control process, you could do that with a signal or a shared variable.

Breaking out of a procedure in VHDL

I am trying to figure out a way to break out of a procedure if some external event occurs. Let's say I have a procedure like this:
procedure p_RECEIVE_DATA (
o_data : out std_logic) is
begin
wait until rising_edge(i2c_clock);
o_data := i2c_data;
wait until falling_edge(i2c_clock);
end procedure P_RECEIVE_DATA;
Now what I want is if an external signal, let's call it r_STOP gets asserted at any time, I want this procedure to exit immediately. Is there a nice way to do this? I was thinking that if this Verilog I could use fork/join_any to accomplish this, but there is no equivalent to fork and join in VHDL. Does anyone have any suggestions?
First of all, the code you have here might be just fine for a test or simulation. If this is what it's for, then great. However, keep in mind that code written as you have above is not synthesizable. You can compile and run it in a simulation setup, but you almost certainly won't be able to turn this into a hardware design for an FPGA, ASIC, or any other type of physical device. (In general, procedures can be used in synthesis only when they are called in a process and have no wait statements (or, less commonly, and only in some tools, when all of the wait statements are exactly the same).)
So to answer exactly what you've asked, the way to break out of a procedure is to call return when the condition you are interested in is met. For example if you wanted a global "r_stop" signal as you suggested make this procedure exit early no matter what whenever it changed to a '1', then you'd look for that explicitly:
procedure p_RECEIVE_DATA (
o_data : out std_logic) is
begin
wait until rising_edge(i2c_clock) or r_stop = '1';
if r_stop = '1' then return; end if;
o_data := i2c_data;
wait until falling_edge(i2c_clock) or r_stop = '1';
if r_stop = '1' then return; end if;
end procedure P_RECEIVE_DATA;
Again, if this is not testbench code, but is meant to be synthesizable, you need to take a different approach and model your logic as an explicit finite state machine.
I'm not sure there's a nice solution to this in VHDL. It's a bit like making an inferred state machine with a reset signal, which is also not pleasant.
You can do:
wait until rising_edge(clk); exit when reset = 1;
within a loop.
I guess you could do:
wait until rising_edge(clk); if stop = '1' then return; end if;
but again, not pleasant!
Here my 2 cents.
You can do this in your main thread/process by calling trigger control signals for those other threads/processes.
Depending on the state of those control signals you can wait for any thread(join_any), all threads(join) or just do not wait (join_none).
Driving signals from multiple processes is a bad idea unless you really know what you're doing (multiple driver problem). Therefore the activation and deactivation signal for each thread should be different since they are controlled from different processes/drivers. That is the reason why i have written 2 control signals 1.started and 2.finished for each thread.
It is very important that a signal/interface is only written in one process in your code.
The code use waits so the same problems stated by wjl are applicable for synthesis.
If you want it synthetizable then put thread_0_active in the sensitivity list and do if rising_edge(thread_0_active) then inside the process. This will encapsulate the code and will be executed only in case of the rising condition. Of course the code inside this process should be synthetizable and contain no waits.
A state machine can only run and be in one state at a time.
I think you are interested on a direct equivalente to the systemverilog fork behavior. I have tried to make the example as close as possible.
The code below:
signal thread_0_started : std_logic:='0';
signal thread_0_finished : std_logic:='0';
signal thread_1_started : std_logic:='0';
signal thread_1_finished : std_logic:='0';
--......
p_main_father : process
variable father_v : std_logic_vector( 32-1 downto 0 );
begin
--Do other things in your main thread using variables
--
--Now fork a thread activating it.
thread_0_started <= '1';
thread_1_started <= '1';
--signals are activated and now we need to wait when they are finished
--here both threads are started at the same time concurrently.
----------------------
--a fork .. join_any would be to do an "or" until the logic
wait until (thread_0_finished = '1') or (thread_1_finished = '1');
-------------------
--a fork .. join would be to do an "and" with the logic
--wait until (thread_0_finished = '0') and(thread_1_finished = '0');
--a fork .. join_none would be to just NOT do "wait until" and ignore that the threads were activated!!!
thread_0_started <= '0';--restore started state in case this main thread want to start them again.
thread_1_started <= '0';
end process;
child_thread_0 : process
variable prdata_v : std_logic_vector( 32-1 downto 0 );
begin
if thread_0_started = '0' then
thread_0_finished <= '0';--important disable finished if not started
end if;
wait until rising_edge(thread_0_started);--trigger event
--Do your things inside de thread_0 that consume time. e.g. calling other process
thread_0_finished <= '1';
end process;
child_thread_1 : process
variable prdata_v : std_logic_vector( 32-1 downto 0 );
begin
if thread_1_started = '0' then
thread_1_finished <= '0';--important disable finished if not started
end if;
wait until rising_edge(thread_1_started);
--Do your things inside de thread_1 that consume time. e.g. calling other process
thread_1_finished <= '1';
end process;

Can't infer register for ... at ... because it does not hold its value outside the clock edge

This must be the most common problem among people new to VHDL, but I don't see what I'm doing wrong here! This seems to conform to all of the idioms that I've seen on proper state machine design. I'm compiling in Altera Quartus 9.2, for what it's worth. The actual error is:
"Can't infer register for "spiclk_out" at [file] [line] because it does not hold its value outside the clock edge"
ENTITY spi_state_machine IS
PORT(
spiclk_internal : IN STD_LOGIC;
reset : IN STD_LOGIC;
spiclk_out : BUFFER STD_LOGIC
);
END spi_state_machine;
PROCESS(spiclk_internal, reset)
BEGIN
IF reset = '1' THEN
spiclk_out <= '0';
END IF;
IF spiclk_internal = '1' AND spiclk_internal'EVENT THEN --error here
spiclk_out <= NOT spiclk_out;
END IF;
END PROCESS;
Thanks for your time.
As written, the process would cause spiclk_out to toggle on spiclk_internal edges even when reset is active, which is not how flip-flops with asynchronous resets should behave.
What you probably want is
SPICLK: process(spiclk_internal, reset)
if reset = '1' then
spiclk_out <= '0';
elsif spiclk_internal'event and spiclk_internal='1' then
spiclk_out <= not spiclk_out;
end if;
end process SPICLK;

Resources