I'm currently designing a simple multiple input SPI master in Quartus. Given it is a serial protocol, I have a serial clock and a signal that stores the current bit index.
One of the processes I have written looks like this:
store_bits : process(bit_clk) is
begin
if rising_edge(bit_clk) and bit_index >= LEADING_BITS and bit_index < LEADING_BITS+DATA_BITS then
data_valid <= '0';
for input in 0 to INPUTS-1 loop
data(input)(bit_index - LEADING_BITS) <= spi_miso(input);
end loop;
if bit_index = LEADING_BITS+DATA_BITS-1 then
data_valid <= '1';
end if;
end if;
end process store_bits;
Now, bit_index is incremented in a separate process on the falling edge of bit_clk. The process above shouldn't be sensitive to bit_index transitions, so I've left it out of the sensitivity list.
Unfortunately, Quartus II throws a warning during analysis:
10492 VHDL Process Statement warning at multi_spi.vhd(68): signal "bit_index" is read inside the Process Statement but isn't in the Process Statement's sensitivity list
Is it correct? Should I add it to the sensitivity list even though the actual process will only do anything when there is also a bit_clk rising edge?
Related
If you assign a value to a signal in a process, does it only become the correct value of the signal at the end of the process?
So there would be no point in assigning a value to a signal more than once per process, because the last assignment would be the only one that would be implemented, correct?
I'm a bit desperate because I'm trying to implement the booth algorithm in VHDL with signals and I can't get it baked. It wasn't a problem with variables, but signals make it all more difficult.
I tried a for loop, but that doesn't work because I have to update the values within the loop.
My next idea is a counter in the testbench.
Would be very thanksful for an idea!
my current Code look like this:
architecture behave of booth is
signal buffer_result1, buffer_result2, buffer_result3: std_logic_vector(7 downto 0) := "0000"&b;
signal s: std_logic:= '0';
signal count1, count2: integer:=0;
begin
assignment: process(counter) is
begin
if counter = "000" then
buffer_result1 <= "0000"&b;
end if;
end process;
add_sub: process(counter) is
begin
if counter <= "011" then
if(buffer_result1(0) = '1' and s = '0') then
buffer_result2 <= buffer_result1(7 downto 4)-a;
else if (buffer_result1(0) = '0' and s = '1') then
buffer_result2 <= buffer_result1(7 downto 4)+a;
end if;
end if;
end process;
shift:process(counter) is
begin
if counter <= "011"
buffer_result3(7) <= buffer_result2(7);
buffer_result3(6 downto 0) <= buffer_result2(7 downto 1);
s<= buffer_result3(0);
else
result<=buffer_result3;
end if;
end behave;
Short answer: that's correct. A signal's value will not update until the end of your process.
Long answer: A signal will only update when its assignment takes effect. Some signal assignments will use after and specify a time, making the transaction time explicit. Without an explicit time given, signals will update after the default "time-delta," an "instant" of simulation time that passes as soon as all concurrently executing statements at the given sim time have completed (e.g. a process). So your signals will hold their initial values until the process completes, at which point sim time moves forward one "delta," and the values update.
That does not mean that multiple signal assignment statements to the same signal don't accomplish anything in a process. VHDL will take note of all assignments, but of a series of assignments given with the same transaction time, only the last assignment will take effect. This can be used for a few tricky things, although I've encountered differences of opinion on how often they should be tried. For instance:
-- Assume I have a 'clk' coming in
signal pulse : std_ulogic;
signal counter : unsigned(2 downto 0);
pulse_on_wrap : process(clk) is
begin
clock : if rising_edge(clk):
pulse <= '0'; -- Default assignment to "pulse" is 0
counter <= counter + 1; -- Counter will increment each clock cycle
if counter = 2**3-1 then
pulse <= '1'; -- Pulse high when the counter drops to 0 (after this cycle)
end if;
end if clock;
end process pulse_on_wrap;
Here, the typical behavior is to assign the value '0' to pulse on each clock cycle. But if counter hits its max value, there will be a following assignment to pulse, which will set it to '1' once simulation time advances. Because it comes after the '0' assignment and also has a "delta" transaction delay, it will override the earlier assignment. So this process will cause the signal pulse, fittingly, to go high for one cycle each time the counter wraps to zero and then drop the next - it's a pulse, after all! :^)
I provide that example only to illustrate the potential benefit of multiple assignments within a process, as you mention that in your question. I do not advise trying anything fancy with assignments until you're clear on the difference between variable assignment and signal assignment - and how that needs to be reflected in your code!
Try to think of things in terms of simulation time and hardware when it comes to signals. Everything is static until time moves forward, then you can handle the new values. It's a learning curve, but it'll happen! ;^)
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 would I do something like this without a synchronous error in vhdl?
process (shift_button)
variable x : STD_LOGIC;
begin
x := '0';
if falling_edge(shift_button) then
x := '1';
end if;
shift_button_let_go <= x;
end process;
I would first read the Xilinx support article about the error you're encountering:
http://www.xilinx.com/support/answers/14047.html
It basically states there is a certain template that XST expects when making synchronous design elements (note that falling_edge() will use the VHDL 'event attribute). I'm guessing that XST doesn't like how you are defining your clear of shift_button_let_go on the rising edge of shift_button.
You mentioned you want shift_button_let_go to go high for one clock cycle after shift_button goes low. If this is the case then you would want to use your clock in the process' sensitivity list instead of shift_button.
process (clk)
begin
if rising_edge(clk) then
shift_button_d <= shift_button;
if (shift_button_d = '1' and shift_button = '0') then -- Falling edge detect
shift_button_let_go <= '1';
else
shift_button_let_go <= '0';
end if;
end process;
NOTE This logic can suffer from meta stability issues if shift_button is not synchronous to clk and is not held stable for several clk cycles.
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)
I have a flip flop which uses as clk input a signal which comes from the processing of to other signals. That means, that I'm not using the clock of the system neither an input. Thus, when I do:
architecture sampler_a of sampler_e is
signal S0_s : std_logic := '0';
begin
-- In my block this is not only a not. I put this to simplify things.
S0_s <= not(S0_i);
S0_o <= S0_s;
process(S0_i)
begin
--Also with rising edge does not work
if (S0_s'event and S0_s= '1') then
BitReady_o <= '1';
end if;
end process;
end sampler_a;
BitReady does not change in the simulation (in modelsim). Is the use of std_logic incorrect here?
Note that I don't want to generate a pulse that is a clock period's wide, because my circuit works in an asynchronous way.
The process is only sensitive to S0_i, but only tests for events on S0_s (which are never in the same delta cycle as S0_i events). Thus the process can never do anything.
Change its sensitivity list to S0_s and if ought to work.
However, as currently written, once BitReady_o becomes '1', there is no way to ever return it to '0'.