4 位移位寄存器的 VHDL 输出有问题
Having trouble with a VHDL output for a 4 bit shift register
我正在尝试在 VHDL 中实现一个 4 位移位寄存器。我觉得我的实现对于实际的移动是正确的,但我的输出不起作用。每个出局都是“0”。
我一直在研究布局问题,但我对 VHDL 还很陌生。有什么想法吗?
我几乎肯定问题出在这一部分:
signal temp: std_logic_vector(3 downto 0):="0000"; -- initial value of output
begin
process (clock)
begin
O <= temp;
但我不确定如何修复它。
library ieee;
use ieee.std_logic_1164.all;
entity shift_reg is
port( I: in std_logic_vector (3 downto 0);
I_SHIFT_IN: in std_logic;
sel: in std_logic_vector(1 downto 0); -- 00:hold; 01: shift left; 10: shift right; 11: load
clock: in std_logic;
enable: in std_logic; -- 0: don't do anything; 1: shift_reg is enabled
O: out std_logic_vector(3 downto 0)
);
end shift_reg;
architecture behav of shift_reg is
signal temp: std_logic_vector(3 downto 0):="0000"; -- initial value of output
begin
process (clock)
begin
O <= temp;
if (enable = '1') then
if (clock='1') then --rising_edge(clock) and
case sel is
when "00" => -- hold
temp <= temp;
O <= temp;
when "01" => -- left shift
temp <= (temp(2 downto 0) & I_SHIFT_IN);
O <= (temp(2 downto 0) & I_SHIFT_IN);
when "10" => -- right shift
temp <= (I_SHIFT_IN & temp(3 downto 1));
O <= (I_SHIFT_IN & temp(3 downto 1));
when "11" => -- load
temp <= I;
O <= I;
when others => --other? exception handling? wouldn't compile without this
temp <= "1111";
O <= "1111";
end case;
end if;
--else null;
end if;
end process;
end behav;
I'm almost positive that problem is coming from this section:
signal temp: std_logic_vector(3 downto 0):="0000"; -- initial value of output
begin
process (clock)
begin
O <= temp;
But I'm not sure how to fix it.
问题有点微妙。 O分配实际上不是问题。要么 temp 与 what 相同,要么稍后再次分配 O。
任何模拟时间都只有一个预计输出波形值,两次分配意味着最新的将取代较早的。
当任何进程尚未恢复或尚未挂起时,也不会发生信号更新。没有相对延迟(相当于 0 ns 之后)的信号更新不会在当前仿真周期内发生,而是在下一个仿真周期开始时发生。变量赋值立即发生。
因此您希望 temp 是在 process 语句中声明的变量。您还可以注意到,使用 VHDL -2008,您可以评估 O 而不需要临时。
您的代码中还有一些综合问题。虽然它将使用 clock = '1'
作为检测时钟上升沿的 if 语句条件成功模拟,但用于合成的约定是明确的。例如,当输入信号从“0”转换为“1”(而不是从 'X' 到 '1',等等)。
还有一个含义是,如果语句和带有使能的 if 语句围绕时钟边沿,将导致门控时钟,而不是在综合中使用使能来推断存储。解决方法是交换两个 if 语句条件。
清理所有这些东西,你会得到类似的东西:
architecture behav of shift_reg is
-- signal temp: std_logic_vector(3 downto 0):="0000";
begin
process (clock)
variable temp: std_logic_vector(3 downto 0):="0000";
begin
-- O <= temp;
if rising_edge(clock) then
if enable = '1' then -- don't gate clock, enable
case sel is
when "00" => -- hold
temp := temp;
when "01" => -- left shift
temp := (temp(2 downto 0) & I_SHIFT_IN);
when "10" => -- right shift
temp := (I_SHIFT_IN & temp(3 downto 1));
when "11" => -- load
temp := I;
when others =>
-- temp <= "1111"; -- temp <= NULL; -- null statement
end case;
O <= temp;
end if;
end if;
end process;
end architecture behav;
您可能会注意到 case 语句中 others 选项下没有语句。每个 case 语句备选方案都由一系列语句组成(IEEE Std 1076-2008 10.9 Case 语句)。
在10.1下我们看到一系列语句可以是空的或一个或多个顺序语句(见1.3.2句法描述f),大括号中的项目出现零次或多次)。
如果你想明确地表明这里没有发生任何事情,你可以使用空语句 (10.14)。
因为对 O 的赋值发生在 case 语句中 sel 的每个二进制值中,所以我们只需要一个赋值。如果它在过程的开始,它会导致半个时钟延迟(直到下一个时钟事件)。
为了证明问题或更改后的代码有效,您可以使用测试台,提供 Minimal, Complete, and Verifiable example:
library ieee;
use ieee.std_logic_1164.all;
entity shift_reg_tb is
end entity;
architecture foo of shift_reg_tb is
signal I: std_logic_vector (3 downto 0);
signal I_SHIFT_IN: std_logic;
signal sel: std_logic_vector(1 downto 0);
signal clock: std_logic := '0';
signal enable: std_logic;
signal O: std_logic_vector(3 downto 0);
type op is (HOLD, LEFT, RIGHT, LOAD);
signal shftop: op;
use ieee.numeric_std.all;
begin
shftop <= op'val(to_integer(unsigned(sel)) );
DUT:
entity work.shift_reg
port map (
I => I,
I_SHIFT_IN => I_SHIFT_IN,
sel => sel,
clock => clock,
enable => enable,
O => O
);
CLOCK_PROC:
process
begin
wait for 5 ns;
clock <= not clock;
if now > 160 ns then
wait;
end if;
end process;
STIMULI:
process
begin
wait until rising_edge(clock);
I <= x"C";
I_SHIFT_IN <= '0';
enable <= '0';
sel <= "00"; -- HOLD
wait until rising_edge(clock);
enable <= '1';
wait until rising_edge(clock);
sel <= "11"; -- LOAD
wait until rising_edge(clock);
sel <= "10"; -- shift right
wait until rising_edge(clock);
wait until rising_edge(clock);
I_SHIFT_IN <= '1';
wait until rising_edge(clock);
wait until rising_edge(clock);
I_SHIFT_IN <= '0';
sel <= "01"; -- shift left
wait until rising_edge(clock);
wait until rising_edge(clock);
I_SHIFT_IN <= '1';
enable <= '1';
wait until rising_edge(clock);
wait until rising_edge(clock);
wait until rising_edge(clock);
wait until rising_edge(clock);
wait until rising_edge(clock);
wait until rising_edge(clock);
enable <= '0';
wait;
end process;
end architecture;
注意枚举类型的创建以定义移位寄存器操作,该类型的信号 (shftop) 被分配了从 sel 值转换的值以使波形显示更易于解释:
好消息是您的 case 语句替代项中的表达式是函数式的。
我正在尝试在 VHDL 中实现一个 4 位移位寄存器。我觉得我的实现对于实际的移动是正确的,但我的输出不起作用。每个出局都是“0”。
我一直在研究布局问题,但我对 VHDL 还很陌生。有什么想法吗?
我几乎肯定问题出在这一部分:
signal temp: std_logic_vector(3 downto 0):="0000"; -- initial value of output
begin
process (clock)
begin
O <= temp;
但我不确定如何修复它。
library ieee;
use ieee.std_logic_1164.all;
entity shift_reg is
port( I: in std_logic_vector (3 downto 0);
I_SHIFT_IN: in std_logic;
sel: in std_logic_vector(1 downto 0); -- 00:hold; 01: shift left; 10: shift right; 11: load
clock: in std_logic;
enable: in std_logic; -- 0: don't do anything; 1: shift_reg is enabled
O: out std_logic_vector(3 downto 0)
);
end shift_reg;
architecture behav of shift_reg is
signal temp: std_logic_vector(3 downto 0):="0000"; -- initial value of output
begin
process (clock)
begin
O <= temp;
if (enable = '1') then
if (clock='1') then --rising_edge(clock) and
case sel is
when "00" => -- hold
temp <= temp;
O <= temp;
when "01" => -- left shift
temp <= (temp(2 downto 0) & I_SHIFT_IN);
O <= (temp(2 downto 0) & I_SHIFT_IN);
when "10" => -- right shift
temp <= (I_SHIFT_IN & temp(3 downto 1));
O <= (I_SHIFT_IN & temp(3 downto 1));
when "11" => -- load
temp <= I;
O <= I;
when others => --other? exception handling? wouldn't compile without this
temp <= "1111";
O <= "1111";
end case;
end if;
--else null;
end if;
end process;
end behav;
I'm almost positive that problem is coming from this section:
signal temp: std_logic_vector(3 downto 0):="0000"; -- initial value of output begin process (clock) begin O <= temp;
But I'm not sure how to fix it.
问题有点微妙。 O分配实际上不是问题。要么 temp 与 what 相同,要么稍后再次分配 O。
任何模拟时间都只有一个预计输出波形值,两次分配意味着最新的将取代较早的。
当任何进程尚未恢复或尚未挂起时,也不会发生信号更新。没有相对延迟(相当于 0 ns 之后)的信号更新不会在当前仿真周期内发生,而是在下一个仿真周期开始时发生。变量赋值立即发生。
因此您希望 temp 是在 process 语句中声明的变量。您还可以注意到,使用 VHDL -2008,您可以评估 O 而不需要临时。
您的代码中还有一些综合问题。虽然它将使用 clock = '1'
作为检测时钟上升沿的 if 语句条件成功模拟,但用于合成的约定是明确的。例如,当输入信号从“0”转换为“1”(而不是从 'X' 到 '1',等等)。
还有一个含义是,如果语句和带有使能的 if 语句围绕时钟边沿,将导致门控时钟,而不是在综合中使用使能来推断存储。解决方法是交换两个 if 语句条件。
清理所有这些东西,你会得到类似的东西:
architecture behav of shift_reg is
-- signal temp: std_logic_vector(3 downto 0):="0000";
begin
process (clock)
variable temp: std_logic_vector(3 downto 0):="0000";
begin
-- O <= temp;
if rising_edge(clock) then
if enable = '1' then -- don't gate clock, enable
case sel is
when "00" => -- hold
temp := temp;
when "01" => -- left shift
temp := (temp(2 downto 0) & I_SHIFT_IN);
when "10" => -- right shift
temp := (I_SHIFT_IN & temp(3 downto 1));
when "11" => -- load
temp := I;
when others =>
-- temp <= "1111"; -- temp <= NULL; -- null statement
end case;
O <= temp;
end if;
end if;
end process;
end architecture behav;
您可能会注意到 case 语句中 others 选项下没有语句。每个 case 语句备选方案都由一系列语句组成(IEEE Std 1076-2008 10.9 Case 语句)。
在10.1下我们看到一系列语句可以是空的或一个或多个顺序语句(见1.3.2句法描述f),大括号中的项目出现零次或多次)。
如果你想明确地表明这里没有发生任何事情,你可以使用空语句 (10.14)。
因为对 O 的赋值发生在 case 语句中 sel 的每个二进制值中,所以我们只需要一个赋值。如果它在过程的开始,它会导致半个时钟延迟(直到下一个时钟事件)。
为了证明问题或更改后的代码有效,您可以使用测试台,提供 Minimal, Complete, and Verifiable example:
library ieee;
use ieee.std_logic_1164.all;
entity shift_reg_tb is
end entity;
architecture foo of shift_reg_tb is
signal I: std_logic_vector (3 downto 0);
signal I_SHIFT_IN: std_logic;
signal sel: std_logic_vector(1 downto 0);
signal clock: std_logic := '0';
signal enable: std_logic;
signal O: std_logic_vector(3 downto 0);
type op is (HOLD, LEFT, RIGHT, LOAD);
signal shftop: op;
use ieee.numeric_std.all;
begin
shftop <= op'val(to_integer(unsigned(sel)) );
DUT:
entity work.shift_reg
port map (
I => I,
I_SHIFT_IN => I_SHIFT_IN,
sel => sel,
clock => clock,
enable => enable,
O => O
);
CLOCK_PROC:
process
begin
wait for 5 ns;
clock <= not clock;
if now > 160 ns then
wait;
end if;
end process;
STIMULI:
process
begin
wait until rising_edge(clock);
I <= x"C";
I_SHIFT_IN <= '0';
enable <= '0';
sel <= "00"; -- HOLD
wait until rising_edge(clock);
enable <= '1';
wait until rising_edge(clock);
sel <= "11"; -- LOAD
wait until rising_edge(clock);
sel <= "10"; -- shift right
wait until rising_edge(clock);
wait until rising_edge(clock);
I_SHIFT_IN <= '1';
wait until rising_edge(clock);
wait until rising_edge(clock);
I_SHIFT_IN <= '0';
sel <= "01"; -- shift left
wait until rising_edge(clock);
wait until rising_edge(clock);
I_SHIFT_IN <= '1';
enable <= '1';
wait until rising_edge(clock);
wait until rising_edge(clock);
wait until rising_edge(clock);
wait until rising_edge(clock);
wait until rising_edge(clock);
wait until rising_edge(clock);
enable <= '0';
wait;
end process;
end architecture;
注意枚举类型的创建以定义移位寄存器操作,该类型的信号 (shftop) 被分配了从 sel 值转换的值以使波形显示更易于解释:
好消息是您的 case 语句替代项中的表达式是函数式的。