A clock cycle unwanted delay in incrementing counter withouth state machine - vhdl

I am trying to run a simple counter(v_bincount) starting from 0 to the time when the s_saxis_tlast goes high. It starts counting when s_saxis_tuser_in is high. It starts from 0 however the value of the counter remains 0 for one more clock cycle even though v_bincount is a shared variable and not a signal.
p_count: process(clk)
begin
if (rising_edge (clk)) then
if (s_saxis_tvalid_in = '1')and (s_saxis_tready_out = '1') then
if(s_saxis_tuser_in ='1') then
v_bincount1 := 0;
v_idcount1 := 0;
else
if (s_saxis_tlast_in = '0') then
v_bincount1 := v_bincount1 + 1;
else
v_bincount1 := 0;
v_idcount1 := v_idcount1 + 1;
end if;
end if;
else
v_bincount1 := 0;
v_idcount1 := 0;
end if;
end if;
end process p_count;

The simulation is what you would assume. On the lowering edge of the tuser_in, it is still '1' at the clock edge.
I would suggest not to use shared variable here. Instead, have a combinatorial counter with signals which increment the value according to your wishes and then clocked process to assign the value to a register e.g.:
p_count_r : process(clk)
begin
if (rising_edge (clk)) then
s_bin_count_r <= s_bin_count;
s_id_count_r <= s_id_count;
end if;
end process p_count_r;
and in the combinatorial process use the s_bin_count_r on the right-hand side.

Related

Easy Count-Down Counters Integer vs Unsigned

Rather than having to build counters as follows -
signal my_counter : unsigned(3 downto 0) := to_unsigned(9, 4);
signal reset_value : unsigned(3 downto 0) := to_unsigned(9, 4);
--...
--...
process(clk)
begin
if rising_edge(clk) then
counter <= counter - 1;
if counter = 0 then
counter <= reset_value;
-- raise flag telling other logic to do stuff
end if;
end if;
end process;
Could you do this with an integer count down with a range? and therefore you wouldn't need to have the reset_value? Could this look something like...
signal my_counter_int : integer range 0 to 9 := 9;
--...
--...
process(clk)
begin
if rising_edge(clk) then
counter <= counter - 1;
if counter = 0 then
-- raise flag telling other logic to do stuff
end if;
end if;
end process;
I'm just seeing whether you can have an implied roll over to 9 with an integer with a set range.
Create your own subtype from integer with the proper range (0–9) and define the counter variable to be of that type:
subtype MY_COUNTER_TYPE is integer range 0 to 9;
signal counter : MY_COUNTER_TYPE := 9;
Declare a "rolling decrement" function for your own subtype, which folds the value back to the highest possible value in the range if the decrement would decrease the value under the range:
function r_decrement(val : MY_COUNTER_TYPE) return MY_COUNTER_TYPE is
begin
if val = MY_COUNTER_TYPE'LOW then
return MY_COUNTER_TYPE'HIGH;
else
return val - 1;
end if;
end function;
Now you can use the rolling decrement function of the type without worrying about the resetting the counter manually or checking if the decrement would result in the signal being out of the allowed range:
if rising_edge(clk) then
counter <= r_decrement(counter); -- "rolling" decrement
if counter = 0;
-- raise flag telling other logic to do stuff
end if;
end if;
So yes, it is possible. And if you're using a lot of counters like this in your design, you may avoid writing a lot of redundant code when checking the counter limits and resetting the value back to reset_value manually.

How to count pixels using AXI Stream signals?

I was trying to count pixels based on the signals from the AXI stream signals like tuser and tlast. I wrote this:
p_pixelcount : process (s_clk)
variable v_hcount : integer := 1;
variable v_linecount: integer:= 1;
begin
if (rising_edge(s_clk)) then
if (s_maxis_s_tvalid_out = '1')and (s_maxis_s_tready_in = '1') then
if ( rising_edge(s_maxis_s_tuser_out) ) then
v_hcount := 0;
v_linecount := 0;
else
v_hcount := v_hcount + 1;
end if;
if (s_maxis_s_tlast_out = '1') then
v_hcount := 0;
v_linecount := v_linecount + 1;
end if;
end if;
end if;
end process p_pixelcount;
I received the following simulation outputs
My questions:
When tuser is high, shouldn't the v_hcount be 0?
Is it allowed to use two rising_edge(signal) conditions on different signals in the same process?
I want to count till tlast and then in the next cycle the count is set zero. Is it possible to do this without using a signal?
Thanks
First off: don't make v_hcount and v_linecount variables. They are clocked, so need to be registered: use signals for that. (for synthesizable code)
No, you cannot use rising_edge twice in a process like this. If you want to detect a 0->1 transition, you need to do that in the (correct) clock domain. E.g.
s_maxis_s_tuser_out_delay <= s_maxis_s_tuser_out when rising_edge(s_clk);
s_maxis_s_tuser_out_rising <=
'1' when s_maxis_s_tuser_out = '1' and s_maxis_s_tuser_out_rising = '0'
else '0';
but in this case you should probably just use
if (s_maxis_s_tuser_out = '1') then
v_hcount <= 1;
v_linecount <= 0;
else
v_hcount <= v_hcount + 1;
if (s_maxis_s_tlast_out = '1') then
v_hcount <= 0;
v_linecount <= v_linecount + 1;
end if;
end if;
Why do you initialize the v_hcount and v_linecount at 1, but reset them to 0?

Signal <signal> cannot be synthesized, bad synchronous description

I'm trying to implement a component that takes in input a base clock and as output a pattern accordingly to this scheme:
I'm getting this error, and i've tried to fix it in many ways following various suggestion also from stackoverflow, but nothing...
ERROR:Xst:827 - "E:/Progetti/nuovi/Clock_generator/CG_ex_3/clock_ex3.vhd" line 34: Signal check_0 cannot be synthesized, bad synchronous description. The description style you are using to describe a synchronous element (register, memory, etc.) is not supported in the current software release.
Some times the same error refer to pre_forma_clk
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity clock_ex3 is
Port ( base_clk : in STD_LOGIC;
forma_clk : out STD_LOGIC);
end clock_ex3;
architecture Behavioral of clock_ex3 is
signal pre_forma_clk : std_logic := '0';
begin
forma_clk <= pre_forma_clk;
pattern_generator : process(base_clk) --line 34
variable check_0 : natural := 0;
variable check_1 : natural := 0;
variable check_2 : natural := 0;
variable check_3 : natural := 0;
begin
if (rising_edge(base_clk)) then
check_0 := check_0 + 1;
if (check_0 = 15) then
pre_forma_clk <= not pre_forma_clk;
end if;
end if;
if (falling_edge(base_clk) and check_0 >= 15) then
check_1 := check_1 + 1;
if (check_1 = 10) then
pre_forma_clk <= not pre_forma_clk;
end if;
end if;
if (falling_edge(base_clk) and check_1 >= 10) then
check_2 := check_2 + 1;
if (check_2 = 15) then
pre_forma_clk <= not pre_forma_clk;
end if;
end if;
if (rising_edge(base_clk) and check_2 >= 15) then
check_3 := check_3 + 1;
if (check_3 = 10) then
pre_forma_clk <= not pre_forma_clk;
check_0 := 0;
check_1 := 0;
check_2 := 0;
check_3 := 0;
end if;
end if;
end process;
end Behavioral;
I've already tried to separate IF conditions in different IFs...
thanks for help
Your question is pretty well answered here. The difference between that question and yours, is that the specific error in your code is that you have multiple if (rising_edge(clk)) then structures inside one process; a synthesis-eligible process can only contain one edge detector of this type.
Looking at your functional requirement, I would implement this using two separate rising and falling edge counters, each with their own process, then write another process implementing a state machine that works with these counters to implement the required state transitions and counter resets.

How can I generate a "tick" inside a process in VHDL?

I am writing a specified UART component in VHDL.
send: process(send_start)
variable bit_index : integer range 0 to 2 := 0;
begin
if (falling_edge(send_start)) then
if (start = '0' and transceiver_start = '1') then
bit_index := 0;
end if;
transceiver_start <= '1';
if (bit_index = 0) then
temp_data <= data.RE;
bit_index := 1;
transceiver_start <= '0';
delay_counter <= 0;
elsif (bit_index = 1) then
temp_data <= data.IM;
bit_index := 2;
transceiver_start <= '0';
end if;
end if;
end process;
The falling edge of the transceiver_start signal triggers the sub-component to run. I wanted to trigger it twice, but I do not know how to generate a second falling edge.
I thought about using a concurrent process, which would basically reset the transceiver_start signal to it's hi-state after delay_counter reaches some limit. Therefore I could bring it down inside the send process again to generate a falling edge. However, this makes me have two driving processes for the delay_counter signal, and I read that having resolution functions is not a good practice for synthesis (this code needs to be synthesizable.)
Is there any way for me to generate that falling edge when bit_index = 1?
FPGA devices and related synthesis tools are optimized for synchronous logic,
thus VHDL where a clock triggers process execution. Using a specific signal to
trigger process execution, as in the question code, is thus not in line with
the indented FPGA and VHDL design methodology.
Instead, use an internal clock to trigger process execution, usually the rising
edge of the clock. Actual update inside the process can then be conditional on
detection of change to a control signal, which can be send_start.
process (clock) is
begin
if rising_edge(clock) then
send_start_prev <= send_start; -- Previous for edge detection
if ((send_start = '0') and (send_start_prev = '1')) then -- Falling edge of send_start
... -- More code
end if;
end if;
end process;
For rerunning of conditional process code, for example based on bit_index = 1, the process contents can be updated like:
send_start_prev <= send_start; -- Previous for edge detection
rerun_request <= '0'; -- Default no rerun
if ((send_start = '0') and (send_start_prev = '1')) or -- Falling edge of send_start
(rerun_request = '1') then -- Rerun request
if bit_index = 1 then
rerun_request <= '1';
end if;
... -- More code
end if;

How to change signal value instatntly?

if(rising_edge(clk)) then
count := count + 1;
if count = 3 then
enable <= 1;
elsif count = 6 then
enable <= 0;
count := 0;
end if;
end if;
if enable = 0 then
a0i <= a_0;
boi <= b_0;
end if;
if enable = 1 then
a0i <= a_1;
boi <= b_1;
end if;
All are signals except the count. Value of a0i and boi should response as soon as enable becomes either 0 or 1. I tried using the variable. but it can not allow me to use out side the process.
I am getting the o/p as this. How ever I want to change the input as soon as enable signal change.
Put the last two if conditions in another process
Process(enable, a_0, b_0, a_1, b_1)
begin
If(enable = '0')THEN
a0i <= ...
....
ELSE
.....
END IF;
END PROCESS;
This process is sensitive to the enable signal so anytime there is a change in enable, independent of the clock, the statements will take effect immediately (asynchronously)
Solution 1: use 2 processes as blueprint mentioned.
Solution 2: use an internal variable.
process(clk)
variable count : natural range of 0 to 6 := 0;
variable enable_i : std_logic := '0';
begin
if(rising_edge(clk)) then
count := count + 1;
if count = 3 then
enable_i := '1';
elsif count = 6 then
enable_i := '0';
count := 0;
end if;
end if;
if enable = '0' then
a0i <= a_0;
boi <= b_0;
else
a0i <= a_1;
boi <= b_1;
end if;
enable <= enable_i;
end process;
Some hints:
Maybee, the type boolean is more suitable for your signal/variable enable_i
If enable_i is only used inside the process, then you can remove the conversion to enable
including the data path and multiplexers in a state machine (I assume this is a part of it) is not a good design choice.
You could also take these two equation below out from your process.
process(...)
[...]
if enable = 0 then
a0i <= a_0;
boi <= b_0;
end if;
if enable = 1 then
a0i <= a_1;
boi <= b_1;
end if;
end process
Then you cannot use the IF statement anymore, but you can use the WHEN statement :
a0i <= a_0 when enable = '0' else a_1;
boi <= b_0 when enable = '0' else b_1;
Note that in this case, the multiplexer will be after the latch. This could be important if you have timing issues on these signals.
From your simulation waveform, it looks to me like you failed to include enable, a_0, b_0, a_1, and b_1 in your sensitivity list, but I can't be sure because you didn't post the complete example. Because you test the values of the 5 mentioned signals outside of the if rising_edge(clk), they need to be included. The values are only updated on the falling edge of clk because, presuming that clk is the only thing in your sensitivity list, that is the next time the process is evaluated.
It should be otherwise functional as written, although you could use an else instead of a separate test for enable = 0 for a slight readability improvement. Synthesis usually ignores the sensitivity list (it just makes simulation more efficient) so it should already work if you were to synthesize.

Resources