我的电路有一个32 x 8 D触发网格。每行应产生一个32位向量,其中包含来自D-ff的Q值 - 然后将其发送到8x1 MUX。以下代码是我试图正确生成32 x 8 D触发器并测试我是否可以从中获取一个向量(32位I0向量)。
我试图编写实现的电路可以在这个问题的贴图中看到: test bench of a 32x8 register file VHDLlibrary 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?
我感谢我收到的任何建议!
编辑:我已更新代码以反映答案中给出的建议
答案 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;
这些会取代I0
和Q_out
。
从引用的答案(您显然只是标记为有用 - 谢谢),您可以使用I0(COL)
替换内部生成语句中的QN_out(COL)
实例中的D_FF
和Q(ROW)(COL)
和QN(ROW)(COL)
。
注意如果您未使用D_FF
的Q NOT输出,则不能将它们作为端口提供或不连接它们(open
)。您还可以将Q
输出用于其他读取MUX
的一个读取QN
和MUX
输出,从而反转该MUX
的输出。只有两个端口,您不会显着减少负载,您可以使用Q
。
对于MUX
使用信号Q
定义为上面的reg_array,MUX输入将是Q(0)
到Q(7)
,输出可以是PORT_A
或PORT_B
。 S_in
将分别与READ_REG_A
或READ_REG_B
相关联。
在阅读您的VHDL设计说明时,有一点不明显的原因是您的流程wait for 10 ns
中存在DCDR_AND
的原因?它将写入延迟超过CLK的低波特率(时钟的低部分)。在零时间模型中,您只需使用not CLK
代替CLK
(CLK_vals(I) <= O_out(I) and not CLK
,删除wait for 10 ns;
行。对于合成产生的定时模型,wait
无法合成。如果您打算进行综合,如果CLK
是时钟同步的话,可以依靠输入保持,可以使用WR_DATA
。
然后您的模型已经离散地实例化了D_FF
并使用MUX
es作为读取端口。
我拒绝修改你的代码的冲动,并且在你进行同一课堂练习的情况下显示它。如果其中任何一个不清楚,请在对此答案的评论中提出,并且我将添加到答案中,明确标记对其的任何更正或在必要时演示代码。
请注意,REG_WRT已经显示为来自之前工作的测试平台的反转时钟,因此我删除了前一个not
进程DCDR_AND
,否则使用之前的努力测试平台除了匹配您的端口名称之外没有变化。
另请注意,PORT_A
和PORT_B
输出在写入地址(READ_REG_A
或READ_REG_B
)之前保持未初始化状态,这是特定测试平台的重点
在时钟单元(REG_WRT
)中间写入触发器(统称为8个32位寄存器)的想法是避免时钟偏移问题,在写入输入引起的测试平台的情况下基于延迟值而不是时钟边缘。
您可以在时钟进程中同样拥有激励,这可能需要平衡时钟延迟以确保WRT_DATA
和WRT_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-updates和gtkwave的Sourceforge页面。