用VHDL编写寄存器文件 [英] Writing a Register File in VHDL

查看:302
本文介绍了用VHDL编写寄存器文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在VHDL中写入寄存器文件。该文件包含16个64位寄存器。每个周期读取两个寄存器并写入一个寄存器(假定已启用写入)。应该有一个数据旁路(转发),这样,如果我们在一个周期内对同一寄存器进行读写操作,则刚写入的值将直接转发到输出。

I am trying to write a register file in VHDL. The file contains 16 64-bit registers. Each cycle, two registers are read and one register is written (given that writing is enabled). There should be a data bypass (forwarding) so that the value just written is forwarded directly to the output if we are reading and writing to/from the same register in a single cycle.

我的想法是在时钟的上升沿写入并在时钟的下降沿读取,以便在一个周期内完成此操作。但是,我的设计没有用(不是我期望的那样,因为我不认为在 if 块中检查上升沿是否可以按预期进行)。

My idea was to write on the rising edge and read on the falling edge of the clock in order to complete this in one cycle. However, my design isn't working (not that I expected it to since I don't believe that checking for a falling edge within an if block which checks for a rising edge would work as expected).

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代码具有以下构造:

The submitted VHDL code has construction with:

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

这将留下无效代码,因为 rising_edge falling_edge 都不能是
同时为true。同样,同时使用上升和下降沿
的想法通常会引起设计和综合问题。

This will leave dead code, since both rising_edge and falling_edge can't be true at the same time. Also, the idea of using both rising and falling edge will often cause design and synthesis problems.

为了获得最佳时序,并简化设计和综合约束,我将建议仅
使用上升沿,除非必须同时使用上升和下降
边缘。

For best timing, and ease of design and synthesis constraining, I will suggest use of rising edge only, unless it is mandatory to use both rising and falling edge.

对于在同一周期中读取A和B,寄存器
文件可能看起来像:

With bypass of write data for read A and B in the same cycle, the register file may look like:

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指出的那样。

Note that the "address" in *Sel are reduced to 4 bit only, to match the 16 required entries in the register file, as Daniel Kamil Kozar also points out.

在模拟中不检查X值,但是可以在$中添加b $ b Is_X 函数(如果需要)。

There is no checking for X values in simulation, but this can be added with Is_X function, if required.

这篇关于用VHDL编写寄存器文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆