4 位移位寄存器的 VHDL 输出遇到问题

问题描述 投票:0回答:2

我正在尝试用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;
bit-manipulation vhdl
2个回答
2
投票

我几乎肯定问题出在这一部分:

signal temp: std_logic_vector(3 downto 0):="0000"; -- initial value of output
begin
process (clock)
begin
O <= temp;

但我不知道如何解决它。

问题有点微妙。 O 分配实际上不是问题。要么 temp 与 temp 相同,要么 O 稍后会再次被分配。

任何仿真时间都只有一个预计输出波形值,两次分配将意味着最新的一个将取代较早的一个。

当任何进程尚未恢复或尚未挂起时,也不会发生信号更新。没有相对延迟(相当于 0 ns 之后)的信号更新不会在当前仿真周期内发生,而是在下一个仿真周期开始时发生。变量赋值立即发生。

所以你希望 temp 是在 process 语句中声明的变量。您还可以注意到,使用 VHDL -2008,您可以计算 O 并且不需要 temp。

您的代码中还有一些综合问题。虽然使用

clock = '1'
作为检测时钟上升沿的 if 语句条件可以成功进行模拟,但用于综合的约定是明确的。例如,您可以使用 std_logic_1164 包中定义的
rising_edge(clock)
,当输入信号从“0”转换为“1”(而不是从“X”转换为“1”等)时,它返回一个布尔值(用于条件评估)。 .

还有一个含义是,围绕时钟边沿 if 语句和带有使能的 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 语句替代方案都由一系列语句组成(IEEE Std 1076-2008 10.9 Case 语句)。

在 10.1 中,我们看到语句序列可以是空的,也可以是一个或多个连续语句(参见 1.3.2 语法描述 f),大括号中的项目出现零次或多次)。

如果您想明确表明此处没有发生任何事情,您可以使用 null 语句 (10.14)。

因为对 O 的赋值发生在 case 语句中 sel 的每个二进制值中,所以我们只需要一次赋值。如果它在进程的开始,则会导致半时钟延迟(直到下一个时钟事件)。

为了演示问题或更改后的代码是否有效,您可以使用测试平台,提供一个最小、完整且可验证的示例

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 值转换而来的值,以使波形显示更易于解释:

好消息是案例陈述替代方案中的表达式是有效的。


0
投票

如何添加 7 段显示屏来显示温度值?我编写了代码,但我得到了之前的时钟事件输出。

© www.soinside.com 2019 - 2024. All rights reserved.