Essentially, my question is: "Is it easier to do this?"; and that 'this' follows below (code too):
I wanted to have the add-on counter function implemented in VHDL, which basically inverted / supplemented / not the value of the counter at each step, providing somewhat richer bit samples for testing. Of course, I wanted this to be synthesized (so that the counter value can be assigned to contacts) and portable code (i.e. only IEEE libraries, no STD_LOGIC_ARITH ). I also do not want to treat everything as unsigned by default (so I would like to avoid STD_LOGIC_UNSIGNED ).
In short, this counter can be described as follows: a given initial value C [0], then the values ​​on each measure will be:
C[i+1] = not(C[i]) + ( ( C[i]<(Cmax/2) ) ? 0 : 1 )
... or if C is 16 bits wide (which will result in unsigned Cmax = 65535 and Cmax / 2 = 32768), it can also be written as:
C[i+1] = 65535 - C[i] + ( ( C[i]<32768 ) ? 0 : 1 )
The trick here is that the counter should only increase once - if it increases for both additional and “normal” ranges, then no changes will occur (the equation will “fluctuate” between the two values).
So, given that checking C [i] <(Cmax / 2) is basically the same as checking the most significant (15th) bit of C, I thought I could easily implement something like this in VHDL using something- how:
Y <= not(Y) + Y(15);
Boy, I was wrong about "easy" :)
The first problem is that it is possible that the above equation can end at 65535 + 1, in which case the result will require 17 bits (i.e., overflow); in my case, I would just like to truncate / ignore any "carry bits".
This leads to a usage problem:
std_logic_vector has a not() complement defined; but it does not have + (complement) definednatural / integer can internally accept 32 bits, and since such a bit width is not necessarily specified for them; they support arithmetic + , but do not complement not()- I tried
unsigned too, had some problems as well (can't remember which one)
The 15th bit (MSB) can be extracted only when Y is std_logic_vector , in which case Y (15) is a single std_logic - but then it must be converted to integer type, because otherwise the addition of + not defined: |
So my current solution (below) first has two counter copies; one is SIGNAL wCntReg : STD_LOGIC_VECTOR(15 DOWNTO 0) ; the other is SIGNAL tmp_na : natural . Then:
- There are two clock cycles: one “main” with a frequency of 50 MHz, the other - “counter”: the main 16-fold frequency is divided (3.125 MHz).
- The counter clock must activate the calculation of the counter value from the falling edge
- The calculation is performed using the variable
natural (which copies with std_logic_vector ) - Apparently
std_logic can only be converted to integer if it is first converted to std_logic_vector (I was lucky enough to find the vectorize function on the network).
The most unpleasant part here was how to return the value of the variable natural , back to std_logic_vector ; the only working team that I could build is:
wCntReg <= std_logic_vector(to_unsigned(natural'pos(tmp_na), wCntReg'length));
...; however, note that this command basically “sets” the value that will be “implemented” the next time the same command is executed. Thus, it cannot work in the "counter" mode - in the code below, I have this in a faster "hourly" process.
Finally, the code below works (goes through behavioral modeling in ISE WebPack), but I would still like to know if there is an easier way to solve this problem.
Thanks in advance for any answers, Hooray!
Code:
---------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; -- use IEEE.STD_LOGIC_ARITH.ALL; -- use IEEE.STD_LOGIC_UNSIGNED.ALL; use IEEE.NUMERIC_STD.ALL; ENTITY complement_count_test_tbw IS END complement_count_test_tbw; ARCHITECTURE testbench_arch OF complement_count_test_tbw IS -- http://www.ingenieurbuero-eschemann.de/downloads/ipicregs/example/vhdl/test/timer_regs_tb.vhd -- convert std_logic to std_logic_vector(0 downto 0) function vectorize(s: std_logic) return std_logic_vector is variable v: std_logic_vector(0 downto 0); begin v(0) := s; return v; end; -- DECLARE REGISTERS ========================== -- 'wires' SIGNAL wtCLK : std_logic := '0'; -- counter register: 16 bit SIGNAL wCntReg : STD_LOGIC_VECTOR(15 DOWNTO 0) := (others => 'Z'); -- temporary 'natural' copy of counter register -- http://www.velocityreviews.com/forums/t21700-std_logic_vector-to-unsigned-type-casting.html SIGNAL tmp_na : natural; -- clock parameters constant PERIODN : natural := 20; -- can be real := 20.0; constant PERIOD : time := PERIODN * 1 ns; constant DUTY_CYCLE : real := 0.5; constant OFFSET : time := 100 ns; -- freq divisor; with initial values constant fdiv : natural := 16; SIGNAL fdiv_cnt : natural := 1; SIGNAL wfdiv_CLK : std_logic := '0'; BEGIN -- initializations of connections: -- instances of components, and their wiring (port maps)... -- END instances of components, and their wiring (port maps)... -- PROCESSES (STATE MACHINES) CODE ========= -- clock process for generating CLK PROCESS BEGIN WAIT for OFFSET; CLOCK_LOOP : LOOP wtCLK <= '0'; -- MUST refresh counter reg here with value of tmp_na wCntReg <= std_logic_vector(to_unsigned(natural'pos(tmp_na), wCntReg'length)); WAIT FOR (PERIOD - (PERIOD * DUTY_CYCLE)); wtCLK <= '1'; WAIT FOR (PERIOD * DUTY_CYCLE); END LOOP CLOCK_LOOP; END PROCESS; -- freq divided clock freq_divisor: PROCESS(wtCLK) BEGIN IF rising_edge(wtCLK) THEN -- posedge IF fdiv_cnt = fdiv THEN -- reset fdiv_cnt <= 1 ; wfdiv_CLK <= not(wfdiv_CLK); ELSE fdiv_cnt <= fdiv_cnt + 1; END IF; END IF; END PROCESS freq_divisor; -- sim: count PROCESS BEGIN WAIT for 10 ns; tmp_na <= 125; WAIT for 10 ns; TESTCOUNT_LOOP: LOOP -- change counter on negedge of freq. divided clock WAIT until falling_edge(wfdiv_CLK); tmp_na <= to_integer(unsigned(not(wCntReg))) + to_integer(unsigned(vectorize(wCntReg(15)))); WAIT for 10 ns; END LOOP TESTCOUNT_LOOP; END PROCESS; -- END PROCESSES (STATE MACHINES) CODE ===== -- END IMPLEMENT ENGINE of 'CORE' =============== END testbench_arch; -- END ARCHITECTURE -----------------------------