mirror of
https://github.com/xarc/harv.git
synced 2025-04-18 19:24:51 -04:00
240 lines
7.9 KiB
VHDL
240 lines
7.9 KiB
VHDL
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use ieee.numeric_std.all;
|
|
|
|
use std.textio.all;
|
|
use ieee.std_logic_textio.all;
|
|
|
|
library work;
|
|
use work.harv_pkg.harv;
|
|
|
|
entity sim_from_dump is
|
|
end entity;
|
|
|
|
architecture arch of sim_from_dump is
|
|
constant period : time := 100 ns;
|
|
signal rstn : std_logic := '0';
|
|
signal clk : std_logic := '0';
|
|
signal start : std_logic := '0';
|
|
|
|
constant INST_BASE_ADDR : integer := 0;
|
|
constant INST_SIZE : integer := 4096;
|
|
constant DATA_BASE_ADDR : integer := 8192;
|
|
constant DATA_SIZE : integer := 4096;
|
|
|
|
type mem_t is array(natural range <>) of std_logic_vector(7 downto 0);
|
|
signal inst_mem : mem_t(INST_SIZE + INST_BASE_ADDR - 1 downto INST_BASE_ADDR);
|
|
signal data_mem : mem_t(DATA_SIZE + DATA_BASE_ADDR - 1 downto DATA_BASE_ADDR);
|
|
|
|
-- instruction memory interface
|
|
signal imem_instr_i : std_logic_vector(31 downto 0);
|
|
signal imem_pc_o : std_logic_vector(31 downto 0);
|
|
signal imem_req_o : std_logic;
|
|
signal imem_gnt_i : std_logic;
|
|
|
|
-- data memory interface
|
|
signal dmem_data_i : std_logic_vector(31 downto 0);
|
|
signal dmem_req_o : std_logic;
|
|
signal dmem_wren_o : std_logic;
|
|
signal dmem_gnt_i : std_logic;
|
|
signal dmem_outofrange_i : std_logic;
|
|
signal dmem_byte_en_o : std_logic_vector(1 downto 0);
|
|
signal dmem_usgn_dat_o : std_logic;
|
|
signal dmem_data_o : std_logic_vector(31 downto 0);
|
|
signal dmem_addr_o : std_logic_vector(31 downto 0);
|
|
|
|
constant INST_DUMP_FILE_PATH : string := "../../../../../src/test_text.dump";
|
|
constant DATA_DUMP_FILE_PATH : string := "../../../../../src/test_data.dump";
|
|
|
|
procedure load_memory (
|
|
constant FILE_PATH : in string;
|
|
constant BASE_ADDR : in integer;
|
|
signal mem : out mem_t
|
|
) is
|
|
file file_v : text;
|
|
variable line_v : line;
|
|
variable addr_v : integer;
|
|
variable byte_v : std_logic_vector(7 downto 0);
|
|
variable error_v : boolean;
|
|
begin
|
|
-- read data dump file
|
|
file_open(file_v, FILE_PATH, READ_MODE);
|
|
-- initialize instructions address counter
|
|
addr_v := BASE_ADDR;
|
|
-- iterate through all lines in the file
|
|
while not endfile(file_v) loop
|
|
-- read line from file_v
|
|
readline(file_v, line_v);
|
|
-- ensure that the line is not empty
|
|
if line_v'length > 0 then
|
|
-- iterate in each byte of the data
|
|
for i in 3 downto 0 loop
|
|
-- read hex byte from line
|
|
hread(line_v, byte_v, error_v);
|
|
-- assert if the hread had an error
|
|
assert (error_v) report "Text I/O read error" severity FAILURE;
|
|
-- write byte to memory
|
|
mem(addr_v + i) <= byte_v;
|
|
end loop;
|
|
-- increment address
|
|
addr_v := addr_v + 4;
|
|
end if;
|
|
end loop;
|
|
file_close(file_v);
|
|
end procedure;
|
|
begin
|
|
rstn <= '1' after period;
|
|
clk <= not clk after period/2;
|
|
start <= '1' after period * 2; -- set start signal after 2 clock cycles
|
|
|
|
harv_i : harv
|
|
generic map (
|
|
PROGRAM_START_ADDR => x"00000000",
|
|
TRAP_HANDLER_ADDR => x"00000000",
|
|
TMR_CONTROL => FALSE,
|
|
TMR_ALU => FALSE,
|
|
HAMMING_REGFILE => FALSE,
|
|
HAMMING_PC => FALSE
|
|
)
|
|
port map (
|
|
rstn_i => rstn,
|
|
clk_i => clk,
|
|
start_i => start,
|
|
poweron_rstn_i => rstn,
|
|
wdt_rstn_i => '1',
|
|
imem_instr_i => imem_instr_i,
|
|
imem_pc_o => imem_pc_o,
|
|
imem_req_o => imem_req_o,
|
|
imem_gnt_i => imem_gnt_i,
|
|
imem_err_i => '0',
|
|
hard_dmem_o => open,
|
|
dmem_data_i => dmem_data_i,
|
|
dmem_req_o => dmem_req_o,
|
|
dmem_wren_o => dmem_wren_o,
|
|
dmem_gnt_i => dmem_gnt_i,
|
|
dmem_outofrange_i => dmem_outofrange_i,
|
|
dmem_sbu_i => '0',
|
|
dmem_dbu_i => '0',
|
|
dmem_byte_en_o => dmem_byte_en_o,
|
|
dmem_usgn_dat_o => dmem_usgn_dat_o,
|
|
dmem_data_o => dmem_data_o,
|
|
dmem_addr_o => dmem_addr_o
|
|
);
|
|
|
|
-- INSTRUCTION MEMORY ACCESS
|
|
process
|
|
variable addr_v : integer;
|
|
begin
|
|
-- load instruction memory
|
|
report "Loading instruction memory from " & INST_DUMP_FILE_PATH severity NOTE;
|
|
load_memory(INST_DUMP_FILE_PATH, INST_BASE_ADDR, inst_mem);
|
|
-- infinite loop to provide instruction memory access
|
|
loop
|
|
-- disable grant signal
|
|
imem_gnt_i <= '0';
|
|
imem_instr_i <= (others => 'X');
|
|
-- wait memory request
|
|
wait until rising_edge(clk) and imem_req_o = '1';
|
|
-- wait 1 cycle to give response
|
|
wait for period;
|
|
-- grant response
|
|
imem_gnt_i <= '1';
|
|
addr_v := to_integer(unsigned(imem_pc_o));
|
|
imem_instr_i <= inst_mem(addr_v+3) &
|
|
inst_mem(addr_v+2) &
|
|
inst_mem(addr_v+1) &
|
|
inst_mem(addr_v);
|
|
-- grant response for 1 cycle
|
|
wait for period;
|
|
end loop;
|
|
end process;
|
|
|
|
-- DATA MEMORY ACCESS
|
|
process
|
|
variable addr_v : integer;
|
|
begin
|
|
-- if there is no data dump file
|
|
if DATA_DUMP_FILE_PATH = "" then
|
|
report "No data memory to load" severity NOTE;
|
|
else -- if data dump file is defined
|
|
-- load data memory from file
|
|
report "Loading data memory from " & DATA_DUMP_FILE_PATH severity NOTE;
|
|
load_memory (DATA_DUMP_FILE_PATH, DATA_BASE_ADDR, data_mem);
|
|
end if;
|
|
-- infinite loop to provide data memory access
|
|
loop
|
|
-- disable grant signal
|
|
dmem_gnt_i <= '0';
|
|
dmem_data_i <= (others => 'X');
|
|
dmem_outofrange_i <= '0';
|
|
-- wait memory request
|
|
wait until rising_edge(clk) and dmem_req_o = '1';
|
|
-- wait 1 cycle to give response
|
|
wait for period;
|
|
-- convert address to integer
|
|
addr_v := to_integer(unsigned(dmem_addr_o));
|
|
-- check if range is ok
|
|
if addr_v < DATA_BASE_ADDR or addr_v > (DATA_BASE_ADDR + DATA_SIZE) then
|
|
dmem_outofrange_i <= '1';
|
|
else
|
|
-- grant response
|
|
dmem_gnt_i <= '1';
|
|
-- if it will perform a write
|
|
if dmem_wren_o = '1' then
|
|
-- write the first byte
|
|
data_mem(addr_v) <= dmem_data_o(7 downto 0);
|
|
-- write the second byte for half-word and word
|
|
if dmem_byte_en_o(0) = '1' then
|
|
data_mem(addr_v+1) <= dmem_data_o(15 downto 8);
|
|
end if;
|
|
-- write the upper 16 bits, only for full word
|
|
if dmem_byte_en_o(1) = '1' then
|
|
data_mem(addr_v+2) <= dmem_data_o(23 downto 16);
|
|
data_mem(addr_v+3) <= dmem_data_o(31 downto 24);
|
|
end if;
|
|
|
|
-- read data memory
|
|
else
|
|
-- case between all acess possibilities
|
|
case dmem_byte_en_o is
|
|
-- byte read with and without sign-extension
|
|
when "00" =>
|
|
if dmem_usgn_dat_o = '1' then
|
|
dmem_data_i <= x"000000" & data_mem(addr_v);
|
|
else
|
|
dmem_data_i <= (
|
|
31 downto 8 => data_mem(addr_v)(7),
|
|
7 downto 0 => data_mem(0)
|
|
);
|
|
end if;
|
|
|
|
-- half-word read with and without sign-extension
|
|
when "01" =>
|
|
if dmem_usgn_dat_o = '1' then
|
|
dmem_data_i <= (
|
|
31 downto 16 => data_mem(addr_v + 1)(7),
|
|
15 downto 8 => data_mem(addr_v + 1),
|
|
7 downto 0 => data_mem(addr_v)
|
|
);
|
|
else
|
|
dmem_data_i <= x"000000" & data_mem(addr_v);
|
|
end if;
|
|
|
|
-- word read - concatanate bytes
|
|
when "11" =>
|
|
dmem_data_i <= data_mem(addr_v + 3) &
|
|
data_mem(addr_v + 2) &
|
|
data_mem(addr_v + 1) &
|
|
data_mem(addr_v);
|
|
when others =>
|
|
report "Wrong parameters to data memory" severity ERROR;
|
|
|
|
end case;
|
|
end if;
|
|
end if;
|
|
-- response for 1 cycle
|
|
wait for period;
|
|
end loop;
|
|
end process;
|
|
|
|
end architecture;
|