使用BRAM进行位宽转换

文章目录

  • 手册中的相关内容
  • 仿真测试

在数据吞吐率不变的情况下,偶尔需要进行位宽转换,此时可以考虑使用BRAM实现,

手册中的相关内容

参见pg058章节《Data Width Aspect Ratios》

  • BRAM允许端口A的数据宽度不同于端口B的数据宽度(支持的位宽比为1:32, 1:16, 1:8, 1:4, 1:2, 1:1,
    2:1, 4:1, 8:1, 16:1, and 32:1)
  • 对于TDP,四个数据端口(dina、douta、dinb、doutb)可以具有不同的宽度
  • 对于SDP,两个数据端口(dina、douta)可以具有不同的宽度

手册中举了两个例子,一个例子是A端口的位宽比B端口的位宽大,一个例子是四个端口的位宽都不相同,核心思想是 数据在RAM中是采用小端模式存储的
使用BRAM进行位宽转换_第1张图片
使用BRAM进行位宽转换_第2张图片

仿真测试

测试代码如下,

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

entity data_width_convert is
    port ( 
        clk_A       : in  std_logic;
        din_00      : in  std_logic_vector(7 downto 0); 
        din_01      : in  std_logic_vector(7 downto 0); 
        din_02      : in  std_logic_vector(7 downto 0); 
        din_03      : in  std_logic_vector(7 downto 0); 
        din_04      : in  std_logic_vector(7 downto 0); 
        din_05      : in  std_logic_vector(7 downto 0); 
        din_06      : in  std_logic_vector(7 downto 0); 
        din_07      : in  std_logic_vector(7 downto 0); 
        clk_B       : in  std_logic;  
        dout_00     : out std_logic_vector(7 downto 0); 
        dout_01     : out std_logic_vector(7 downto 0); 
        dout_02     : out std_logic_vector(7 downto 0); 
        dout_03     : out std_logic_vector(7 downto 0); 
        dout_04     : out std_logic_vector(7 downto 0); 
        dout_05     : out std_logic_vector(7 downto 0); 
        dout_06     : out std_logic_vector(7 downto 0); 
        dout_07     : out std_logic_vector(7 downto 0);
        dout_08     : out std_logic_vector(7 downto 0); 
        dout_09     : out std_logic_vector(7 downto 0); 
        dout_10     : out std_logic_vector(7 downto 0); 
        dout_11     : out std_logic_vector(7 downto 0); 
        dout_12     : out std_logic_vector(7 downto 0); 
        dout_13     : out std_logic_vector(7 downto 0); 
        dout_14     : out std_logic_vector(7 downto 0); 
        dout_15     : out std_logic_vector(7 downto 0)
    );
end data_width_convert;

architecture Behavioral of data_width_convert is
    
    component bram_w64_r128
        port (
            clka    : in std_logic;
            wea     : in std_logic_vector(0 downto 0);
            addra   : in std_logic_vector(3 downto 0);
            dina    : in std_logic_vector(63 downto 0);
            clkb    : in std_logic;
            addrb   : in std_logic_vector(2 downto 0);
            doutb   : out std_logic_vector(127 downto 0)
        );
    end component;
    
    signal addra : unsigned(3 downto 0) := "0000";
    signal addrb : unsigned(2 downto 0) := "111";
    signal dina  : std_logic_vector(63 downto 0);
    signal doutb : std_logic_vector(127 downto 0);
    
begin
    
    process(clk_A)
    begin
        if rising_edge(clk_A) then
            addra <= addra + 1;
        end if;
    end process;
    
    process(clk_B)
    begin
        if rising_edge(clk_B) then
            addrb <= addrb + 1;
        end if;
    end process;
    
    dina(07 downto 00) <= din_00;     
    dina(15 downto 08) <= din_01;     
    dina(23 downto 16) <= din_02;     
    dina(31 downto 24) <= din_03;     
    dina(39 downto 32) <= din_04;     
    dina(47 downto 40) <= din_05;     
    dina(55 downto 48) <= din_06;     
    dina(63 downto 56) <= din_07;     
        
    dout_00 <= doutb(007 downto 000);
    dout_01 <= doutb(015 downto 008);
    dout_02 <= doutb(023 downto 016);
    dout_03 <= doutb(031 downto 024);
    dout_04 <= doutb(039 downto 032);
    dout_05 <= doutb(047 downto 040);
    dout_06 <= doutb(055 downto 048);
    dout_07 <= doutb(063 downto 056);
    dout_08 <= doutb(071 downto 064);
    dout_09 <= doutb(079 downto 072);
    dout_10 <= doutb(087 downto 080);
    dout_11 <= doutb(095 downto 088);
    dout_12 <= doutb(103 downto 096);
    dout_13 <= doutb(111 downto 104);
    dout_14 <= doutb(119 downto 112);
    dout_15 <= doutb(127 downto 120);

    Inst_bram_w64_r128 : bram_w64_r128
    port map(
        clka    => clk_A,
        wea     => "1",
        addra   => std_logic_vector(addra),
        dina    => dina,
        clkb    => clk_B,
        addrb   => std_logic_vector(addrb),
        doutb   => doutb
    );

end Behavioral;

tb采用一组递增数进行测试,读写时钟的初始相位不同,仿真结果见下图,
使用BRAM进行位宽转换_第3张图片

你可能感兴趣的:(FPGA)