繁体   English   中英

用VHDL编写寄存器文件

[英]Writing a Register File in VHDL

我正在尝试用VHDL编写寄存器文件。 该文件包含16个64位寄存器。 每个周期读取两个寄存器并写入一个寄存器(假设写入已启用)。 应该有一个数据旁路(转发),这样如果我们在一个周期内读取和写入同一个寄存器,那么刚写入的值就会直接转发到输出。

我的想法是在上升沿写入并在时钟的下降沿读取,以便在一个周期内完成此操作。 但是,我的设计不起作用(不是我预期的,因为我不相信在检查上升沿的if块中检查下降沿将按预期工作)。

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity register_file is   
    port
    (
    outA          : out std_logic_vector(63 downto 0);
    outB          : out std_logic_vector(63 downto 0);
    input         : in  std_logic_vector(63 downto 0);
    writeEnable   : in std_logic;
    regASel       : in std_logic_vector(5 downto 0);
    regBSel       : in std_logic_vector(5 downto 0);
    writeRegSel   : in std_logic_vector(5 downto 0);
    clk           : in std_logic
    );
end register_file;

architecture behavioral of register_file is
type registerFile is array(0 to 15) of std_logic_vector(63 downto 0);
signal registers : registerFile;
begin

    regFile: process(clk)
    begin
        if rising_edge(clk) then 
            if(writeEnable = '1') then
                registers(to_integer(unsigned(writeRegSel))) <= input;
            end if;
            if falling_edge(clk) then
                outA <= registers(to_integer(unsigned(regASel)));
                outB <= registers(to_integer(unsigned(regBSel)));
            end if;
        end if;
        if falling_edge(clk) then
                outA <= registers(to_integer(unsigned(regASel)));
                outB <= registers(to_integer(unsigned(regBSel)));
        end if;
    end process;
end behavioral;

任何帮助,将不胜感激。

提交的VHDL代码具有以下构造:

...
if rising_edge(clk) then
  ...
  if falling_edge(clk) then
  ...

这将留下死代码,因为rising_edgefalling_edge不能同时为真。 此外,使用上升沿和下降沿的想法通常会导致设计和综合问题。

为了获得最佳时序,易于设计和合成约束,我建议仅使用上升沿,除非必须同时使用上升沿和下降沿。

通过在同一周期中绕过读取A和B的写入数据,寄存器文件可能如下所示:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity register_file is
  port(
    outA        : out std_logic_vector(63 downto 0);
    outB        : out std_logic_vector(63 downto 0);
    input       : in  std_logic_vector(63 downto 0);
    writeEnable : in  std_logic;
    regASel     : in  std_logic_vector(3 downto 0);
    regBSel     : in  std_logic_vector(3 downto 0);
    writeRegSel : in  std_logic_vector(3 downto 0);
    clk         : in  std_logic
    );
end register_file;


architecture behavioral of register_file is
  type registerFile is array(0 to 15) of std_logic_vector(63 downto 0);
  signal registers : registerFile;
begin
  regFile : process (clk) is
  begin
    if rising_edge(clk) then
      -- Read A and B before bypass
      outA <= registers(to_integer(unsigned(regASel)));
      outB <= registers(to_integer(unsigned(regBSel)));
      -- Write and bypass
      if writeEnable = '1' then
        registers(to_integer(unsigned(writeRegSel))) <= input;  -- Write
        if regASel = writeRegSel then  -- Bypass for read A
          outA <= input;
        end if;
        if regBSel = writeRegSel then  -- Bypass for read B
          outB <= input;
        end if;
      end if;
    end if;
  end process;
end behavioral;

请注意,* Sel中的“地址”仅减少到4位,以匹配寄存器文件中的16个必需条目,正如Daniel Kamil Kozar所指出的那样。

模拟中没有检查X值,但如果需要,可以使用Is_X函数添加。

在绝大多数情况下,您不能在进程中具有上升沿和下降沿,因为您将定位的(大多数)设备中没有可以在两个边缘上响应的项目​​。 (一个例外是支持双倍数据速率IO的设备中的IO触发器)。

如果您想要旁路,请在正常的上升沿过程中明确编码:

outa <= registers(to_integer(...etc));
if write_enable = '1' and regAsel = writeregsel then 
   outa <= input;
end if;
-- similar for regb  

另外,为什么不使你的regsel输入integer类型,或者至少是unsigned - 假设它们肯定代表一个数字(不只是一个任意的位数,这是你的数据IO向量的情况)?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM