本质上,我的问题是:“这不是更容易吗? ”;什么是'this',如下(代码也是):
我想要一种“补码”计数器功能,用 VHDL 实现,它基本上会在每一步中反转/补码/不是计数器值,从而为测试提供稍微丰富的位模式。当然,我希望它是可综合的(因此计数器值可以分配给引脚)和可移植代码(即仅实现 IEEE 库,没有STD_LOGIC_ARITH
)。我也不想默认将所有都视为无符号(所以我想避免STD_LOGIC_UNSIGNED
)。
简而言之,这个计数器可以描述为:给定初始值 C[0],那么每个时钟滴答的值将是:
C[i+1] = not(C[i]) + ( ( C[i]<(Cmax/2) ) ? 0 : 1 )
...或者给定 C 是 16 位宽(这将导致无符号 Cmax = 65535 和 Cmax/2 = 32768),它也可以写成:
C[i+1] = 65535 - C[i] + ( ( C[i]<32768 ) ? 0 : 1 )
这里的诀窍是计数器应该只增加一次 - 如果它在互补和“正常”范围内都增加,那么不会发生任何变化(方程将在两个值之间“振荡”)。
因此,鉴于检查 C[i]<(Cmax/2) 与检查 C 的最高有效位(第 15 位)基本相同,我认为我可以使用以下方法在 VHDL 中轻松实现类似的东西:
Y <= not(Y) + Y(15);
男孩,我对“容易”的看法是不是错了:)
第一个问题是,上面的等式有可能以 65535+1 结尾,在这种情况下,结果需要 17 位(即溢出);就我而言,我只想截断/忽略任何“进位”。
这导致了使用什么的问题:
std_logic_vector
已定义补码not()
;但它没有+
定义(添加)natural
/integer
可能在内部占用 32 位,因此不必指定它们的位宽;它们支持算术+
,但不支持补码not()
- 我也试过
unsigned
,也有一些问题(不记得是哪个)
第 15 位(MSB)只有在 Y 为 时才能提取std_logic_vector
,在这种情况下,Y(15) 为单字节std_logic
- 但随后需要将其转换为integer
类型,否则+
未定义加法:|
所以,我目前的解决方案(如下)首先有两个计数器寄存器的副本;一个是SIGNAL wCntReg : STD_LOGIC_VECTOR(15 DOWNTO 0)
;另一个是SIGNAL tmp_na : natural
。然后:
- 有两个时钟:一个“主”@ 50 MHz,另一个是“计数器”时钟:主时钟 16 倍分频(3.125 MHz)。
- “计数器”时钟应在下降沿激活计数器值的计算
- 计算是通过
natural
变量执行的(从变量中复制STD_LOGIC_VECTOR
) - 显然,
std_logic
只有先转换为才能integer
转换为(我很幸运在网上std_logic_vector
找到了该功能)。vectorize
这里最讨厌的部分是如何将natural
变量值反馈回那个STD_LOGIC_VECTOR
;我可以构建的唯一有效命令是:
wCntReg <= std_logic_vector(to_unsigned(natural'pos(tmp_na), wCntReg'length));
...; 但是,请注意,此命令基本上是“设置”该值,下次运行同一命令时,该值将“生效” 。因此,它不能在“计数器”时钟进程中运行——在下面的代码中,我将它放在更快的“主”时钟进程中。
最后,下面的代码确实有效(通过 ISE WebPack 中的行为模拟) - 但是,我仍然想知道是否有更直接的方法来解决这个问题。
提前感谢您的任何答案,干杯!
编码:
----------------------------------------------------------------------------------
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 -----------------------------