Мы строим процессор для нашего финального проекта.Нам сказали построить регистровый файл с двумя выходами чтения и одним входом записи.Мы должны использовать мультиплексоры для выбора читаемых регистров и декодер для выбора записываемого регистра.
Мы используем Vivado 2015.4 и плату Nexys4.Я синтезировал файл регистров как часть всего процессора, но не сам по себе.Я запустил симуляцию тестового стенда только для регистров.
Верхний уровень файла регистрации:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
library work;
use work.RegPackage.all;
entity register_file1 is
Port ( clk : in STD_LOGIC;
reset : in STD_LOGIC;
w_en : in STD_LOGIC;
w_data : in STD_LOGIC_VECTOR (63 downto 0);
r_data1 : out STD_LOGIC_VECTOR (63 downto 0);
r_data2 : out STD_LOGIC_VECTOR (63 downto 0);
w_reg : in STD_LOGIC_VECTOR (4 downto 0);
r_reg1 : in STD_LOGIC_VECTOR (4 downto 0);
r_reg2 : in STD_LOGIC_VECTOR (4 downto 0);
r_data19 : out STD_LOGIC_VECTOR (63 downto 0); --Here down are just to track that the registers are being written to properly
r_data20 : out STD_LOGIC_VECTOR (63 downto 0);
r_data21 : out STD_LOGIC_VECTOR (63 downto 0);
r_data24 : out STD_LOGIC_VECTOR (63 downto 0));
end register_file1;
architecture Behavioral of register_file1 is
signal reg_sel : STD_LOGIC_VECTOR (31 downto 0);
signal w_sel: STD_LOGIC_VECTOR(31 downto 0);
signal reg_data0 : STD_LOGIC_VECTOR(63 downto 0);
signal reg_data1 : STD_LOGIC_VECTOR(63 downto 0);
signal reg_data2 : STD_LOGIC_VECTOR(63 downto 0);
signal reg_data3 : STD_LOGIC_VECTOR(63 downto 0);
signal reg_data4 : STD_LOGIC_VECTOR(63 downto 0);
signal reg_data5 : STD_LOGIC_VECTOR(63 downto 0);
signal reg_data6 : STD_LOGIC_VECTOR(63 downto 0);
signal reg_data7 : STD_LOGIC_VECTOR(63 downto 0);
signal reg_data8 : STD_LOGIC_VECTOR(63 downto 0);
signal reg_data9 : STD_LOGIC_VECTOR(63 downto 0);
signal reg_data10 : STD_LOGIC_VECTOR(63 downto 0);
signal reg_data11 : STD_LOGIC_VECTOR(63 downto 0);
signal reg_data12 : STD_LOGIC_VECTOR(63 downto 0);
signal reg_data13 : STD_LOGIC_VECTOR(63 downto 0);
signal reg_data14 : STD_LOGIC_VECTOR(63 downto 0);
signal reg_data15 : STD_LOGIC_VECTOR(63 downto 0);
signal reg_data16 : STD_LOGIC_VECTOR(63 downto 0);
signal reg_data17 : STD_LOGIC_VECTOR(63 downto 0);
signal reg_data18 : STD_LOGIC_VECTOR(63 downto 0);
signal reg_data19 : STD_LOGIC_VECTOR(63 downto 0);
signal reg_data20 : STD_LOGIC_VECTOR(63 downto 0);
signal reg_data21 : STD_LOGIC_VECTOR(63 downto 0);
signal reg_data22 : STD_LOGIC_VECTOR(63 downto 0);
signal reg_data23 : STD_LOGIC_VECTOR(63 downto 0);
signal reg_data24 : STD_LOGIC_VECTOR(63 downto 0);
signal reg_data25 : STD_LOGIC_VECTOR(63 downto 0);
signal reg_data26 : STD_LOGIC_VECTOR(63 downto 0);
signal reg_data27 : STD_LOGIC_VECTOR(63 downto 0);
signal reg_data28 : STD_LOGIC_VECTOR(63 downto 0);
signal reg_data29 : STD_LOGIC_VECTOR(63 downto 0);
signal reg_data30 : STD_LOGIC_VECTOR(63 downto 0);
signal reg_data31 : STD_LOGIC_VECTOR(63 downto 0) := x"0000000000000000"; --zero register
begin
--These are signals for the test bench to track if they are being properly written to
r_data19 <= reg_data19;
r_data20 <= reg_data20;
r_data21 <= reg_data21;
r_data24 <= reg_data24;
--mux for read data1
r_data1 <= reg_data0 when (r_reg1 = "00000")
else reg_data1 when (r_reg1 = "00001")
else reg_data2 when (r_reg1 = "00010")
else reg_data3 when (r_reg1 = "00011")
else reg_data4 when (r_reg1 = "00100")
else reg_data5 when (r_reg1 = "00101")
else reg_data6 when (r_reg1 = "00110")
else reg_data7 when (r_reg1 = "00111")
else reg_data8 when (r_reg1 = "01000")
else reg_data9 when (r_reg1 = "01001")
else reg_data10 when (r_reg1 = "01010")
else reg_data11 when (r_reg1 = "01011")
else reg_data12 when (r_reg1 = "01100")
else reg_data13 when (r_reg1 = "01101")
else reg_data14 when (r_reg1 = "01110")
else reg_data15 when (r_reg1 = "01111")
else reg_data16 when (r_reg1 = "10000")
else reg_data17 when (r_reg1 = "10001")
else reg_data18 when (r_reg1 = "10010")
else reg_data19 when (r_reg1 = "10011")
else reg_data20 when (r_reg1 = "10100")
else reg_data21 when (r_reg1 = "10101")
else reg_data22 when (r_reg1 = "10110")
else reg_data23 when (r_reg1 = "10111")
else reg_data24 when (r_reg1 = "11000")
else reg_data25 when (r_reg1 = "11001")
else reg_data26 when (r_reg1 = "11010")
else reg_data27 when (r_reg1 = "11011")
else reg_data28 when (r_reg1 = "11100")
else reg_data29 when (r_reg1 = "11101")
else reg_data30 when (r_reg1 = "11110")
else reg_data31 when (r_reg1 = "11111");
--mux for read data 2
r_data2 <= reg_data0 when (r_reg2 = "00000")
else reg_data1 when (r_reg2 = "00001")
else reg_data2 when (r_reg2 = "00010")
else reg_data3 when (r_reg2 = "00011")
else reg_data4 when (r_reg2 = "00100")
else reg_data5 when (r_reg2 = "00101")
else reg_data6 when (r_reg2 = "00110")
else reg_data7 when (r_reg2 = "00111")
else reg_data8 when (r_reg2 = "01000")
else reg_data9 when (r_reg2 = "01001")
else reg_data10 when (r_reg2 = "01010")
else reg_data11 when (r_reg2 = "01011")
else reg_data12 when (r_reg2 = "01100")
else reg_data13 when (r_reg2 = "01101")
else reg_data14 when (r_reg2 = "01110")
else reg_data15 when (r_reg2 = "01111")
else reg_data16 when (r_reg2 = "10000")
else reg_data17 when (r_reg2 = "10001")
else reg_data18 when (r_reg2 = "10010")
else reg_data19 when (r_reg2 = "10011")
else reg_data20 when (r_reg2 = "10100")
else reg_data21 when (r_reg2 = "10101")
else reg_data22 when (r_reg2 = "10110")
else reg_data23 when (r_reg2 = "10111")
else reg_data24 when (r_reg2 = "11000")
else reg_data25 when (r_reg2 = "11001")
else reg_data26 when (r_reg2 = "11010")
else reg_data27 when (r_reg2 = "11011")
else reg_data28 when (r_reg2 = "11100")
else reg_data29 when (r_reg2 = "11101")
else reg_data30 when (r_reg2 = "11110")
else reg_data31 when (r_reg2 = "11111");
decoder1 : decoder port map(reg_addr => w_reg, w => w_en, found => reg_sel);
--write select signal. Takes the write enable (w_en) and the selected register from the decoder and uses that to determine which, if any, register is to be written to. Register 31 is never selected, because it is the zero register and cannot be written to.
w_sel(0) <= (reg_sel(0) and w_en);
w_sel(1) <= (reg_sel(1) and w_en);
w_sel(2) <= (reg_sel(2) and w_en);
w_sel(3) <= (reg_sel(3) and w_en);
w_sel(4) <= (reg_sel(4) and w_en);
w_sel(5) <= (reg_sel(5) and w_en);
w_sel(6) <= (reg_sel(6) and w_en);
w_sel(7) <= (reg_sel(7) and w_en);
w_sel(8) <= (reg_sel(8) and w_en);
w_sel(9) <= (reg_sel(9) and w_en);
w_sel(10) <= (reg_sel(10) and w_en);
w_sel(11) <= (reg_sel(11) and w_en);
w_sel(12) <= (reg_sel(12) and w_en);
w_sel(13) <= (reg_sel(13) and w_en);
w_sel(14) <= (reg_sel(14) and w_en);
w_sel(15) <= (reg_sel(15) and w_en);
w_sel(16) <= (reg_sel(16) and w_en);
w_sel(17) <= (reg_sel(17) and w_en);
w_sel(18) <= (reg_sel(18) and w_en);
w_sel(19) <= (reg_sel(19) and w_en);
w_sel(20) <= (reg_sel(20) and w_en);
w_sel(21) <= (reg_sel(21) and w_en);
w_sel(22) <= (reg_sel(22) and w_en);
w_sel(23) <= (reg_sel(23) and w_en);
w_sel(24) <= (reg_sel(24) and w_en);
w_sel(25) <= (reg_sel(25) and w_en);
w_sel(26) <= (reg_sel(26) and w_en);
w_sel(27) <= (reg_sel(27) and w_en);
w_sel(28) <= (reg_sel(28) and w_en);
w_sel(29) <= (reg_sel(29) and w_en);
w_sel(30) <= (reg_sel(30) and w_en);
--Registers. I know that there is a way to generate these simpler with indexing, but we couldn't get it to work.
register0 : newRegister port map( clk => clk, reset => reset, w_en => w_en, w_data => w_data , r_data => reg_data0, sel => w_sel(0));
register1 : newRegister port map( clk => clk, reset => reset, w_en => w_en, w_data => w_data , r_data => reg_data1, sel => w_sel(1));
register2 : newRegister port map( clk => clk, reset => reset, w_en => w_en, w_data => w_data , r_data => reg_data2, sel => w_sel(2));
register3 : newRegister port map( clk => clk, reset => reset, w_en => w_en, w_data => w_data , r_data => reg_data3, sel => w_sel(3));
register4 : newRegister port map( clk => clk, reset => reset, w_en => w_en, w_data => w_data , r_data => reg_data4, sel => w_sel(4));
register5 : newRegister port map( clk => clk, reset => reset, w_en => w_en, w_data => w_data , r_data => reg_data5, sel => w_sel(5));
register6 : newRegister port map( clk => clk, reset => reset, w_en => w_en, w_data => w_data , r_data => reg_data6, sel => w_sel(6));
register7 : newRegister port map( clk => clk, reset => reset, w_en => w_en, w_data => w_data , r_data => reg_data7, sel => w_sel(7));
register8 : newRegister port map( clk => clk, reset => reset, w_en => w_en, w_data => w_data , r_data => reg_data8, sel => w_sel(8));
register9 : newRegister port map( clk => clk, reset => reset, w_en => w_en, w_data => w_data , r_data => reg_data9, sel => w_sel(9));
register10 : newRegister port map( clk => clk, reset => reset, w_en => w_en, w_data => w_data , r_data => reg_data10, sel => w_sel(10));
register11 : newRegister port map( clk => clk, reset => reset, w_en => w_en, w_data => w_data , r_data => reg_data11, sel => w_sel(11));
register12 : newRegister port map( clk => clk, reset => reset, w_en => w_en, w_data => w_data , r_data => reg_data12, sel => w_sel(12));
register13 : newRegister port map( clk => clk, reset => reset, w_en => w_en, w_data => w_data , r_data => reg_data13, sel => w_sel(13));
register14 : newRegister port map( clk => clk, reset => reset, w_en => w_en, w_data => w_data , r_data => reg_data14, sel => w_sel(14));
register15 : newRegister port map( clk => clk, reset => reset, w_en => w_en, w_data => w_data , r_data => reg_data15, sel => w_sel(15));
register16 : newRegister port map( clk => clk, reset => reset, w_en => w_en, w_data => w_data , r_data => reg_data16, sel => w_sel(16));
register17 : newRegister port map( clk => clk, reset => reset, w_en => w_en, w_data => w_data , r_data => reg_data17, sel => w_sel(17));
register18 : newRegister port map( clk => clk, reset => reset, w_en => w_en, w_data => w_data , r_data => reg_data18, sel => w_sel(18));
register19 : newRegister port map( clk => clk, reset => reset, w_en => w_en, w_data => w_data , r_data => reg_data19, sel => w_sel(19));
register20 : newRegister port map( clk => clk, reset => reset, w_en => w_en, w_data => w_data , r_data => reg_data20, sel => w_sel(20));
register21 : newRegister port map( clk => clk, reset => reset, w_en => w_en, w_data => w_data , r_data => reg_data21, sel => w_sel(21));
register22 : newRegister port map( clk => clk, reset => reset, w_en => w_en, w_data => w_data , r_data => reg_data22, sel => w_sel(22));
register23 : newRegister port map( clk => clk, reset => reset, w_en => w_en, w_data => w_data , r_data => reg_data23, sel => w_sel(23));
register24 : newRegister port map( clk => clk, reset => reset, w_en => w_en, w_data => w_data , r_data => reg_data24, sel => w_sel(24));
register25 : newRegister port map( clk => clk, reset => reset, w_en => w_en, w_data => w_data , r_data => reg_data25, sel => w_sel(25));
register26 : newRegister port map( clk => clk, reset => reset, w_en => w_en, w_data => w_data , r_data => reg_data26, sel => w_sel(26));
register27 : newRegister port map( clk => clk, reset => reset, w_en => w_en, w_data => w_data , r_data => reg_data27, sel => w_sel(27));
register28 : newRegister port map( clk => clk, reset => reset, w_en => w_en, w_data => w_data , r_data => reg_data28, sel => w_sel(28));
register29 : newRegister port map( clk => clk, reset => reset, w_en => w_en, w_data => w_data , r_data => reg_data29, sel => w_sel(29));
register30 : newRegister port map( clk => clk, reset => reset, w_en => w_en, w_data => w_data , r_data => reg_data30, sel => w_sel(30));
register31 : newRegister port map( clk => clk, reset => reset, w_en => '0', w_data => w_data , r_data => reg_data31, sel => '0');
end Behavioral;
Декодер:
entity decoder is
Port ( reg_addr : in STD_LOGIC_VECTOR (4 downto 0);
w : in std_logic;
found : out STD_LOGIC_VECTOR (31 downto 0)
) ;
end decoder;
architecture Behavioral of decoder is
begin
process(reg_addr)
begin
case reg_addr is
when "00000" => found <= x"00000001";
when "00001" => found <= x"00000002";
when "00010" => found <= x"00000004";
when "00011" => found <= x"00000008";
when "00100" => found <= x"00000010";
when "00101" => found <= x"00000020";
when "00110" => found <= x"00000040";
when "00111" => found <= x"00000080";
when "01000" => found <= x"00000100";
when "01001" => found <= x"00000200";
when "01010" => found <= x"00000400";
when "01011" => found <= x"00000800";
when "01100" => found <= x"00001000";
when "01101" => found <= x"00002000";
when "01110" => found <= x"00004000";
when "01111" => found <= x"00008000";
when "10000" => found <= x"00010000";
when "10001" => found <= x"00020000";
when "10010" => found <= x"00040000";
when "10011" => found <= x"00080000";
when "10100" => found <= x"00100000";
when "10101" => found <= x"00200000";
when "10110" => found <= x"00400000";
when "10111" => found <= x"00800000";
when "11000" => found <= x"01000000";
when "11001" => found <= x"02000000";
when "11010" => found <= x"04000000";
when "11011" => found <= x"08000000";
when "11100" => found <= x"10000000";
when "11101" => found <= x"20000000";
when "11110" => found <= x"40000000";
when "11111" => found <= x"80000000";
when others => found <= x"00000000";
end case;
end process;
end Behavioral;
Регистры:
entity newRegister is
Port ( clk : in STD_LOGIC;
reset : in STD_LOGIC;
sel : in STD_LOGIC; --register select enable
w_en : in STD_LOGIC; --write enable
w_data : in STD_LOGIC_VECTOR (63 downto 0);
r_data : out STD_LOGIC_VECTOR (63 downto 0)
);
end newRegister;
architecture Behavioral of newRegister is
signal reg: std_logic_vector(63 downto 0); --internal register storage
begin
process(clk) --nothing happens if this register isn't selected
begin
if reset = '1' then
reg <= x"0000000000000000";
end if;
if rising_edge(clk) then
if sel='1' then
reg <= w_data; --load new data into register memory
end if;
end if;
end process;
r_data <= reg ;
end Behavioral;
Пакет:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
package RegPackage is
component newRegister is
Port ( clk : in STD_LOGIC;
reset : in STD_LOGIC;
sel : in STD_LOGIC; --register select enable
w_en : in STD_LOGIC; --write enable
w_data : in STD_LOGIC_VECTOR (63 downto 0);
r_data : out STD_LOGIC_VECTOR (63 downto 0)
);
end component;
component decoder is
Port ( reg_addr : in STD_LOGIC_VECTOR (4 downto 0);
w : in std_logic;
found : out STD_LOGIC_VECTOR (31 downto 0)
) ;
end component;
end RegPackage;
Тестовый стенд предназначен для имитации того, что будет происходить в регистрах для следующего кода сборки ARMv8:
ADDI X24, XZR, #2048 // Address 2048 is stored in X24
ADDI X19, XZR, #10 // X19 = a = 10
ADDI X20, XZR, #5 // X20 = b = 5
ADD X21, X19, X20 // X21 = a + b = 10 + 5 = 15
STUR X21, [X24, #0] // send value X21 to 7 seg display
END
и:
entity testbench1 is
-- Port ( );
end testbench1;
architecture Behavioral of testbench1 is
component register_file1 is
Port( clk : in STD_LOGIC;
reset : in STD_LOGIC;
w_en : in STD_LOGIC;
w_data : in STD_LOGIC_VECTOR (63 downto 0);
r_data1 : out STD_LOGIC_VECTOR (63 downto 0);
r_data2 : out STD_LOGIC_VECTOR (63 downto 0);
w_reg : in STD_LOGIC_VECTOR (4 downto 0);
r_reg1 : in STD_LOGIC_VECTOR (4 downto 0);
r_reg2 : in STD_LOGIC_VECTOR (4 downto 0);
r_data19 : out STD_LOGIC_VECTOR (63 downto 0);
r_data20 : out STD_LOGIC_VECTOR (63 downto 0);
r_data21 : out STD_LOGIC_VECTOR (63 downto 0);
r_data24 : out STD_LOGIC_VECTOR (63 downto 0));
end component;
signal clk : STD_LOGIC := '0';
signal reset : STD_LOGIC := '0';
signal w_en : STD_LOGIC := '0';
signal w_data : STD_LOGIC_VECTOR (63 downto 0) := x"ABCDEF0123456789";
signal r_data1 : STD_LOGIC_VECTOR (63 downto 0) := x"0000000000000000";
signal r_data2 : STD_LOGIC_VECTOR (63 downto 0) := x"0000000000000000";
signal w_reg : STD_LOGIC_VECTOR (4 downto 0) := "00000";
signal r_reg1 : STD_LOGIC_VECTOR (4 downto 0) := "00000";
signal r_reg2 : STD_LOGIC_VECTOR (4 downto 0) := "00000";
signal r_data19 : STD_LOGIC_VECTOR (63 downto 0);
signal r_data20 : STD_LOGIC_VECTOR (63 downto 0);
signal r_data21 : STD_LOGIC_VECTOR (63 downto 0);
signal r_data24 : STD_LOGIC_VECTOR (63 downto 0);
begin
uut: register_file1 PORT MAP (
clk => clk,
reset => reset,
w_en => w_en,
w_data => w_data,
r_data1 => r_data1,
r_data2 => r_data2,
w_reg => w_reg,
r_reg1 => r_reg1,
r_reg2 => r_reg2,
r_data19 => r_data19,
r_data20 => r_data20,
r_data21 => r_data21,
r_data24 => r_data24);
process
begin
wait for 10 ns;
clk <= not clk;
w_en <= '1';
w_data <= x"0000000000000800";
w_reg <= "11000";
wait for 10 ns;
clk <= not clk;
w_en <= '0';
wait for 10 ns;
clk <= not clk;
w_en <= '1';
w_data <= x"000000000000000A";
w_reg <= "10011";
wait for 10ns;
clk <= not clk;
w_en <= '0';
wait for 10ns;
clk <= not clk;
w_en <= '1';
w_data <= x"0000000000000005";
w_reg <= "10100";
wait for 10ns;
clk <= not clk;
wait for 10ns;
clk <= not clk;
w_en <= '0';
r_reg1 <= "10011";
r_reg2 <= "10100";
wait for 10ns;
clk <= not clk;
wait for 10ns;
clk <= not clk;
w_en <= '1';
w_data <= x"000000000000000F";
w_reg <= "10101";
wait for 10ns;
clk <= not clk;
wait for 10ns;
clk <= not clk;
w_en <= '0';
r_reg1 <= "10101";
r_reg2 <= "11000";
wait for 10ns;
wait;
end process;
end Behavioral;
Что приводит к следующему:
Кажется, иногда пишут, а иногда нет, и я не знаю, в чем разница между тем, когда это происходит икогда это не так.Похоже, что он всегда читает нормально.
Кажется, что между считыванием вновь записанных данных существует задержка в один такт, чего я не ожидал, но сейчас я не беспокоюсь.