用于32 x 8寄存器VHDL的嵌套生成语句

时间:2014-03-29 23:13:42

标签: vhdl

我的电路有一个32 x 8 D触发网格。每行应产生一个32位向量,其中包含来自D-ff的Q值 - 然后将其发送到8x1 MUX。以下代码是我试图正确生成32 x 8 D触发器并测试我是否可以从中获取一个向量(32位I0向量)。

我试图编写实现的电路可以在这个问题的贴图中看到: test bench of a 32x8 register file VHDL

library ieee;
use ieee.std_logic_1164.all;

entity REG is
port (
    REG_WRT     : in std_logic;
    WRT_REG_NUM : in std_logic_vector(2 downto 0);
    WRT_DATA    : in std_logic_vector(31 downto 0);
    READ_REG_A  : in std_logic_vector(2 downto 0);
    READ_REG_B  : in std_logic_vector(2 downto 0);
    PORT_A      : out std_logic_vector(31 downto 0);
    PORT_B      : out std_logic_vector(31 downto 0)
);
end REG;

architecture BEHV_32x8_REG of REG is
-- decoder component
component DCDR
    port (
        I_in    : in std_logic_vector(2 downto 0);
        O_out   : out std_logic_vector(7 downto 0)
    );
end component;
-- D flip flop component
component D_FF
    port (
        D_in    : in    std_logic;
        CLK     : in    std_logic;
        Q_out   : out   std_logic;
        QN_out  : out   std_logic   -- Q not
    );
end component;
-- MUX copmonent
component MUX
    port (
        S_in                            : in std_logic_vector(2 downto 0);
        I7, I6, I5, I4, I3, I2, I1, I0  : in std_logic_vector(31 downto 0);
        O_out                           : out std_logic_vector(31 downto 0)
    );
end component;

-- internal signals used
signal I_in     : std_logic_vector(2 downto 0);
signal O_out    : std_logic_vector(7 downto 0);
signal CLK_vals : std_logic_vector(7 downto 0);
signal MUXA_O_out : std_logic_vector(31 downto 0);
signal MUXB_O_out : std_logic_vector(31 downto 0);

-- two arrays of eight 32 bit vectors - the Q and QN outputs of all D_FFs
type reg_array is array (0 to 7) of std_logic_vector(31 downto 0);
signal Q, QN: reg_array;

begin

-- decoder instance
DCDR1 : DCDR port map(I_in, O_out);

GEN_D_FF:
for ROW in 0 to 7 generate
begin
    GEN_D_FF0:
    for COL in 0 to 31 generate
    begin
        DFF_X : D_FF port map(WRT_DATA(COL), CLK_vals(ROW), Q(ROW)(COL), QN(ROW)(COL));
    end generate GEN_D_FF0;
end generate GEN_D_FF;

DCDR_AND : process(O_out, REG_WRT)
begin

    I_in <= WRT_REG_NUM;
    for I in 0 to 7 loop
        CLK_vals(I) <= O_out(I) and not REG_WRT;
    end loop;
end process DCDR_AND;

-- MUX instances
MUX_A : MUX port map(READ_REG_A, Q(7), Q(6), Q(5), Q(4), Q(3), Q(2), Q(1), Q(0), MUXA_O_out);
MUX_B : MUX port map(READ_REG_B, Q(7), Q(6), Q(5), Q(4), Q(3), Q(2), Q(1), Q(0), MUXB_O_out);

process(MUXA_O_out, MUXB_O_out)
begin

    PORT_A <= MUXA_O_out;
    PORT_B <= MUXB_O_out;

end process;

end BEHV_32x8_REG;

当我在ModelSim中模拟上面的代码时,我没有获得I0的任何输出。我的设计在哪里有缺陷?我是否违反了任何VHDL最佳做法?假设我可以正常运行,我怎么能得到8个不同的32位向量(来自每一排触发器)发送到MUX?

我感谢我收到的任何建议!

编辑:我已更新代码以反映答案中给出的建议

1 个答案:

答案 0 :(得分:2)

你有8个ROW的32位COL连接到I0。如果没有D_FF的重置输入,您必须写入所有8行才能获得&#39; X而不是&#39; U&#39; < / p>

您的MUX未针对任一读取端口进行实例化。如果要实现数组值:

type reg_array is array (0 to 7) of std_logic_vector(31 downto 0);
signal Q,QN: reg_array;

这些会取代I0Q_out

从引用的答案(您显然只是标记为有用 - 谢谢),您可以使用I0(COL)替换内部生成语句中的QN_out(COL)实例中的D_FFQ(ROW)(COL)QN(ROW)(COL)

注意如果您未使用D_FF的Q NOT输出,则不能将它们作为端口提供或不连接它们(open)。您还可以将Q输出用于其他读取MUX的一个读取QNMUX输出,从而反转该MUX的输出。只有两个端口,您不会显着减少负载,您可以使用Q

对于MUX使用信号Q定义为上面的reg_array,MUX输入将是Q(0)Q(7),输出可以是PORT_APORT_BS_in将分别与READ_REG_AREAD_REG_B相关联。

在阅读您的VHDL设计说明时,有一点不明显的原因是您的流程wait for 10 ns中存在DCDR_AND的原因?它将写入延迟超过CLK的低波特率(时钟的低部分)。在零时间模型中,您只需使用not CLK代替CLKCLK_vals(I) <= O_out(I) and not CLK,删除wait for 10 ns;行。对于合成产生的定时模型,wait无法合成。如果您打算进行综合,如果CLK是时钟同步的话,可以依靠输入保持,可以使用WR_DATA

然后您的模型已经离散地实例化了D_FF并使用MUX es作为读取端口。

我拒绝修改你的代码的冲动,并且在你进行同一课堂练习的情况下显示它。如果其中任何一个不清楚,请在对此答案的评论中提出,并且我将添加到答案中,明确标记对其的任何更正或在必要时演示代码。

回应评论&#34; ...但我仍然看到UUU为PORT_A和PORT_B&#34;

reg_tb.png

请注意,REG_WRT已经显示为来自之前工作的测试平台的反转时钟,因此我删除了前一个not进程DCDR_AND,否则使用之前的努力测试平台除了匹配您的端口名称之外没有变化。

另请注意,PORT_APORT_B输出在写入地址(READ_REG_AREAD_REG_B)之前保持未初始化状态,这是特定测试平台的重点

在时钟单元(REG_WRT)中间写入触发器(统称为8个32位寄存器)的想法是避免时钟偏移问题,在写入输入引起的测试平台的情况下基于延迟值而不是时钟边缘。

您可以在时钟进程中同样拥有激励,这可能需要平衡时钟延迟以确保WRT_DATAWRT_REG_NUM在正确的时间有效。这也可以通过不使用REG_WRT来解决。

如果您在测试平台上REG_WRT使用直立时钟而不是倒置时钟,则可以让not进入DCDR_AND

还有并发信号赋值语句,它们偶然可以进入生成语句,允许进程DCDR_AND折叠到第一个生成语句中:

GEN_D_FF:
    for ROW in 0 to 7 generate
    begin
GEN_D_FF0:
        for COL in 0 to 31 generate
        begin
DFF_X:  
            D_FF 
            port map(
                D_in => WRT_DATA(COL), 
                CLK => CLK_vals(ROW), 
                Q_out => Q(ROW)(COL), 
                QN_out => QN(ROW)(COL)
            );
        end generate;
DCDR_AND:
        CLK_vals(ROW) <= O_out(ROW) and REG_WRT;

    end generate;

-- DCDR_AND: 
--     process (O_out, REG_WRT)
--     begin
--
--         I_in <= WRT_REG_NUM;
--         for I in 0 to 7 loop
--             CLK_vals(I) <= O_out(I) and REG_WRT;
--         end loop;
-- end process;

也可以在PORT_A和PORT_B分配中使用,而不是在进程语句中使用。您还可以在两个MUX实例中将PORT_A和PORT_B指定为O_out,从而消除并发信号分配或进程,例如:

MUX_A: 
    MUX 
        port map ( 
            S_in => READ_REG_A, 
            I7 => Q(7), 
            I6 => Q(6), 
            I5 => Q(5), 
            I4 => Q(4), 
            I3 => Q(3), 
            I2 => Q(2), 
            I1 => Q(1), 
            I0 => Q(0), 
            O_out => Port_A
        );

您可以这样做,因为您没有在内部使用读取端口数据,端口是模式out

在执行此操作时,我发现如上所述取消I_in的分配可能会导致您的读取端口上的所有'U'都可以被类似地修复:

DCDR1: 
    DCDR 
    port map (
        I_in => WRT_REG_NUM, 
        O_out => O_out
    );

允许消除I_in,MUXA_O_out和MUXB_O_out的信号声明:

-- internal signals used

-- signal I_in:        std_logic_vector(2 downto 0);
signal O_out:       std_logic_vector(7 downto 0);
signal CLK_vals:    std_logic_vector(7 downto 0);
-- signal MUXA_O_out:  std_logic_vector(31 downto 0);
-- signal MUXB_O_out:  std_logic_vector(31 downto 0);

我没有在读取端口上始终有'U' s的情况,除非我在WRT_REG_NUM中意外删除了CLK_vals,如上所述。< / p>

我没有完成美化你的代码:

library ieee;
use ieee.std_logic_1164.all;

entity DCDR is
    port (
        I_in:   in  std_logic_vector (2 downto 0);
        O_out:  out std_logic_vector (7 downto 0)
    );
end entity;

architecture foo of DCDR is
    signal input:   std_logic_vector (2 downto 0);
begin
    input <= TO_X01Z(I_in);

    O_out <= "00000001"  when input = "000" else
             "00000010"  when input = "001" else
             "00000100"  when input = "010" else
             "00001000"  when input = "011" else
             "00010000"  when input = "100" else
             "00100000"  when input = "101" else
             "01000000"  when input = "110" else
             "10000000"  when input = "111" else
             (others => 'X');

end architecture;

library ieee;
use ieee.std_logic_1164.all;

entity D_FF is
    port (
        D_in:     in    std_logic;
        CLK:      in    std_logic;
        Q_out:    out   std_logic;
        QN_out:   out   std_logic
    );
end entity;

architecture foo of D_FF is

    signal Q:   std_logic;

begin

FF:
    process (CLK)
    begin
        if CLK'EVENT and CLK = '1' then
            Q <= D_in;
        end if;
    end process;

    Q_out <= Q;
    QN_out <= not Q;

end architecture;

library ieee;
use ieee.std_logic_1164.all;

entity MUX is
    port (
        S_in:                             in  std_logic_vector(2 downto 0);
        I7, I6, I5, I4, I3, I2, I1, I0:   in  std_logic_vector(31 downto 0);
        O_out:                            out std_logic_vector(31 downto 0)
    );
end entity;

architecture foo of MUX is

begin
    O_out <= I0 when S_in = "000" else
             I1 when S_in = "001" else
             I2 when S_in = "010" else
             I3 when S_in = "011" else
             I4 when S_in = "100" else
             I5 when S_in = "101" else
             I6 when S_in = "110" else
             I7 when S_in = "111" else
             (others => 'X');

end architecture;

library ieee;
use ieee.std_logic_1164.all;

entity REG is
port (
    REG_WRT:        in  std_logic;
    WRT_REG_NUM:    in  std_logic_vector(2 downto 0);
    WRT_DATA:       in  std_logic_vector(31 downto 0);
    READ_REG_A:     in  std_logic_vector(2 downto 0);
    READ_REG_B:     in  std_logic_vector(2 downto 0);
    PORT_A:         out std_logic_vector(31 downto 0);
    PORT_B:         out std_logic_vector(31 downto 0)
);
end REG;

architecture BEHV_32x8_REG of REG is
-- decoder component
component DCDR
    port (
        I_in:       in  std_logic_vector(2 downto 0);
        O_out:      out std_logic_vector(7 downto 0)
    );
end component;
-- D flip flop component
component D_FF
    port (
        D_in:       in    std_logic;
        CLK:        in    std_logic;
        Q_out:      out   std_logic;
        QN_out:     out   std_logic   -- Q not
    );
end component;
-- MUX component
component MUX
    port (
        S_in:                            in std_logic_vector(2 downto 0);
        I7, I6, I5, I4, I3, I2, I1, I0:  in std_logic_vector(31 downto 0);
        O_out:                           out std_logic_vector(31 downto 0)
    );
end component;

-- internal signals used

-- signal I_in:        std_logic_vector(2 downto 0);
signal O_out:       std_logic_vector(7 downto 0);
signal CLK_vals:    std_logic_vector(7 downto 0);
-- signal MUXA_O_out:  std_logic_vector(31 downto 0);
-- signal MUXB_O_out:  std_logic_vector(31 downto 0);

-- two arrays of eight 32 bit vectors - the Q and QN outputs of all D_FFs

type reg_array is array (0 to 7) of std_logic_vector(31 downto 0);
signal Q, QN: reg_array;

begin

-- decoder instance
DCDR1: 
    DCDR 
    port map (
        I_in => WRT_REG_NUM, 
        O_out => O_out
    );

GEN_D_FF:
    for ROW in 0 to 7 generate
    begin
GEN_D_FF0:
        for COL in 0 to 31 generate
        begin
DFF_X:  
            D_FF 
            port map(
                D_in => WRT_DATA(COL), 
                CLK => CLK_vals(ROW), 
                Q_out => Q(ROW)(COL), 
                QN_out => QN(ROW)(COL)
            );
        end generate;

        CLK_vals(ROW) <= O_out(ROW) and REG_WRT;

    end generate;

-- DCDR_AND: 
--     process (O_out, REG_WRT)
--     begin
-- 
--         I_in <= WRT_REG_NUM;
--         for I in 0 to 7 loop
--             CLK_vals(I) <= O_out(I) and REG_WRT;
--         end loop;
-- end process;

-- MUX instances
MUX_A: 
    MUX 
        port map ( 
            S_in => READ_REG_A, 
            I7 => Q(7), 
            I6 => Q(6), 
            I5 => Q(5), 
            I4 => Q(4), 
            I3 => Q(3), 
            I2 => Q(2), 
            I1 => Q(1), 
            I0 => Q(0), 
            O_out => Port_A
        );

MUX_B: 
    MUX 
        port map ( 
        S_in => READ_REG_B, 
        I7 => Q(7), 
        I6 => Q(6), 
        I5 => Q(5), 
        I4 => Q(4), 
        I3 => Q(3), 
        I2 => Q(2), 
        I1 => Q(1), 
        I0 => Q(0), 
        O_out => Port_B
        );

end architecture;

library ieee; 
use ieee.std_logic_1164.all; 

entity reg_tb is    
end entity; 

architecture fum of reg_tb is 

component REG
    port (  
        REG_WRT:        in  std_logic; 
        WRT_REG_NUM:    in  std_logic_vector (2 downto 0);
        WRT_DATA:       in  std_logic_vector (31 downto 0);
        READ_REG_A:     in  std_logic_vector (2 downto 0);
        READ_REG_B:     in  std_logic_vector (2 downto 0);
        PORT_A:         out std_logic_vector (31 downto 0);
        PORT_B:         out std_logic_vector (31 downto 0)
        ); 
    end component; 

signal REG_WRT:         std_logic := '1';
signal WRT_REG_NUM:     std_logic_vector (2 downto 0) := "000";
signal WRT_DATA:        std_logic_vector (31 downto 0) := (others => '0');
signal READ_REG_A:      std_logic_vector (2 downto 0) := "000";
signal READ_REG_B:      std_logic_vector (2 downto 0) := "000";
signal PORT_A:          std_logic_vector (31 downto 0);
signal PORT_B:          std_logic_vector (31 downto 0);

begin 

DUT: 
        REG
        port map (
            REG_WRT => REG_WRT,
            WRT_REG_NUM => WRT_REG_NUM,
            WRT_DATA  => WRT_DATA,
            READ_REG_A => READ_REG_A, 
            READ_REG_B => READ_REG_B, 
            PORT_A => PORT_A, 
            PORT_B => PORT_B
        ); 


STIMULUS:
    process 
    begin 
    wait for 20 ns;
    REG_WRT <= '0';
    wait for 20 ns;
    REG_WRT <= '1';
    wait for 20 ns;
    WRT_DATA <= x"feedface";
    WRT_REG_NUM <= "001";
    REG_WRT <= '0';
    wait for 20 ns;
    REG_WRT <= '1';
    READ_REG_A <= "001";
    wait for 20 ns;
    WRT_DATA <= x"deadbeef";
    WRT_REG_NUM <= "010";
    READ_REG_B <= "010";
    REG_WRT <= '0';
    wait for 20 ns;
    REG_WRT <= '1';
    wait for 20 ns;
    wait for 20 ns;
    wait;
 end process; 
end architecture; 

但它运行并产生上面显示的波形。这是使用Tony Bybell的gtkwave在Mac(OS X 10.9.2)上使用Tristan Gingold的ghdl(ghdl-0.31)完成的。请参阅ghdl-updatesgtkwave的Sourceforge页面。