当两个地址具有相同的值时,我如何读取此ram并返回q = 1

时间:2017-07-24 10:06:32

标签: vhdl ram

我创建了这个ram:

    library ieee;
        use ieee.std_logic_1164.all;
        USE IEEE.STD_LOGIC_UNSIGNED.ALL;
        entity true_dpram_sclk is
        port 
        (   
        data_a  : in std_logic_vector(7 downto 0);
        data_b  : in std_logic_vector(7 downto 0);
        address_a   : in std_logic_vector(7 downto 0);
        address_b   : in std_logic_vector(7 downto 0);
        we_a    : in std_logic := '1';
        --  we_b    : in std_logic := '1';
        clk     : in std_logic;
        q_a     : out std_logic_vector(7 downto 0);
        q_b     : out std_logic_vector(7 downto 0);
        q           : out std_logic
        );

        end true_dpram_sclk;

        architecture rtl of true_dpram_sclk is

        -- Build a 2-D array type for the RAM
        subtype word_t is std_logic_vector(7 downto 0);
        type memory_t is array(17 downto 0) of word_t;

        -- Declare the RAM
        shared variable ram : memory_t;
        SIGNAL ADDR_A : INTEGER RANGE 0 TO 17;
        SIGNAL ADDR_B : INTEGER RANGE 0 TO 17;

        begin

        -- Port A
        process(clk)
        begin
        ADDR_A<=CONV_INTEGER(ADDRESS_A);
        if(rising_edge(clk)) then 
            if(we_a = '1') then
                ram(addr_a) := data_a;
            elsif (we_a = '0') then
                q_a <= ram(addr_a);
            else
                q_a <= "ZZZZZZZZ";
            end if;
        end if; 
        end process;

        -- Port B
        process(clk)
        begin
        ADDR_B<=CONV_INTEGER(ADDRESS_B);
        if(rising_edge(clk)) then
            if(we_a = '1') then
                ram(addr_b) := data_b;
            elsif (we_a = '0') then
                q_b <= ram(addr_b);
            else
                q_b <= "ZZZZZZZZ";
            end if;
        end if; 
        end process;

        --   --MATCHER
        --  process (clk)
        --  begin
        --       if ((we_a = '0') and (we_b = '0') and ram(addr_a) = 
        --ram(addr_b)) then
        --                  q <= '1';
        --          else
        --                  q <= '0';
--   end if;        
--  end process;
--
end rtl;    

以及上述测试基准:

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;

ENTITY tb2 IS
END tb2;

ARCHITECTURE behavior OF tb2 IS 

    -- Component Declaration for the Unit Under Test (UUT)

    COMPONENT true_dpram_sclk
    PORT(
         data_a : IN  std_logic_vector(7 downto 0);
         data_b : IN  std_logic_vector(7 downto 0);
         address_a : IN  std_logic_vector(7 downto 0);
         address_b : IN  std_logic_vector(7 downto 0);
         we_a : IN  std_logic;
    --     we_b : IN  std_logic;
         clk : IN  std_logic;
         q_a : OUT  std_logic_vector(7 downto 0);
         q_b : OUT  std_logic_vector(7 downto 0);
            q : OUT std_logic
        );
    END COMPONENT;

--   COMPONENT matcher
--   PORT(
--          A : IN std_logic_vector(15 downto 0);
--          B : IN std_logic_vector(15 downto 0);
--          clk: IN std_logic;
--          Q : OUT std_logic
--          );
--   END COMPONENT;     

   --Inputs
   signal data_a : std_logic_vector(7 downto 0) := (others => '0');
   signal data_b : std_logic_vector(7 downto 0) := (others => '0');
   signal address_a : std_logic_vector(7 downto 0) := (others => '0');
   signal address_b : std_logic_vector(7 downto 0) := (others => '0');
   signal we_a : std_logic := '1';
 --  signal we_b : std_logic := '1';
   signal clk : std_logic := '0';
    SIGNAL ADDR_A : INTEGER RANGE 0 TO 17;
    SIGNAL ADDR_B : INTEGER RANGE 0 TO 17;

    --Outputs
   signal q_a : std_logic_vector(7 downto 0);
   signal q_b : std_logic_vector(7 downto 0);
    signal q : std_logic := '0';

   -- Clock period definitions
   constant clk_period : time := 10 ns;

BEGIN

    -- Instantiate the Unit Under Test (UUT)
   uut: true_dpram_sclk PORT MAP (
          data_a => data_a,
          data_b => data_b,
          address_a => address_a,
          address_b => address_b,
          we_a => we_a,
   --       we_b => we_b,
          clk => clk,
          q_a => q_a,
          q_b => q_b,
             q => q
        );

--  uut: matcher PORT MAP (
--          A => q_a,
--           B => q_b,
--           clk => clk,
--           Q => Q
--        );      

   -- Clock process definitions
   clk_process :process
   begin
        clk <= '0';
        wait for clk_period;
        clk <= '1';
        wait for clk_period;
    end process;

process
begin
    --Write data into RAM
        wait for clk_period*1;
        --1
        address_a <= "00000000";
        address_b <= "00000000";
        data_a <= "10111001";
        data_b <= "10111001";
        wait for clk_period*1;
        --2
        address_a <= "00000001";
        address_b <= "00000001";
        data_a <= "01101100";
        data_b <= "01101100";
        wait for clk_period*1;
        --3
        address_a <= "00000010";
        address_b <= "00000010";
        data_a <= "00110011";
        data_b <= "00110011";
        wait for clk_period*1;
        --4
        address_a <= "00000011";
        address_b <= "00000011";
        data_a <= "00001101";
        data_b <= "00001101";
        wait for clk_period*1;
        --5
        address_a <= "00000100";
        address_b <= "00000100";
        data_a <= "00001010";
        data_b <= "00001010";
        wait for clk_period*1;
        --6
        address_a <= "00000101";
        address_b <= "00000101";
        data_a <= "00110111";
        data_b <= "00110111";
        wait for clk_period*1;
       --7
        address_a <= "00000110";
        address_b <= "00000110";
        data_a <= "11110010";
        data_b <= "10111001";
        wait for clk_period*1;
        --8
        address_a <= "00000111";
        address_b <= "00000111";
        data_a <= "10101011";
        data_b <= "01101100";
        wait for clk_period*1;
        --9
        address_a <= "00001000";
        address_b <= "00001000";
        data_a <= "01111000";
        data_b <= "00110011";
        wait for clk_period*1;
        --10
        address_a <= "00001001";
        address_b <= "00001001";
        data_a <= "01011000";
        data_b <= "00001101";
        wait for clk_period*1;
        --11
        address_a <= "00001010";
        address_b <= "00001010";
        data_a <= "00001010";
        data_b <= "00001010";
        wait for clk_period*1;
        --12
        address_a <= "00001011";
        address_b <= "00001011";
        data_a <= "00111000";
        data_b <= "00110111";
    wait for clk_period*1;

   --Read data from RAM
    we_a <= '0';
--  we_b <= '0';

        --1
        address_a <= "00000000";
        address_b <= "00000000";
        wait for clk_period*1;
        --2
        address_a <= "00000001";
        address_b <= "00000001";
        wait for clk_period*1;
       --3
        address_a <= "00000010";
        address_b <= "00000010";
        wait for clk_period*1;
        --4
        address_a <= "00000011";
        address_b <= "00000011";
        wait for clk_period*1;
        --5
        address_a <= "00000100";
        address_b <= "00000100";
        wait for clk_period*1;
        --6
        address_a <= "00000101";
        address_b <= "00000101";
        wait for clk_period*1;
        --7
        address_a <= "00000110";
        address_b <= "00000110";
        wait for clk_period*1;
        --8
        address_a <= "00000111";
        address_b <= "00000111";
        wait for clk_period*1;
        --9
        address_a <= "00001000";
        address_b <= "00001000";
        wait for clk_period*1;
        --10
        address_a <= "00001001";
        address_b <= "00001001";
        wait for clk_period*1;
        --11
        address_a <= "00001010";
        address_b <= "00001010";
        wait for clk_period*1;
        --12
        address_a <= "00001100";
        address_b <= "00001100";
        wait for clk_period*1;

wait;
end process;

END behavior;

我想阅读address_a和address_b并逐一比较它们并返回q&lt; =&#39; 1&#39;当address_a = adress_b且q&lt; =&#39; 0&#39;什么时候不平等。我想要这样的事情:

--Read data from RAM
    we_a <= '0';
--  we_b <= '0';

        --1
        address_a <= "00000000";
        address_b <= "00000000";
        if ( q_a = q_b ) then 
        q <= '1'; else
        q <= '0';
        end if;
        wait for clk_period*1;

任何帮助都会很棒。谢谢!!

1 个答案:

答案 0 :(得分:4)

图书馆的选择

USE IEEE.STD_LOGIC_UNSIGNED.ALL;

失礼。那是一个非标准化的图书馆。不要使用它。替换为

USE IEEE.NUMERIC_STD.ALL;

并使用UNSIGNEDSIGNED数据类型进行算术运算。

特别是不要同时使用这两个库,就像你在测试台上那样......

尺寸不匹配

address_a   : in std_logic_vector(7 downto 0);
[...]
SIGNAL ADDR_A : INTEGER RANGE 0 TO 17;
[...]
ADDR_A<=CONV_INTEGER(ADDRESS_A);

address_a为8位,因此范围为0到255(如果已签名则为-128到127)。你不能简单地把它放在0到17的范围内。这可能会导致错误。

顺序与组合

-- Port A
process(clk)
begin
    ADDR_A<=CONV_INTEGER(ADDRESS_A);
    if (rising_edge(clk)) then 

作业ADDR_A<=CONV_INTEGER(ADDRESS_A);是一个组合声明。然而你把它放在计时过程中(但不是在时钟if语句中)。这有各种奇怪的效果,特别是当你合成时:它甚至可能产生一个锁存器。

ADDR_A<=CONV_INTEGER(ADDRESS_A);需要在流程之外。如果您使用库numeric_stdADDR_A <= to_integer(unsigned((ADDRESS_A));

,情况会更好

实现中无法访问的代码和错误的RAM实例化。

在实现中,逻辑值只能是'0'和'1'。

if(we_a = '1') then
    [...]
elsif (we_a = '0') then
    [... we_a = '0' is redundant here ...]
else
    [... unreachable, as '1' and '0' are already covered ...]
end if;

足够的是:

if(we_a = '1') then
    ram(addr_b) := data_b;
else
    q_b <= ram(addr_b);
end if;

然而,这不是正确支持的RAM编码,因为您键入的内容是为了阻止q_bwe_a = '1'时更改。正确的是:

q_b <= ram(addr_b);
if(we_a = '1') then
    ram(addr_b) := data_b;
end if;

即。写作时q_b也会发生变化。 例如,请参阅Xilinx synthesis user guide

访问RAM数据

Block RAM(就像你打算使用的那样)是一个封闭的组件。它最多只有两个访问端口,您使用它们:端口A和端口B.但是,在第三个进程中,您尝试通过第三个端口访问RAM!

if [...] ram(addr_a) = ram(addr_b) [...] then

这是不可能的。

如果你想比较地址的值,你必须先从RAM中取出它们......这实际上已经在端口A和端口B进程中发生了(如果你正确地改变这些就像我之前建议的那样) )。然后,您可以使用以下方法简单地比较内容:

process (clk)
begin
    if rising_edge(clk) then
        if q_a = q_b then
            q <= '1';
        else
            q <= '0';
        end if;        
    end if;
end process;

问题与代码??

在您的代码中,您正在比较RAM 内容

ram(addr_a) = ram(addr_b)

但是,如果我读了你的问题,你想要比较地址

addr_a = addr_b

这是什么?如果是后者,则无需做复杂的事情。只是做:

process (clk)
begin
    if rising_edge(clk) then
        if addr_a = addr_b then
            q <= '1';
        else
            q <= '0';
        end if;
    end if;
end process;