使用结构设计制作加减柜台

Make an up down counter using structural design

我尝试使用结构设计制作一个 4 位加减计数器。 我的代码如下:

entity counter4bit is
    Port ( clock : in  STD_LOGIC;
           reset : in  STD_LOGIC;
           load : in  STD_LOGIC;
           enable : in  STD_LOGIC;
           counterOut : out  STD_LOGIC_VECTOR (3 downto 0);
           updown : in  STD_LOGIC);
end counter4bit;

architecture Behavioral of counter4bit is

component D_FlipFlop
    Port ( d : in  STD_LOGIC;
           reset : in  STD_LOGIC;
           clock : in  STD_LOGIC;
           load : in  STD_LOGIC;
           enable : in  STD_LOGIC;
           updown : in  STD_LOGIC;
           q : out  STD_LOGIC);
end component;

component MUX 
    Port ( i0 : in  STD_LOGIC; 
           i1 : in  STD_LOGIC; 
           i2 : in  STD_LOGIC; 
           i3 : in  STD_LOGIC;
           inload : in  STD_LOGIC;
           bitout : out  STD_LOGIC;
           load : in  STD_LOGIC;
           updown : in  STD_LOGIC;
           en : in  STD_LOGIC);
end component;

signal w: std_logic_vector(3 downto 0);
signal cnt : std_logic_vector(3 downto 0);

begin

FF0 : D_FlipFlop
    port map( d => w(0),
                 reset => reset,
                 clock =>clock,
                 load => load,
                 enable => enable,
                 updown => updown,
                 q => cnt(0) );

FF1 : D_FlipFlop
    port map( d => w(1),
                 reset => reset,
                 Clock => clock,
                 load => load,
                 enable => enable,
                 updown => updown,
                 q => cnt(1));

FF2 : D_FlipFlop
    port map( d => w(2),
                 reset => reset,
                 clock => clock,
                 load => load,
                 enable => enable,
                 updown => updown,
                 q => cnt(2));

FF3 : D_FlipFlop
    port map( d => w(3),
                 reset => reset,
                 clock => clock,
                 load => load,
                 enable => enable,
                 updown => updown,
                 q => cnt(3));

MUX0 : MUX
    port map( i0 => '1',
                 i1 => '1',
                 i2 => '1',
                 i3 => cnt(0),
                 inload => '1',
                 bitout =>w(0) ,
                 load => load,
                 updown => updown,
                 en => enable);

MUX1 : MUX
    port map( i0 => cnt(0),
                 i1 =>'1',
                 i2 => '1',
                 i3 => cnt(1),
                 inload => '1',
                 bitout =>w(1) ,
                 load => load,
                 updown => updown,
                 en => enable); 

MUX2 : MUX
    port map( i0 => cnt(0),
                 i1 => cnt(1),
                 i2 =>  '1',
                 i3 => cnt(2),
                 inload => '0',
                 bitout =>w(2) ,
                 load => load,
                 updown => updown,
                 en => enable);

MUX3 : MUX
    port map( i0 => cnt(0),
                 i1 => cnt(1),
                 i2 =>cnt(2),
                 i3 => cnt(3),
                 inload => '0',
                 bitout =>w(3) ,
                 load => load,
                 updown => updown,
                 en => enable);

counterOut <= cnt ;

end Behavioral;

当我模拟它时,它从 0 开始,因为它应该导致重置,然后计数到 1,然后再次计数到 0。我不明白为什么它在 1 之后又回到 0。

这是我的 mux 代码:

entity MUX is
    Port ( i0 : in  STD_LOGIC; 
           i1 : in  STD_LOGIC; 
           i2 : in  STD_LOGIC; 
           i3 : in  STD_LOGIC;
           inload : in  STD_LOGIC;
           bitout : out  STD_LOGIC;
           load : in  STD_LOGIC;
           updown : in  STD_LOGIC;
           en : in  STD_LOGIC);
end MUX;

architecture Behavioral of MUX is
signal  sel : std_logic_vector(1 downto 0);
signal y, z, x: std_logic;
begin

y <= (updown and i0 and i1 and i2 and en);
z <= (not updown) and i0 and i1 and i2 and en;

sel(0) <= not load;
sel(1) <= y or z ;

process(sel, x)
    begin 
        if sel = "00" then x<= i3;
        elsif sel = "01" then x <= (not i3);
        else    x <= inload;
        end if;
    end process;
    bitout <= x ;
end Behavioral;

触发器的代码:

entity D_FlipFlop is
    Port ( d : in  STD_LOGIC;
           reset : in  STD_LOGIC;
           clock : in  STD_LOGIC;
           load : in  STD_LOGIC;
           enable : in  STD_LOGIC;
           updown : in  STD_LOGIC;
           q : out  STD_LOGIC);
end D_FlipFlop;

architecture Behavioral of D_FlipFlop is

begin

process(clock, reset)
begin
    if (reset = '0') then
        q <= '0';
    elsif (rising_edge(clock)) then
        q <= d;
    end if;
end process;

end Behavioral;

需要注意的是load和enable是同步的,reset是异步的,我也会附上一张我的仿真图。

When I simulate it it starts from 0 as it should cause of the reset , then counts to 1 and then again 0 . I can't see why it goes back to 0 after 1.

我修改了昨天的测试台以复制您的波形:

我不得不修改重置为“0”到“1”和“1”到“0”的一组增量循环,以使计数器显示为全“0”。

首先要注意的是你的复位极性错误。

修正给出:

我们可以看到计数没有正确增加并且仍然停止。

在不考虑负载极性的情况下,停滞值是由 MUX 中进程的敏感列表引起的:

process(sel, x)
    begin 
        if sel = "00" then x<= i3;
        elsif sel = "01" then x <= (not i3);
        else    x <= inload;
        end if;
    end process;
    bitout <= x ;
end Behavioral;

应该有一个敏感度列表:

 process (sel, i3, inload) -- was (sel, x) -- incorrect sensitivity list

这会产生:

仍然缺少增量显示,但确实有变化。

在测试台中将加载值更改为“0”会在反击时为我们提供丢失的事务,但值仍然是错误的:

这告诉我们您的 select 方程式错误或您的多路复用器输入错误或两者的某种组合。

无论如何,MUX 似乎是您应该关注的地方。

因此,通过在 MUX 中输入您的 select 更改,您在评论中告诉我们,您可以获得正确的计数:

-- sel(0) <= not load;
-- sel(1) <= y or z ;
sel(1) <= (not load);  -- per comments
sel(0) <= y or z; 

我们得到:

显示向上计数正确但向下计数不正确。请注意负载的极性在 select 秒内已更改,并与上面的波形匹配。

现在我们知道我们应该根据 updown 增加或减少 cnt,

y <= updown and i0 and i1 and i2 and en;

用于向上计数,剩下

z <= not updown and i0 and i1 and i2 and en;

不幸的是,它在 i0、i1 和 i2 上使用相同的值来切换位输出(特定 cnt 元素的相应 D_FlipFlop 的输入)。

我们相当确定 z 想成为:

z <= not updown and not i0 and not i1 and not i2 and en;

用于递减(不是递增)。

当我们进行更改时,计数不起作用。我们需要 MUX 的未使用输入是 updown 的正确值,“1”表示向上(如现在))或“0”表示向下。

我们可以在 counter4bit 中使用 updown 来做到这一点:

MUX0 : MUX
    port map( i0 => updown, -- '1'
                 i1 => updown, -- '1',
                 i2 => updown, -- '1',
                 i3 => cnt(0),
                 inload => '1',
                 bitout =>w(0) ,
                 load => load,
                 updown => updown,
                 en => enable);

MUX1 : MUX
    port map( i0 => cnt(0),
                 i1 => updown,  -- '1',
                 i2 => updown, -- '1',
                 i3 => cnt(1),
                 inload => '1',
                 bitout =>w(1) ,
                 load => load,
                 updown => updown,
                 en => enable); 

MUX2 : MUX
    port map( i0 => cnt(0),
                 i1 => cnt(1),
                 i2 => updown, -- '1',
                 i3 => cnt(2),
                 inload => '0',
                 bitout =>w(2) ,
                 load => load,
                 updown => updown,
                 en => enable);

这给了我们:

注意此波形尚未测试加载或启用 (false),但它会向上计数,然后成功返回。

D_FlipFlop(加载、启用、上行)上还有一些未使用的端口。