如何在VHDL中声明共享std_logic_vector?

时间:2015-01-29 00:35:52

标签: vhdl

我目前正在尝试在我的架构中创建一个共享数组声明,但它不起作用并且它一直给我一个语法错误,有人可以向我解释为什么会这样吗?

architecture behav of mpy8 is
shared variable P : std_logic_vector (17 downto 0); // doesn't work

我想在转换过程中使用变量P并断言输出过程。

2 个答案:

答案 0 :(得分:0)

变量仅可在vhdl中的一个进程中使用。您不允许在体系结构块外部进程中使用变量。为了在不同的过程或实体之间共享值,您需要多个信号。所有过程都可以读取一个信号。但是只允许一个进程写入相同的信号。

也许以下示例可以帮助您。它是我上个学期写的处理器的数据存储器:

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


    entity DataMemory is

        generic(
            size : natural := 8 --number of instructions
        );  
        port(
            clk_i           : in  std_logic;
            rst_i           : in  std_logic;
            alu_result_i    : in  std_logic_vector(31 DOWNTO 0);
            writeData_i     : in  std_logic_vector(31 DOWNTO 0);
            memWrite_i      : in  std_logic;   
            memRead_i       : in  std_logic;
            loadMode_i  : in  load_mode;
            storeMode_i : in store_mode;

            readData_o   : out std_logic_vector(31 DOWNTO 0)
        );
    end entity DataMemory;

    architecture behaviour of DataMemory is
        constant size2 : integer := size * 4;
        type dataMemType is array (0 to size2 - 1) of std_logic_vector(7 downto 0);
        signal dataMem : dataMemType := (
                "11111011","00000000","00000000","00000000",
                "11101111","01000010","00000000","00000000",
                "00000000","00000000","00000000","00000000",
                "00000000","00000000","00000000","00000000",
                "00000000","00000000","00000000","00000000",
                "00000000","00000000","00000000","00000000",
                "00000000","00000000","00000000","00000000",
                "00000000","00000000","00000000","00000000"
        );
        signal readout : std_logic_vector(31 downto 0);
        signal loadWordRaw : std_logic_vector(31 downto 0);
        signal loadHalfRaw : std_logic_vector(31 downto 0);
        signal loadByteRaw : std_logic_vector(31 downto 0);
        signal loadHalfSigned : std_logic_vector(31 downto 0);
        signal loadByteSigned : std_logic_vector(31 downto 0);

        begin

        --determines how much bytes are loaded
        loadWordRaw <= dataMem(TO_INTEGER(UNSIGNED(alu_result_i))) &
                    dataMem(TO_INTEGER(UNSIGNED(alu_result_i)) + 1) &
                    dataMem(TO_INTEGER(UNSIGNED(alu_result_i)) + 2) &
                    dataMem(TO_INTEGER(UNSIGNED(alu_result_i)) + 3)     when memRead_i = '1' and loadMode_i = ld_lw ELSE
                    (others => '-');
        loadHalfRaw <= ("00000000" & "00000000" & 
                    dataMem(TO_INTEGER(UNSIGNED(alu_result_i))) &
                    dataMem(TO_INTEGER(UNSIGNED(alu_result_i)) + 1))    when (memRead_i = '1') and ((loadMode_i = ld_lh) or (loadMode_i = ld_lhu)) ELSE
                    (others => '-');
        loadByteRaw <= "00000000" & "00000000" & "00000000" & 
                    dataMem(TO_INTEGER(UNSIGNED(alu_result_i)))         when memRead_i = '1' and ((loadMode_i = ld_lb) or (loadMode_i = ld_lbu)) ELSE
                    (others => '-');

        --signed: resize to 32 bit
        loadHalfSigned <= std_logic_vector(resize(signed(loadHalfRaw(15 downto 0)), 32)) when loadMode_i = ld_lh ELSE
                    (others => '-');
        loadByteSigned <= std_logic_vector(resize(signed(loadByteRaw(7 downto 0)), 32))  when loadMode_i = ld_lb ELSE
                    (others => '-');

        --which mode is chosen
        readout <=  loadWordRaw         when loadMode_i = ld_lw ELSE
                    loadHalfRaw         when loadMode_i = ld_lhu ELSE
                    loadHalfSigned  when loadMode_i = ld_lh ELSE
                    loadByteRaw         when loadMode_i = ld_lbu ELSE
                    loadByteSigned; 

        dataMem_process : process(clk_i, rst_i) is
        begin
            if rst_i = '1' then
                readData_o <= (others => '0');
            elsif rising_edge(clk_i) then
                readData_o <= readout;
                if memWrite_i = '1' then
                    if storeMode_i = st_sw then --store normal
                        dataMem(TO_INTEGER(UNSIGNED(alu_result_i))) <= writeData_i(31 DOWNTO 24);
                        dataMem(TO_INTEGER(UNSIGNED(alu_result_i)) + 1) <= writeData_i(23 DOWNTO 16);
                        dataMem(TO_INTEGER(UNSIGNED(alu_result_i)) + 2) <= writeData_i(15 DOWNTO 8);
                        dataMem(TO_INTEGER(UNSIGNED(alu_result_i)) + 3) <= writeData_i(7 DOWNTO 0);
                    elsif storeMode_i = st_sh then      --store half
                        dataMem(TO_INTEGER(UNSIGNED(alu_result_i))) <= writeData_i(15 DOWNTO 8);
                        dataMem(TO_INTEGER(UNSIGNED(alu_result_i)) + 1) <= writeData_i(7 DOWNTO 0);
                    else    --store byte
                        dataMem(TO_INTEGER(UNSIGNED(alu_result_i))) <= writeData_i(7 DOWNTO 0);
                        end if;
                end if;
            end if;
        end process dataMem_process;                

    end architecture;

包“instructions_pack”:

    library ieee;
    use ieee.std_logic_1164.all;

    package Instructions_pack is
        constant c_op_bits      : integer                      := 6;
        constant c_instr_bits   : integer                      := 5;
        constant c_immed_bits   : integer                      := 16;
        constant c_address_bits : integer                      := 26;
        ----------------------------------------------------
        --- MIPS registers ---------------------------------
        ----------------------------------------------------
        constant R0             : std_logic_vector(4 downto 0) := (others => '0');
        constant Rat            : std_logic_vector(4 downto 0) := '0' & x"1";
        constant Rv0            : std_logic_vector(4 downto 0) := '0' & x"2";
        constant Rv1            : std_logic_vector(4 downto 0) := '0' & x"3";
        constant Ra0            : std_logic_vector(4 downto 0) := '0' & x"4";
        constant Ra1            : std_logic_vector(4 downto 0) := '0' & x"5";
        constant Ra2            : std_logic_vector(4 downto 0) := '0' & x"6";
        constant Ra3            : std_logic_vector(4 downto 0) := '0' & x"7";
        constant Rt0            : std_logic_vector(4 downto 0) := '0' & x"8";
        constant Rt1            : std_logic_vector(4 downto 0) := '0' & x"9";
        constant Rt2            : std_logic_vector(4 downto 0) := '0' & x"A";
        constant Rt3            : std_logic_vector(4 downto 0) := '0' & x"B";
        constant Rt4            : std_logic_vector(4 downto 0) := '0' & x"C";
        constant Rt5            : std_logic_vector(4 downto 0) := '0' & x"D";
        constant Rt6            : std_logic_vector(4 downto 0) := '0' & x"E";
        constant Rt7            : std_logic_vector(4 downto 0) := '0' & x"F"; --15
        constant Rt8            : std_logic_vector(4 downto 0) := '1' & x"8"; --24
        constant Rt9            : std_logic_vector(4 downto 0) := '1' & x"9"; --25
        constant Rs0            : std_logic_vector(4 downto 0) := '1' & x"0"; --16
        constant Rs1            : std_logic_vector(4 downto 0) := '1' & x"1"; --17
        constant Rs2            : std_logic_vector(4 downto 0) := '1' & x"2"; --18
        constant Rs3            : std_logic_vector(4 downto 0) := '1' & x"3"; --19
        constant Rs4            : std_logic_vector(4 downto 0) := '1' & x"4"; --20
        constant Rs5            : std_logic_vector(4 downto 0) := '1' & x"5"; --21
        constant Rs6            : std_logic_vector(4 downto 0) := '1' & x"6"; --22
        constant Rs7            : std_logic_vector(4 downto 0) := '1' & x"7"; --23
        constant Rk0            : std_logic_vector(4 downto 0) := '1' & x"A"; --26
        constant Rk1            : std_logic_vector(4 downto 0) := '1' & x"B"; --27
        constant Rgp            : std_logic_vector(4 downto 0) := '1' & x"C"; --28
        constant Rsp            : std_logic_vector(4 downto 0) := '1' & x"D"; --29
        constant Rfp            : std_logic_vector(4 downto 0) := '1' & x"E"; --30
        constant Rra            : std_logic_vector(4 downto 0) := '1' & x"F"; --31

        ----------------------------------------------------
        ------- r type constants ---------------------------
        ---------------------------------------------------- 
        type R_Type_Constant is record
            opcode : std_logic_vector(c_op_bits - 1 downto 0);
            funct  : std_logic_vector(c_op_bits - 1 downto 0);
        end record;
        --reg <= c_add.opcode & rs & rt & rd & shamt & c_add.funct;
        constant c_add : R_Type_Constant := (
            opcode => (others => '0'), funct => "10" & x"0"
        );
        constant c_addu : R_Type_Constant := (
            opcode => (others => '0'), funct => "10" & x"1"
        );
        constant c_and : R_Type_Constant := (
            opcode => "000000",
            funct  => "10" & x"4"
        );
        -- count leading ones
        constant c_clo : R_Type_Constant := (
            opcode => "01" & x"C",
            funct  => "10" & x"1"
        );
        -- count leading zeros
        constant c_clz : R_Type_Constant := (
            opcode => "01" & x"C",
            funct  => "10" & x"0"
        );
        constant c_div : R_Type_Constant := (
            opcode => (others => '0'), funct => "01" & x"A"
        );
        constant c_divu : R_Type_Constant := (
            opcode => (others => '0'), funct => "01" & x"B"
        );
        --multiply
        constant c_mult : R_Type_Constant := (
            opcode => (others => '0'), funct => "01" & x"8"
        );
        --unsigned multiply
        constant c_multu : R_Type_Constant := (
            opcode => (others => '0'), funct => "01" & x"9"
        );
        --multiply without overflow
        constant c_mul : R_Type_Constant := (
            opcode => "01" & x"C",
            funct  => "00" & x"2"
        );
        --multiply and add
        constant c_madd : R_Type_Constant := (
            opcode => "01" & x"C",
            funct  => (others => '0')
        );
        --unsigned multiply add
        constant c_maddu : R_Type_Constant := (
            opcode => "01" & x"C",
            funct  => "00" & x"1"
        );
        --multiply subtract
        constant c_msub : R_Type_Constant := (
            opcode => "01" & x"C",
            funct  => "00" & x"4"
        );
        --unsigned multiply subtract
        constant c_msubu : R_Type_Constant := (
            opcode => "01" & x"C",
            funct  => "00" & x"5"
        );

        constant c_nor : R_Type_Constant := (
            opcode => (others => '0'), funct => "10" & x"7"
        );

        constant c_or : R_Type_Constant := (
            opcode => (others => '0'), funct => "10" & x"5"
        );
        --logical shift left
        constant c_sll : R_Type_Constant := (
            opcode => (others => '0'), funct => (others => '0')
        );
        --shift left logical variable
        constant c_sllv : R_Type_Constant := (
            opcode => (others => '0'), funct => "00" & x"4"
        );
        --shift right arithmetic
        constant c_sra : R_Type_Constant := (
            opcode => (others => '0'), funct => "00" & x"3"
        );
        --shift right arithmetic variable
        constant c_srav : R_Type_Constant := (
            opcode => (others => '0'), funct => "00" & x"7"
        );
        --shift right logical
        constant c_srl : R_Type_Constant := (
            opcode => (others => '0'), funct => "00" & x"2"
        );
        --shift right logical variable
        constant c_srlv : R_Type_Constant := (
            opcode => (others => '0'), funct => "00" & x"6"
        );
        --subtract with overflow
        constant c_sub : R_Type_Constant := (
            opcode => (others => '0'), funct => "10" & x"2"
        );
        --subtract without overflow
        constant c_subu : R_Type_Constant := (
            opcode => (others => '0'), funct => "10" & x"3"
        );

        constant c_xor : R_Type_Constant := (
            opcode => (others => '0'), funct => "10" & x"6"
        );
        --comparison instructions
        --set less than
        constant c_slt : R_Type_Constant := (
            opcode => (others => '0'), funct => "10" & x"A"
        );
        --set less than unsigned
        constant c_sltu : R_Type_Constant := (
            opcode => (others => '0'), funct => "10" & x"B"
        );

        ------------------------------------------------------
        ----Branch constants
        ------------------------------------------------------
        type Branch_Type_Const is record
            opcode : std_logic_vector(c_op_bits - 1 downto 0);
            rt     : std_logic_vector(4 downto 0);
        end record;

        type Branch_Type_2regs_Const is record
            opcode : std_logic_vector(c_op_bits - 1 downto 0);
        end record;

        --branch on equal, use 2 registers
        constant c_beq : Branch_Type_2regs_Const := (opcode => "00" & x"4");

        --branch on not equal, use 2 registers
        constant c_bne : Branch_Type_2regs_Const := (opcode => "00" & x"5");

        -- branch on greater than equal zero
        constant c_bgez : Branch_Type_Const := (
            opcode => "00" & x"1",
            rt     => "0" & x"1"
        );

        --branch on greater than equal zero and link 
        --(save the address of next instruct. in reg. 31)
        constant c_bgezal : Branch_Type_Const := (
            opcode => "00" & x"1",
            rt     => "1" & x"1"
        );

        --branch on greater than zero
        constant c_bgtz : Branch_Type_Const := (
            opcode => "00" & x"7",
            rt     => (others => '0')
        );

        --branch on less than equal zero
        constant c_blez : Branch_Type_Const := (
            opcode => "00" & x"6",
            rt     => (others => '0')
        );

        --branch on less than zero and link
        --(save address in reg. 31)
        constant c_bltzal : Branch_Type_Const := (
            opcode => "00" & x"1",
            rt     => "1" & x"0"
        );

        --branch on less than zero
        constant c_bltz : Branch_Type_Const := (
            opcode => "00" & x"1",
            rt     => (others => '0')
        );

        ------------------------------------------------------
        -----i type instructions, load store
        ------------------------------------------------------
        subtype OP_Type_Const is std_logic_vector(c_op_bits - 1 downto 0);

        constant c_addi  : OP_Type_Const := "00" & x"8";
        constant c_addiu : OP_Type_Const := "00" & x"9";
        constant c_andi  : OP_Type_Const := "00" & x"C";
        constant c_ori   : OP_Type_Const := "00" & x"D"; --immediate or
        constant c_xori  : OP_Type_Const := "00" & x"E";
        --constant manipulation: load upper immediate
        constant c_lui   : OP_Type_Const := "00" & x"F";
        --set less than
        constant c_slti  : OP_Type_Const := "00" & x"A";
        constant c_sltiu : OP_Type_Const := "00" & x"B";
        --load instructions
        --load byte
        constant c_lb    : OP_Type_Const := "10" & x"0";
        --load unsigned byte
        constant c_lbu   : OP_Type_Const := "10" & x"4";
        --load halfword
        constant c_lh    : OP_Type_Const := "10" & x"1";
        --load halfword unsigned
        constant c_lhu   : OP_Type_Const := "10" & x"5";
        --load word
        constant c_lw    : OP_Type_Const := "10" & x"3";
        --lw left
        constant c_lwl   : OP_Type_Const := "10" & x"2";
        --lw right
        constant c_lwr   : OP_Type_Const := "10" & x"6";
        --load linked
        constant c_ll    : OP_Type_Const := "11" & x"0";
        --store word (sw)
        constant c_sw    : OP_Type_Const := "10" & x"B";
        --store byte
        constant c_sb    : OP_Type_Const := "10" & x"8";
        --store halfword
        constant c_sh    : OP_Type_Const := "10" & x"9";
        --store word left
        constant c_swl   : OP_Type_Const := "10" & x"A";
        --store word right
        constant c_swr   : OP_Type_Const := "10" & x"E";
        --store conditional: olways succeeds on SPIM (stores 1 to rt)
        constant c_sc    : OP_Type_Const := "11" & x"8";

        ------------------------------------------------------
        --Jump Instructions
        ------------------------------------------------------
        type J_Type_Const is record
            opcode : std_logic_vector(c_op_bits - 1 downto 0);
            rt     : std_logic_vector(c_instr_bits - 1 downto 0);
            funct  : std_logic_vector(c_op_bits - 1 downto 0);
        end record;

        --jump unconditionally to instruction at target
        -- PC(31 downto 28) & target(26 downto 0) & "00"
        constant c_j : OP_Type_Const := "00" & x"2";

        --Jump and link: unconditionally jump to instruction
        --at target address, save the address of next
        --instruction in register $ra (register 31)
        --PC(31 downto 28) & target(26 downto 0) & "00"
        constant c_jal : OP_Type_Const := "00" & x"3";

        --jump and link register:
        --unconditionally jump to instruction whose address
        --is in register rs. Save address of next instruct.
        --in register rd (default reg $ra)
        constant c_jalr : J_Type_Const := (
            opcode => "00" & x"0",
            rt     => "00000",
            funct  => "00" & x"9"
        );

        --jump register:
        --unconditionally jump to instruction whose address is in register rs
        constant c_jr : J_Type_Const := (
            opcode => "000000",
            rt     => "00000",
            funct  => "00" & x"8"
        );

        ------------------------------------------------------

        --type for r type instructions
        type R_Type is record
            opcode : std_logic_vector(c_op_bits - 1 downto 0);
            rs     : std_logic_vector(c_instr_bits - 1 downto 0);
            rt     : std_logic_vector(c_instr_bits - 1 downto 0);
            rd     : std_logic_vector(c_instr_bits - 1 downto 0);
            shamt  : std_logic_vector(c_instr_bits - 1 downto 0);
            funct  : std_logic_vector(c_op_bits - 1 downto 0);
        end record;

        -- i type instructions
        type I_Type is record
            opcode    : std_logic_vector(c_op_bits - 1 downto 0);
            rs        : std_logic_vector(c_instr_bits - 1 downto 0);
            rt        : std_logic_vector(c_instr_bits - 1 downto 0);
            immediate : std_logic_vector(c_immed_bits - 1 downto 0); --can used as offset value
        end record;

        --j type instructions
        type J_Type is record
            opcode  : std_logic_vector(c_op_bits - 1 downto 0);
            address : std_logic_vector(c_address_bits - 1 downto 0);
        end record;


        --alu code definition
        type alu_code is (  c_alu_add, c_alu_addu, c_alu_sub, c_alu_subu,
                            c_alu_and, c_alu_or, c_alu_nor, c_alu_xor,
                            c_alu_sllv, c_alu_srlv, c_alu_sll, c_alu_srl,
                            c_alu_sra, c_alu_srav, c_alu_zero,
                            c_alu_error --needed?
                            );
        --when to branch 
        type branch_condition is (bc_beq, bc_bgtz, bc_blez, bc_bne);

        --how much data to load
        type load_mode is (ld_lb, ld_lbu, ld_lh, ld_lhu, ld_lw);

        --how much data to store
        type store_mode is (st_sb, st_sh, st_sw);

    end package Instructions_pack;

    package body Instructions_pack is
    end package body Instructions_pack;

希望对你有所帮助

答案 1 :(得分:0)

我使用以下共享变量代码来模拟我的一个项目中的多端口内存。在这种情况下,模拟器的内存占用空间要小得多,仿真运行速度比使用简单信号要快。

据我所知,这不是可综合的,可能并非所有模拟器都支持。

architecture behavioral of testbench is
    type shared_ram is protected
        procedure write(addr: in integer; value: in std_logic_vector(63 downto 0));
        impure function read(addr: integer) return std_logic_vector;
    end protected shared_ram;

    type shared_ram is protected body
        -- bit_vector has a smaller simulation memory requirement than std_logic_vector
        type ram_t is array(0 to 2**25-1) of bit_vector(63 downto 0);
        variable ram: ram_t;

        procedure write(addr: in integer; value: in std_logic_vector(63 downto 0)) is
        begin
            ram(addr) := to_bitvector(value);
        end procedure write;

        impure function read(addr: integer) return std_logic_vector is
        begin
            return to_stdlogicvector(ram(addr));
        end function read;
    end protected body shared_ram;

    shared variable ram: shared_ram;
begin
    -- Processes can use ram.write(address, value) and ram.read(address)
end architecture behavioral;