Easy Count-Down Counters Integer vs Unsigned - vhdl

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.

Related

std_logic_vector (to_unsigned(X, Y));

This is a test-bench, and I have these signals:
signal DATA_INPUT :std_logic_vector(0 to 31);
signal rand_num :integer;
I am trying to put random numbers into this 32bit signal by this:
DATA_INPUT <= std_logic_vector(to_unsigned(rand_num, 32));
My question is, I need numbers more than 31bits but when the random numbers goes above this number: 2147483647 which is INTEGER'high, I am getting this error:
near "4294967295": (vcom-119) Integer value exceeds INTEGER'high.
# ** Error: tb.vhd: (vcom-1144) Value -1 (of type
std.STANDARD.NATURAL) is out of range 0 to 2147483647.
I tried to modify the TO_UNSIGNED() function and change the NATURAL input to something else but nothing.
Here is the TO_UNSIGNED function from IEEE and RANDOOM GENERATOR process:
function TO_UNSIGNED(ARG, SIZE: NATURAL) return UNSIGNED is
variable RESULT: UNSIGNED (SIZE-1 downto 0);
variable i_val: NATURAl := ARG;
begin
if (SIZE < 1) then return NAU; end if;
for i in 0 to RESULT'left loop
if (i_val MOD 2) = 0 then
RESULT(i) := '0';
else RESULT(i) := '1';
end if;
i_val := i_val/2;
end loop;
if not(i_val=0) then
assert NO_WARNING
report "numeric_std.TO_UNSIGNED : vector truncated"
severity WARNING;
end if;
return RESULT;
end TO_UNSIGNED;
Random generator:
process
variable seed1, seed2 :positive;
variable rand :real;
variable range_of_rand :real:= 46340.0;
begin
uniform(seed1, seed2, rand);
rand_num <= integer(rand*range_of_rand);
wait for 1 ns;
end process;
You can make a new,bigger random number by combining two.
The simplest solution is to convert two random integers to vectors and then concatenate until you get the number of bits you need. This gives you 64 bits:
DATA_INPUT <= std_logic_vector(to_unsigned(rand_num, 32)) & std_logic_vector(to_unsigned(rand_num, 32));

A clock cycle unwanted delay in incrementing counter withouth state machine

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.

How do you make vhdl counter that can count in tenths of a millisecond?

I am working on an IR Decoder in VHDL and I know that the widths of an IR 1 bit is 1.2 ms, an IR 0 bit is 0.6 ms, and the start bit is 2.5 ms. I am trying to make a counter that takes in the 50MHz clock and converts to tenths of a millisecond. How can I do this?
entity counter is
Port ( EN : in STD_LOGIC;
RESET : in STD_LOGIC;
CLK : in STD_LOGIC;
COUNT : out STD_LOGIC_VECTOR (4 downto 0));
end counter;
architecture Behavioral of counter is
constant max_count : integer := (2);
begin
startCounter: process(EN, RESET, CLK)
variable cnt : integer := 0;
variable div_cnt : integer := 0;
begin
if (RESET = '1') then
cnt := 0;
div_cnt := 0;
elsif (EN = '1' and rising_edge(CLK)) then
if (cnt = max_count) then
cnt := 0;
div_cnt:= div_cnt + 1;
else
cnt := cnt + 1;
end if;
end if;
COUNT <= conv_std_logic_vector(cnt, 5);
-- COUNT <= temp_count(16 downto 13);
end process startCounter;
end Behavioral;
Since you have a 50 MHz clock and want to generate a 0.1 msec pulse, you can use the ieee library, math_real, to compute the number of 50 MHz clocks to create a 0.1 msec pulse. Here's a code fragment.
library ieee;
use ieee.math_real.all;
-- omitting for clarity...
-- generate one clk cycle pulse with period of 0.1 msec
gen_0p1mspulse_p : process(Clk)
constant CLK_PERIOD : real := 1/50e6;
constant PULSE_PERIOD : real := 0.1e-3;
constant MAX_CNT : integer := INTEGER(PULSE_PERIOD/CLK_PERIOD);
variable cnt : integer range 0 to MAX_CNT-1 := 0;
begin
if rising_edge(Clk) then
if reset = '1' then
cnt := 0;
pulse_0p1msec <= '0';
else
pulse_0p1msec <= '0'; -- default value
if cnt < MAX_CNT-1 then
cnt := cnt + 1;
else
cnt := 0;
pulse_0p1msec <= '1';
end if;
end if;
end if;
end process;
-- logic using 0.1 msec pulse
your_logic_p : process(Clk)
begin
if rising_edge(Clk) then
if reset = '1' then
your_cnt := 0;
else
if pulse_0p1msec = '1' then
-- insert your logic here
end if;
end if;
end if;
end process;
I like to split up my VHDL processes so that they're short. I also prefer to use synchronous resets and enables since they synthesize to less hardware for Xilinx FPGAs as well as running at a higher clock rates. Hope that addresses your issue.

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.

VHDL infinite loop

I'm writing a small piece of code to take a 32 bit input and output 2 bits at a time. I believe I'm having infinite loop problems from the while loop, based on simulation attempts. Everything looks right to me, compared to other examples of loops I've looked at. Any clue what I could be doing wrong?
library ieee;
use ieee.std_logic_1164.all;
entity regA is
port(mpcnd: in std_logic_vector(31 downto 0);
clk: in std_logic;
twobits: out std_logic_vector(1 downto 0));
end regA;
architecture behavior of regA is
begin
process
variable count: integer;
begin
count := 0;
while (count < 32) loop
if rising_edge(clk) then
twobits(0) <= mpcnd(count);
twobits(1) <= mpcnd(count+1);
count := count + 2;
end if;
end loop;
end process;
end behavior;
for a process you need either a sensitivity list or a wait statement within. a (not synthesisable but simulatable) version of your process could look as follows:
process
variable count: integer;
begin
count := 0;
while (count < 32) loop
wait until rising_edge(clk);-- if rising_edge(clk) then
twobits(0) <= mpcnd(count);
twobits(1) <= mpcnd(count+1);
count := count + 2;
--end if;
end loop;
end process;

Resources