HARV project

This commit is contained in:
Douglas Santos 2021-06-17 17:23:41 +02:00
parent 807fe54447
commit 3dcef8bce8
22 changed files with 3161 additions and 2 deletions

12
.gitignore vendored Normal file
View file

@ -0,0 +1,12 @@
*/**
!*/
!/hdl/**/*.vhd
!/sim/**/*.vhd
!/src/**/*.asm
!/script/*.sh
!/script/*.py
!/script/*.do
!/script/*.tcl
!/script/*.ld
!/xilinx/*.wcfg
!/images/*.png

View file

@ -1,2 +1,42 @@
# harv
HARV - HArdened Risc-V
# HARV - HArdened Risc-V
The focus of the HARV processor core is harsh environments. It implements the integer instruction-set of the RISC-V specification (RV32I), except system calls. To provide reliability for harsh environments, we implement the fault tolerance techniques TMR (Triple-Modular Redundancy) and Hamming code to the different parts of the processor. These techniques improve the reliability by mitigating or correcting errors caused by the single-event effects SEU (Single-Event Upset) and SET (Single-Event Transient).
HARV is being developed in partnership between the **LEDS - Laboratory of Embedded and Distributed Systems** and the **LIRMM - Laboratoire dInformatique, de Robotique et de Microélectronique de Montpellier**.
The HARV was introduced by the following paper published at the IEEE DTIS 2021:
D. A. Santos, L. M. Luza, C. A. Zeferino, L. Dilillo and D. R. Melo, "A Low-Cost Fault-Tolerant RISC-V Processor for Space Systems," *2020 15th Design & Technology of Integrated Systems in Nanoscale Era (DTIS), 2020*, pp. 1-5, doi: [10.1109/DTIS48698.2020.9081185](https://doi.org/10.1109/DTIS48698.2020.9081185).
The current mantainer of this repository is [Douglas Almeida dos Santos](https://github.com/Douglasas).
## Getting started
This getting started is a tutorial for the simulation of the simple assembly program `src/test.asm`
Requirements:
- Vivado 2020.2
- RARS 1.5
Open the RARS and open the assembly file from the sources folder.
You will need to configure the memory to work with the testbench parameters. The following image shows the required memory configuration.
![RARS memory configuration](images/rars-memory-configuration.png)
After that, you may export the assembly code so it can be used by the testbench.
Dump both the `.text` and `.data` sections to the `src` folder. The following images shows the configurations that must be used for the memory dump.
The file paths must be `src/test_text.dump` and `src/test_data.dump` for the sections, respectively.
![RARS .text export](images/rars-text-export.png)
![RARS .data export](images/rars-data-export.png)
The next step is to create and open the Vivado project.
Execute the following command at the terminal and at the root project directory. Note that Vivado must be in the path.
```
vivado -mode tcl -source script/project.tcl
```
After that, you may open the Vivado project through the interface and run the simulation set 1.

59
hdl/alu.vhd Normal file
View file

@ -0,0 +1,59 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.harv_pkg.all;
entity alu is
port (
-- input ports
data1_i : in std_logic_vector(31 downto 0);
data2_i : in std_logic_vector(31 downto 0);
operation_i : in std_logic_vector(ALUOP_SIZE-1 downto 0);
-- output ports
zero_o : out std_logic;
data_o : out std_logic_vector(31 downto 0)
);
end entity;
architecture arch of alu is
signal add_sub_data2_w : signed(31 downto 0);
signal add_sub_w : std_logic_vector(31 downto 0);
signal and_w : std_logic_vector(31 downto 0);
signal or_w : std_logic_vector(31 downto 0);
signal xor_w : std_logic_vector(31 downto 0);
signal sll_w : std_logic_vector(31 downto 0);
signal srl_w : std_logic_vector(31 downto 0);
signal sra_w : std_logic_vector(31 downto 0);
signal slt_w : std_logic_vector(31 downto 0);
signal sltu_w : std_logic_vector(31 downto 0);
signal result_w : std_logic_vector(31 downto 0);
begin
add_sub_data2_w <= signed(data2_i) when operation_i = ALU_ADD_OP else -signed(data2_i);
add_sub_w <= std_logic_vector(signed(data1_i) + add_sub_data2_w);
and_w <= data1_i and data2_i;
or_w <= data1_i or data2_i;
xor_w <= data1_i xor data2_i;
sll_w <= std_logic_vector(shift_left(unsigned(data1_i), to_integer(unsigned(data2_i))));
srl_w <= std_logic_vector(shift_right(unsigned(data1_i), to_integer(unsigned(data2_i))));
sra_w <= std_logic_vector(shift_right(signed(data1_i), to_integer(unsigned(data2_i))));
slt_w <= (0 => '1', others => '0') when signed(data1_i) < signed(data2_i) else (others => '0');
sltu_w <= (0 => '1', others => '0') when unsigned(data1_i) < unsigned(data2_i) else (others => '0');
with operation_i select result_w <=
add_sub_w when ALU_ADD_OP,
add_sub_w when ALU_SUB_OP,
sll_w when ALU_SLL_OP,
slt_w when ALU_SLT_OP,
sltu_w when ALU_SLTU_OP,
xor_w when ALU_XOR_OP,
srl_w when ALU_SRL_OP,
sra_w when ALU_SRA_OP,
or_w when ALU_OR_OP,
and_w when ALU_AND_OP,
(others => '0') when others;
data_o <= result_w;
zero_o <= '1' when result_w = (31 downto 0 => '0') else '0';
end architecture;

282
hdl/control.vhd Normal file
View file

@ -0,0 +1,282 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.harv_pkg.all;
entity control is
port (
-- input ports
-- processor status
imem_gnt_i : in std_logic;
imem_err_i : in std_logic;
dmem_gnt_i : in std_logic;
dmem_outofrange_i : in std_logic;
dmem_sbu_i : in std_logic;
dmem_dbu_i : in std_logic;
-- instruction decode
opcode_i : in std_logic_vector(6 downto 0);
funct3_i : in std_logic_vector(2 downto 0);
funct7_i : in std_logic_vector(6 downto 0);
funct12_i : in std_logic_vector(11 downto 0);
-- sync
rstn_i : in std_logic;
clk_i : in std_logic;
start_i : in std_logic;
-- output ports
-- processor status
imem_req_o : out std_logic;
dmem_req_o : out std_logic;
update_pc_o : out std_logic;
trap_o : out std_logic;
-- ALU operations
aluop_o : out std_logic_vector(ALUOP_SIZE-1 downto 0);
alusrc_imm_o : out std_logic;
-- immediate selector
imm_shamt_o : out std_logic;
imm_up_o : out std_logic;
-- register bank
regwr_o : out std_logic;
-- control transfer
inv_branch_o : out std_logic;
branch_o : out std_logic;
jump_o : out std_logic;
jalr_o : out std_logic;
ecall_o : out std_logic;
-- mem access
memrd_o : out std_logic;
memwr_o : out std_logic;
byte_en_o : out std_logic_vector(1 downto 0);
mem_usgn_o : out std_logic; -- unsigned data
-- U type
load_upimm_o : out std_logic;
auipc_o : out std_logic;
-- csr control
csr_enable_o : out std_logic;
csr_source_imm_o : out std_logic;
csr_maskop_o : out std_logic;
csr_clearop_o : out std_logic
);
end entity;
architecture arch of control is
--------- PROCESSOR STATUS -----------
subtype proc_status_t is std_logic_vector(2 downto 0);
constant STAT_IDLE : proc_status_t := "000";
constant STAT_REQ_INSTR : proc_status_t := "001";
constant STAT_RUN : proc_status_t := "010";
constant STAT_DMEM_STALL : proc_status_t := "011";
constant STAT_UPDATE_PC : proc_status_t := "100";
constant STAT_TRAP : proc_status_t := "101";
signal proc_status_r : proc_status_t;
signal next_proc_status_w : proc_status_t;
-------- INSTRUCTION DECODE ----------
subtype instr_format_t is std_logic_vector(3 downto 0);
constant R : instr_format_t := x"1";
constant I_jalr : instr_format_t := x"2";
constant I_load : instr_format_t := x"3";
constant I_arith : instr_format_t := x"4";
constant I_fence : instr_format_t := x"5";
constant I_system : instr_format_t := x"6";
constant S : instr_format_t := x"7";
constant B : instr_format_t := x"8";
constant U_lui : instr_format_t := x"9";
constant U_auipc : instr_format_t := x"A";
constant U_jal : instr_format_t := x"B";
--- CSR TYPES ---
constant SYS_ECALL : std_logic_vector(2 downto 0) := "000";
constant SYS_CSRRW : std_logic_vector(2 downto 0) := "001"; -- Atomic Read/Write CSR
constant SYS_CSRRS : std_logic_vector(2 downto 0) := "010"; -- Atomic Read and Set Bits in CSR
constant SYS_CSRRC : std_logic_vector(2 downto 0) := "011"; -- Atomic Read and Clear Bits in CSR
constant SYS_CSRRWI : std_logic_vector(2 downto 0) := "101";
constant SYS_CSRRSI : std_logic_vector(2 downto 0) := "110";
constant SYS_CSRRCI : std_logic_vector(2 downto 0) := "111";
-- auxiliar signals
signal memwr_w : std_logic;
signal memrd_w : std_logic;
signal memreq_w : std_logic;
-- opcodes
signal instr_format_w : instr_format_t;
-- signal rshift_op_w : std_logic_vector(ALUOP_SIZE-1 downto 0);
-- signal add_op_w : std_logic_vector(ALUOP_SIZE-1 downto 0);
signal arith_aluop_w : std_logic_vector(ALUOP_SIZE-1 downto 0);
signal branch_op_w : std_logic_vector(ALUOP_SIZE-1 downto 0);
begin
------------------------- PROCESSOR STATUS ------------------------------
-- STAT_REQ_INSTR
imem_req_o <= '1' when proc_status_r = STAT_REQ_INSTR else '0';
-- STAT_DMEM_STALL
memreq_w <= memrd_w or memwr_w;
dmem_req_o <= '1' when proc_status_r = STAT_DMEM_STALL else '0';
-- STAT_UPDATE_PC
update_pc_o <= '1' when proc_status_r = STAT_UPDATE_PC else
'1' when proc_status_r = STAT_TRAP else
'0';
trap_o <= '1' when proc_status_r = STAT_TRAP else '0';
PROC_CURRENT_STATUS : process(clk_i, rstn_i)
begin
if rstn_i = '0' then
proc_status_r <= STAT_IDLE;
elsif rising_edge(clk_i) then
proc_status_r <= next_proc_status_w;
end if;
end process;
PROC_NEXT_STATUS : process(proc_status_r, start_i, imem_gnt_i, imem_err_i, dmem_outofrange_i, memreq_w, dmem_gnt_i)
begin
case proc_status_r is
when STAT_IDLE =>
if start_i = '1' then
next_proc_status_w <= STAT_REQ_INSTR;
else
next_proc_status_w <= STAT_IDLE;
end if;
when STAT_REQ_INSTR =>
if imem_err_i = '1' then
next_proc_status_w <= STAT_IDLE;
elsif imem_gnt_i = '1' then
next_proc_status_w <= STAT_RUN;
else
next_proc_status_w <= STAT_REQ_INSTR;
end if;
when STAT_RUN =>
if memreq_w = '1' then
next_proc_status_w <= STAT_DMEM_STALL;
else
next_proc_status_w <= STAT_UPDATE_PC;
end if;
when STAT_DMEM_STALL =>
if dmem_outofrange_i = '1' then -- or dmem_sbu_i = '1' or dmem_dbu_i = '1' then
next_proc_status_w <= STAT_TRAP;
elsif dmem_gnt_i = '1' then
next_proc_status_w <= STAT_UPDATE_PC;
else
next_proc_status_w <= STAT_DMEM_STALL;
end if;
when STAT_UPDATE_PC =>
next_proc_status_w <= STAT_REQ_INSTR;
when STAT_TRAP =>
next_proc_status_w <= STAT_REQ_INSTR;
when others =>
next_proc_status_w <= STAT_TRAP;
end case;
end process;
------------------------ INSTRUCTIONS DECODE ----------------------------
with opcode_i select instr_format_w <=
R when "0110011",
I_jalr when "1100111",
I_load when "0000011",
I_arith when "0010011",
I_fence when "0001111",
I_system when "1110011",
S when "0100011",
B when "1100011",
U_lui when "0110111",
U_auipc when "0010111",
U_jal when "1101111",
(others => '0') when others;
--------------------------------- ALU -----------------------------------
-- rshift_op_w <= ALU_SRL_OP when funct7_i = "0000000" else ALU_SRA_OP;
-- add_op_w <= ALU_SUB_OP when funct7_i = "0100000" and instr_format_w = R else ALU_ADD_OP;
--
-- with funct3_i select arith_aluop_w <=
-- add_op_w when "000",
-- ALU_SLL_OP when "001",
-- ALU_SLT_OP when "010",
-- ALU_SLTU_OP when "011",
-- ALU_XOR_OP when "100",
-- rshift_op_w when "101",
-- ALU_OR_OP when "110",
-- ALU_AND_OP when "111",
-- (others => '0') when others;
arith_aluop_w <= funct7_i(5) & funct3_i;
with funct3_i(2 downto 1) select branch_op_w <=
ALU_XOR_OP when "00", -- beq or bne
ALU_SLT_OP when "10", -- blt or bge
ALU_SLTU_OP when "11", -- bltu or bgeu
(others => '0') when others;
aluop_o <= arith_aluop_w when instr_format_w = I_arith or
instr_format_w = R else
branch_op_w when instr_format_w = B else
ALU_ADD_OP; -- when instr_format_w = U_auipc, I_load, S
alusrc_imm_o <= '1' when instr_format_w /= R and instr_format_w /= B else '0';
------------------------ IMMEDIATE SELECTOR ------------------------------
-- instr[24:20]
imm_shamt_o <= '1' when (arith_aluop_w = ALU_SLL_OP or
arith_aluop_w = ALU_SRL_OP or
arith_aluop_w = ALU_SRA_OP) and
instr_format_w = I_arith else '0';
-- instr[31:12] -> imm[31:12]
imm_up_o <= '1' when instr_format_w = U_lui or
instr_format_w = U_auipc else '0';
----------------------------- REGISTER BANK -------------------------------
regwr_o <= '1' when proc_status_r = STAT_UPDATE_PC and not (
instr_format_w = I_fence or
(instr_format_w = I_system and funct3_i = SYS_ECALL) or
instr_format_w = S or instr_format_w = I_load or
instr_format_w = B) else
'1' when proc_status_r = STAT_DMEM_STALL and
instr_format_w = I_load and
dmem_gnt_i = '1' else
'0';
------------------------------- BRANCHES ----------------------------------
inv_branch_o <= funct3_i(2) xor funct3_i(0);
branch_o <= '1' when instr_format_w = B else '0';
jump_o <= '1' when instr_format_w = U_jal or instr_format_w = I_jalr else '0';
jalr_o <= '1' when instr_format_w = I_jalr else '0';
ecall_o <= '0'; -- '1' when instr_format_w = I_system else
------------------------------ MEM ACCESS ---------------------------------
memrd_w <= '1' when instr_format_w = I_load else '0';
memrd_o <= memrd_w;
memwr_w <= '1' when instr_format_w = S else '0';
memwr_o <= memwr_w;
byte_en_o <= funct3_i(1 downto 0) when funct3_i(1) = '0' else "11"; -- byte or halfword -- else word
mem_usgn_o <= funct3_i(2);
-------------------------------- U type -----------------------------------
load_upimm_o <= '1' when instr_format_w = U_lui else '0';
auipc_o <= '1' when instr_format_w = U_auipc else '0';
-------------------------- CSR instructions ------------------------------
csr_enable_o <= '1' when instr_format_w = I_system and funct3_i /= SYS_ECALL else '0';
csr_source_imm_o <= funct3_i(2); -- select source to write the CSR (immediate or register)
csr_maskop_o <= funct3_i(1); -- write operation based on mask
csr_clearop_o <= funct3_i(0); -- operation is CLEAR, if not, operation is SET
end architecture;

357
hdl/csr.vhd Normal file
View file

@ -0,0 +1,357 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.math_real.ceil;
use ieee.math_real.log2;
use ieee.numeric_std.all;
entity csr is
generic (
TMR_CONTROL : boolean;
TMR_ALU : boolean;
HAMMING_REGFILE : boolean;
HAMMING_PC : boolean
);
port (
-- sync
rstn_i : in std_logic;
clk_i : in std_logic;
-- access interface
addr_i : in std_logic_vector(11 downto 0);
data_o : out std_logic_vector(31 downto 0);
rs1_data_i : in std_logic_vector(31 downto 0);
imm_data_i : in std_logic_vector(4 downto 0);
-- write control
wren_i : in std_logic;
source_imm_i : in std_logic;
csr_maskop_i : in std_logic;
csr_clearop_i : in std_logic;
-- trap handling
trap_i : in std_logic;
uscratch_i : in std_logic_vector(31 downto 0);
uepc_i : in std_logic_vector(31 downto 0);
ucause_i : in std_logic_vector(31 downto 0);
utval_i : in std_logic_vector(31 downto 0);
uip_i : in std_logic_vector(31 downto 0);
-- error counter inputs
reg1_cen_i : in std_logic;
reg1_sbu_i : in std_logic;
reg1_dbu_i : in std_logic;
reg2_cen_i : in std_logic;
reg2_sbu_i : in std_logic;
reg2_dbu_i : in std_logic;
pc_cen_i : in std_logic;
pc_sbu_i : in std_logic;
pc_dbu_i : in std_logic;
dmem_cen_i : in std_logic;
dmem_sbu_i : in std_logic;
dmem_dbu_i : in std_logic;
control_cen_i : in std_logic;
control_err_i : in std_logic;
alu_cen_i : in std_logic;
alu_err_i : in std_logic;
-- hardening configuration outputs
hard_pc_o : out std_logic;
hard_regfile_o : out std_logic;
hard_dmem_o : out std_logic;
hard_control_o : out std_logic;
hard_alu_o : out std_logic;
-- reset cause input
poweron_rstn_i : in std_logic;
wdt_rstn_i : in std_logic
);
end entity;
architecture arch of csr is
-- USER: Counter/Timers
constant CYCLE_ADDR : std_logic_vector(11 downto 0) := x"C00";
constant TIME_ADDR : std_logic_vector(11 downto 0) := x"C01";
constant INSTRET_ADDR : std_logic_vector(11 downto 0) := x"C02";
constant CYCLEH_ADDR : std_logic_vector(11 downto 0) := x"C80";
constant TIMEH_ADDR : std_logic_vector(11 downto 0) := x"C81";
constant INSTRETH_ADDR : std_logic_vector(11 downto 0) := x"C82";
-- USER: trap handling
constant USCRATCH_ADDR : std_logic_vector(11 downto 0) := x"040";
constant UEPC_ADDR : std_logic_vector(11 downto 0) := x"041";
constant UCAUSE_ADDR : std_logic_vector(11 downto 0) := x"042";
constant UTVAL_ADDR : std_logic_vector(11 downto 0) := x"043";
constant UIP_ADDR : std_logic_vector(11 downto 0) := x"044";
-- MACHINE: custom error counter registers
constant REG1_SBU_ADDR : std_logic_vector(11 downto 0) := x"7C0";
constant REG1_DBU_ADDR : std_logic_vector(11 downto 0) := x"7C1";
constant REG2_SBU_ADDR : std_logic_vector(11 downto 0) := x"7C2";
constant REG2_DBU_ADDR : std_logic_vector(11 downto 0) := x"7C3";
constant PC_SBU_ADDR : std_logic_vector(11 downto 0) := x"7C4";
constant PC_DBU_ADDR : std_logic_vector(11 downto 0) := x"7C5";
constant DMEM_SBU_ADDR : std_logic_vector(11 downto 0) := x"7C6";
constant DMEM_DBU_ADDR : std_logic_vector(11 downto 0) := x"7C7";
constant CONTROL_ERR_ADDR : std_logic_vector(11 downto 0) := x"7C8";
constant ALU_ERR_ADDR : std_logic_vector(11 downto 0) := x"7C9";
-- MACHINE: hardening configuration
constant HARDEN_CONF_ADDR : std_logic_vector(11 downto 0) := x"BC0";
-- MACHINE: information
constant MVENDORID_ADDR : std_logic_vector(11 downto 0) := x"F11";
constant MARCHID_ADDR : std_logic_vector(11 downto 0) := x"F12";
constant MIMPID_ADDR : std_logic_vector(11 downto 0) := x"F13";
constant MHARTID_ADDR : std_logic_vector(11 downto 0) := x"F14";
-- MACHINE: reset cause
constant RSTCAUSE_ADDR : std_logic_vector(11 downto 0) := x"FC0";
-- Registers from unprivileged specification -- except float CSR
signal cycle_r : std_logic_vector(31 downto 0); -- read by RDCYCLE
signal time_r : std_logic_vector(31 downto 0); -- read by RDTIME
signal instret_r : std_logic_vector(31 downto 0); -- read by RDINSTRET
signal cycleh_r : std_logic_vector(31 downto 0); -- read by RDCYCLEH
signal timeh_r : std_logic_vector(31 downto 0); -- read by RDTIMEH
signal instreth_r : std_logic_vector(31 downto 0); -- read by RDINSTRETH
-- Registers for trap handling
signal uscratch_r : std_logic_vector(31 downto 0); --at 0x040
signal uepc_r : std_logic_vector(31 downto 0); --at 0x041
signal ucause_r : std_logic_vector(31 downto 0); --at 0x042
signal utval_r : std_logic_vector(31 downto 0); --at 0x043
signal uip_r : std_logic_vector(31 downto 0); --at 0x044
-- Registers for error counting
signal reg1_sbu_r : std_logic_vector(31 downto 0); -- at 0x7C0
signal reg1_dbu_r : std_logic_vector(31 downto 0); -- at 0x7C1
signal reg2_sbu_r : std_logic_vector(31 downto 0); -- at 0x7C2
signal reg2_dbu_r : std_logic_vector(31 downto 0); -- at 0x7C3
signal pc_sbu_r : std_logic_vector(31 downto 0); -- at 0x7C4
signal pc_dbu_r : std_logic_vector(31 downto 0); -- at 0x7C5
signal dmem_sbu_r : std_logic_vector(31 downto 0); -- at 0x7C6
signal dmem_dbu_r : std_logic_vector(31 downto 0); -- at 0x7C7
signal control_err_r : std_logic_vector(31 downto 0); -- at 0x7C8
signal alu_err_r : std_logic_vector(31 downto 0); -- at 0x7C9
-- Register for hardening flags
signal harden_conf_r : std_logic_vector(31 downto 0); -- at 0xBC0
-- Registers for information registers
signal mvendorid_r : std_logic_vector(31 downto 0);
signal marchid_r : std_logic_vector(31 downto 0);
signal mimpid_r : std_logic_vector(31 downto 0);
signal mhartid_r : std_logic_vector(31 downto 0);
-- Register for reset cause
signal rstcause_r : std_logic_vector(31 downto 0);
-- write and read signals
signal wdata_w : std_logic_vector(31 downto 0);
signal rdata_w : std_logic_vector(31 downto 0);
-- auxiliar signals
signal mask_w : std_logic_vector(31 downto 0);
signal cleared_data_w : std_logic_vector(31 downto 0);
signal setted_data_w : std_logic_vector(31 downto 0);
signal maskop_res_w : std_logic_vector(31 downto 0);
begin
rdata_w <= cycle_r when addr_i = CYCLE_ADDR else
time_r when addr_i = TIME_ADDR else
instret_r when addr_i = INSTRET_ADDR else
cycleh_r when addr_i = CYCLEH_ADDR else
timeh_r when addr_i = TIMEH_ADDR else
instreth_r when addr_i = INSTRETH_ADDR else
-- USER TRAP
uscratch_r when addr_i = USCRATCH_ADDR else
uepc_r when addr_i = UEPC_ADDR else
ucause_r when addr_i = UCAUSE_ADDR else
utval_r when addr_i = UTVAL_ADDR else
uip_r when addr_i = UIP_ADDR else
-- MACHINE INFORMATION
mvendorid_r when addr_i = MVENDORID_ADDR else
marchid_r when addr_i = MARCHID_ADDR else
mimpid_r when addr_i = MIMPID_ADDR else
mhartid_r when addr_i = MHARTID_ADDR else
-- MACHINE HARDENING CONFIGURATION
harden_conf_r when addr_i = HARDEN_CONF_ADDR else
-- MACHINE RSTCAUSE
rstcause_r when addr_i = RSTCAUSE_ADDR else
-- CUSTOM ERROR
reg1_sbu_r when addr_i = REG1_SBU_ADDR else
reg1_dbu_r when addr_i = REG1_DBU_ADDR else
reg2_sbu_r when addr_i = REG2_SBU_ADDR else
reg2_dbu_r when addr_i = REG2_DBU_ADDR else
pc_sbu_r when addr_i = PC_SBU_ADDR else
pc_dbu_r when addr_i = PC_DBU_ADDR else
dmem_sbu_r when addr_i = DMEM_SBU_ADDR else
dmem_dbu_r when addr_i = DMEM_DBU_ADDR else
control_err_r when addr_i = CONTROL_ERR_ADDR else
alu_err_r when addr_i = ALU_ERR_ADDR else
x"deadbeef";
data_o <= rdata_w;
-- define data to be written
mask_w <= ((31 downto 5 => '0') & imm_data_i) when source_imm_i = '1' else rs1_data_i;
cleared_data_w <= rdata_w and (not mask_w);
setted_data_w <= rdata_w or mask_w;
maskop_res_w <= cleared_data_w when csr_clearop_i = '1' else setted_data_w;
-- select data that will be written
wdata_w <= maskop_res_w when csr_maskop_i = '1' else rs1_data_i;
--------------------------------------------------------------------------------------
--------------------------------------- CSRs -----------------------------------------
--------------------------------------------------------------------------------------
p_CYCLE_COUNT : process(clk_i, rstn_i)
begin
if rstn_i = '0' then
cycle_r <= (others => '0');
cycleh_r <= (others => '0');
elsif rising_edge(clk_i) then
-- increment cycle
cycle_r <= std_logic_vector(unsigned(cycle_r) + 1);
-- in case of cycle_r overflow, increase cycleh_r
if cycle_r = x"FFFFFFFF" then
cycleh_r <= std_logic_vector(unsigned(cycleh_r) + 1);
end if;
end if;
end process;
p_TIME_COUNT : process(clk_i, rstn_i)
begin
if rstn_i = '0' then
time_r <= (others => '0');
timeh_r <= (others => '0');
elsif rising_edge(clk_i) then
-- increment time
time_r <= std_logic_vector(unsigned(time_r) + 1);
-- in case of time_r overflow, increase timeh_r
if time_r = x"FFFFFFFF" then
timeh_r <= std_logic_vector(unsigned(timeh_r) + 1);
end if;
end if;
end process;
p_TRAP_REGISTERS : process(clk_i)
begin
if rising_edge(clk_i) then
if trap_i = '1' then
uscratch_r <= uscratch_i;
uepc_r <= uepc_i;
ucause_r <= ucause_i;
utval_r <= utval_i;
uip_r <= uip_i;
end if;
end if;
end process;
-- information registers
mvendorid_r <= x"CAFECAFE";
marchid_r <= x"000000CA";
mimpid_r(31 downto 6) <= (others => '0');
mimpid_r( 3 downto 2) <= (others => '0');
mimpid_r(0) <= '1' when HAMMING_PC else '0';
mimpid_r(1) <= '1' when HAMMING_REGFILE else '0';
mimpid_r(4) <= '1' when TMR_CONTROL else '0';
mimpid_r(5) <= '1' when TMR_ALU else '0';
mhartid_r <= x"00000000";
p_RSTCAUSE : process(poweron_rstn_i, wdt_rstn_i)
begin
if poweron_rstn_i = '0' then
rstcause_r <= x"00000001";
elsif wdt_rstn_i = '0' then
rstcause_r <= x"00000002";
end if;
end process;
p_HARDENING : process(clk_i)
begin
if rising_edge(clk_i) then
if wren_i = '1' and addr_i = HARDEN_CONF_ADDR then
harden_conf_r <= wdata_w;
end if;
end if;
end process;
-- Hamming
hard_pc_o <= harden_conf_r(0);
hard_regfile_o <= harden_conf_r(1);
hard_dmem_o <= harden_conf_r(2);
-- TMR
hard_control_o <= harden_conf_r(4);
hard_alu_o <= harden_conf_r(5);
p_ERROR_COUNT : process(clk_i)
begin
if rising_edge(clk_i) then
-- Register file upsets
if wren_i = '1' and addr_i = REG1_SBU_ADDR then
reg1_sbu_r <= wdata_w;
elsif reg1_cen_i = '1' and reg1_sbu_i = '1' then
reg1_sbu_r <= std_logic_vector(unsigned(reg1_sbu_r)+1);
end if;
if wren_i = '1' and addr_i = REG1_DBU_ADDR then
reg1_dbu_r <= wdata_w;
elsif reg1_cen_i = '1' and reg1_dbu_i = '1' then
reg1_dbu_r <= std_logic_vector(unsigned(reg1_dbu_r)+1);
end if;
-- Register file upsets
if wren_i = '1' and addr_i = REG2_SBU_ADDR then
reg2_sbu_r <= wdata_w;
elsif reg2_cen_i = '1' and reg2_sbu_i = '1' then
reg2_sbu_r <= std_logic_vector(unsigned(reg2_sbu_r)+1);
end if;
if wren_i = '1' and addr_i = REG2_DBU_ADDR then
reg2_dbu_r <= wdata_w;
elsif reg2_cen_i = '1' and reg2_dbu_i = '1' then
reg2_dbu_r <= std_logic_vector(unsigned(reg2_dbu_r)+1);
end if;
-- PC upsets
if wren_i = '1' and addr_i = PC_SBU_ADDR then
pc_sbu_r <= wdata_w;
elsif pc_cen_i = '1' and pc_sbu_i = '1' then
pc_sbu_r <= std_logic_vector(unsigned(pc_sbu_r)+1);
end if;
if wren_i = '1' and addr_i = PC_DBU_ADDR then
pc_dbu_r <= wdata_w;
elsif pc_cen_i = '1' and pc_dbu_i = '1' then
pc_dbu_r <= std_logic_vector(unsigned(pc_dbu_r)+1);
end if;
-- Data memory upsets
if wren_i = '1' and addr_i = DMEM_SBU_ADDR then
dmem_sbu_r <= wdata_w;
elsif dmem_cen_i = '1' and dmem_sbu_i = '1' then
dmem_sbu_r <= std_logic_vector(unsigned(dmem_sbu_r)+1);
end if;
if wren_i = '1' and addr_i = DMEM_DBU_ADDR then
dmem_dbu_r <= wdata_w;
elsif dmem_cen_i = '1' and dmem_dbu_i = '1' then
dmem_dbu_r <= std_logic_vector(unsigned(dmem_dbu_r)+1);
end if;
-- CONTROL errors
if wren_i = '1' and addr_i = CONTROL_ERR_ADDR then
control_err_r <= wdata_w;
elsif control_cen_i = '1' and control_err_i = '1' then
control_err_r <= std_logic_vector(unsigned(control_err_r)+1);
end if;
-- ALU errors
if wren_i = '1' and addr_i = ALU_ERR_ADDR then
alu_err_r <= wdata_w;
elsif alu_cen_i = '1' and alu_err_i = '1' then
alu_err_r <= std_logic_vector(unsigned(alu_err_r)+1);
end if;
end if;
end process;
end architecture;

View file

@ -0,0 +1,80 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_misc.all;
library work;
use work.harv_pkg.all;
entity alu_tmr is
port (
-- input ports
data1_i : in std_logic_vector(31 downto 0);
data2_i : in std_logic_vector(31 downto 0);
operation_i : in std_logic_vector(ALUOP_SIZE-1 downto 0);
correct_error_i : in std_logic;
-- output ports
error_o : out std_logic;
zero_o : out std_logic;
data_o : out std_logic_vector(31 downto 0)
);
end entity;
architecture arch of alu_tmr is
type tmr_std_logic_t is array(2 downto 0) of std_logic;
signal zero_w : tmr_std_logic_t;
signal corr_zero_w : std_logic;
signal error_zero_w : std_logic;
type tmr_data_t is array(2 downto 0) of std_logic_vector(31 downto 0);
signal data_w : tmr_data_t;
signal corr_data_w : std_logic_vector(31 downto 0);
signal error_data_w : std_logic;
begin
gen_TMR : for i in 2 downto 0 generate
-- Xilinx attributes to prevent optimization of TMR
attribute DONT_TOUCH : string;
attribute DONT_TOUCH of alu_i : label is "TRUE";
-- Synplify attributes to prevent optimization of TMR
attribute syn_radhardlevel : string;
attribute syn_keep : boolean;
attribute syn_safe_case : boolean;
attribute syn_noprune : boolean;
attribute syn_radhardlevel of alu_i : label is "tmr";
attribute syn_keep of alu_i : label is TRUE;
attribute syn_safe_case of alu_i : label is TRUE;
attribute syn_noprune of alu_i : label is TRUE;
begin
alu_i : alu
port map (
data1_i => data1_i,
data2_i => data2_i,
operation_i => operation_i,
zero_o => zero_w(i),
data_o => data_w(i)
);
end generate;
corr_zero_w <= (zero_w(2) and zero_w(1)) or
(zero_w(2) and zero_w(0)) or
(zero_w(1) and zero_w(0));
corr_data_w <= (data_w(2) and data_w(1)) or
(data_w(2) and data_w(0)) or
(data_w(1) and data_w(0));
error_zero_w <= (zero_w(2) xor zero_w(1)) or
(zero_w(2) xor zero_w(0)) or
(zero_w(1) xor zero_w(0));
error_data_w <= or_reduce((data_w(2) xor data_w(1)) or
(data_w(2) xor data_w(0)) or
(data_w(1) xor data_w(0)));
error_o <= error_zero_w or error_data_w;
zero_o <= corr_zero_w when correct_error_i = '1' else zero_w(0);
data_o <= corr_data_w when correct_error_i = '1' else data_w(0);
end architecture;

View file

@ -0,0 +1,299 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_misc.all;
library work;
use work.harv_pkg.all;
entity control_tmr is
port (
-- input ports
-- processor status
imem_gnt_i : in std_logic;
imem_err_i : in std_logic;
dmem_gnt_i : in std_logic;
dmem_outofrange_i : in std_logic;
dmem_sbu_i : in std_logic;
dmem_dbu_i : in std_logic;
-- instruction decode
opcode_i : in std_logic_vector(6 downto 0);
funct3_i : in std_logic_vector(2 downto 0);
funct7_i : in std_logic_vector(6 downto 0);
funct12_i : in std_logic_vector(11 downto 0);
-- hardening
correct_error_i : in std_logic;
-- sync
rstn_i : in std_logic;
clk_i : in std_logic;
start_i : in std_logic;
-- output ports
-- processor status
imem_req_o : out std_logic;
dmem_req_o : out std_logic;
update_pc_o : out std_logic;
trap_o : out std_logic;
-- hardening
error_o : out std_logic;
-- ALU operations
aluop_o : out std_logic_vector(ALUOP_SIZE-1 downto 0);
alusrc_imm_o : out std_logic;
-- immediate selector
imm_shamt_o : out std_logic;
imm_up_o : out std_logic;
-- register bank
regwr_o : out std_logic;
-- control transfer
inv_branch_o : out std_logic;
branch_o : out std_logic;
jump_o : out std_logic;
jalr_o : out std_logic;
ecall_o : out std_logic;
-- mem access
memrd_o : out std_logic;
memwr_o : out std_logic;
byte_en_o : out std_logic_vector(1 downto 0);
mem_usgn_o : out std_logic; -- unsigned data
-- U type
load_upimm_o : out std_logic;
auipc_o : out std_logic;
-- csr control
csr_enable_o : out std_logic;
csr_source_imm_o : out std_logic;
csr_maskop_o : out std_logic;
csr_clearop_o : out std_logic
);
end entity;
architecture arch of control_tmr is
type tmr_std_logic_t is array(2 downto 0) of std_logic;
signal imem_req_w : tmr_std_logic_t;
signal dmem_req_w : tmr_std_logic_t;
signal update_pc_w : tmr_std_logic_t;
signal trap_w : tmr_std_logic_t;
signal alusrc_imm_w : tmr_std_logic_t;
signal imm_shamt_w : tmr_std_logic_t;
signal imm_up_w : tmr_std_logic_t;
signal regwr_w : tmr_std_logic_t;
signal inv_branch_w : tmr_std_logic_t;
signal branch_w : tmr_std_logic_t;
signal jump_w : tmr_std_logic_t;
signal jalr_w : tmr_std_logic_t;
signal ecall_w : tmr_std_logic_t;
signal memrd_w : tmr_std_logic_t;
signal memwr_w : tmr_std_logic_t;
signal mem_usgn_w : tmr_std_logic_t;
signal load_upimm_w : tmr_std_logic_t;
signal auipc_w : tmr_std_logic_t;
signal csr_enable_w : tmr_std_logic_t;
signal csr_source_imm_w : tmr_std_logic_t;
signal csr_maskop_w : tmr_std_logic_t;
signal csr_clearop_w : tmr_std_logic_t;
signal corr_imem_req_w : std_logic;
signal corr_dmem_req_w : std_logic;
signal corr_update_pc_w : std_logic;
signal corr_trap_w : std_logic;
signal corr_alusrc_imm_w : std_logic;
signal corr_imm_shamt_w : std_logic;
signal corr_imm_up_w : std_logic;
signal corr_regwr_w : std_logic;
signal corr_inv_branch_w : std_logic;
signal corr_branch_w : std_logic;
signal corr_jump_w : std_logic;
signal corr_jalr_w : std_logic;
signal corr_ecall_w : std_logic;
signal corr_memrd_w : std_logic;
signal corr_memwr_w : std_logic;
signal corr_mem_usgn_w : std_logic;
signal corr_load_upimm_w : std_logic;
signal corr_auipc_w : std_logic;
signal corr_csr_enable_w : std_logic;
signal corr_csr_source_imm_w : std_logic;
signal corr_csr_maskop_w : std_logic;
signal corr_csr_clearop_w : std_logic;
signal error_imem_req_w : std_logic;
signal error_dmem_req_w : std_logic;
signal error_update_pc_w : std_logic;
signal error_trap_w : std_logic;
signal error_alusrc_imm_w : std_logic;
signal error_imm_shamt_w : std_logic;
signal error_imm_up_w : std_logic;
signal error_regwr_w : std_logic;
signal error_inv_branch_w : std_logic;
signal error_branch_w : std_logic;
signal error_jump_w : std_logic;
signal error_jalr_w : std_logic;
signal error_ecall_w : std_logic;
signal error_memrd_w : std_logic;
signal error_memwr_w : std_logic;
signal error_mem_usgn_w : std_logic;
signal error_load_upimm_w : std_logic;
signal error_auipc_w : std_logic;
signal error_csr_enable_w : std_logic;
signal error_csr_source_imm_w : std_logic;
signal error_csr_maskop_w : std_logic;
signal error_csr_clearop_w : std_logic;
type tmr_alu_operations_t is array(2 downto 0) of std_logic_vector(ALUOP_SIZE-1 downto 0);
signal aluop_w : tmr_alu_operations_t;
signal corr_aluop_w : std_logic_vector(ALUOP_SIZE-1 downto 0);
signal error_aluop_w : std_logic;
type tmr_std_logic_2_t is array(2 downto 0) of std_logic_vector(1 downto 0);
signal byte_en_w : tmr_std_logic_2_t;
signal corr_byte_en_w : std_logic_vector(1 downto 0);
signal error_byte_en_w : std_logic;
begin
gen_TMR : for i in 2 downto 0 generate
-- Xilinx attributes to prevent optimization of TMR
attribute DONT_TOUCH : string;
attribute DONT_TOUCH of control_i : label is "TRUE";
-- Synplify attributes to prevent optimization of TMR
attribute syn_radhardlevel : string;
attribute syn_keep : boolean;
attribute syn_safe_case : boolean;
attribute syn_noprune : boolean;
attribute syn_radhardlevel of control_i : label is "tmr";
attribute syn_keep of control_i : label is TRUE;
attribute syn_safe_case of control_i : label is TRUE;
attribute syn_noprune of control_i : label is TRUE;
begin
control_i : control
port map (
imem_gnt_i => imem_gnt_i,
imem_err_i => imem_err_i,
dmem_gnt_i => dmem_gnt_i,
dmem_outofrange_i => dmem_outofrange_i,
dmem_sbu_i => dmem_sbu_i,
dmem_dbu_i => dmem_dbu_i,
opcode_i => opcode_i,
funct3_i => funct3_i,
funct7_i => funct7_i,
funct12_i => funct12_i,
rstn_i => rstn_i,
clk_i => clk_i,
start_i => start_i,
imem_req_o => imem_req_w(i),
dmem_req_o => dmem_req_w(i),
update_pc_o => update_pc_w(i),
trap_o => trap_w(i),
aluop_o => aluop_w(i),
alusrc_imm_o => alusrc_imm_w(i),
imm_shamt_o => imm_shamt_w(i),
imm_up_o => imm_up_w(i),
regwr_o => regwr_w(i),
inv_branch_o => inv_branch_w(i),
branch_o => branch_w(i),
jump_o => jump_w(i),
jalr_o => jalr_w(i),
ecall_o => ecall_w(i),
memrd_o => memrd_w(i),
memwr_o => memwr_w(i),
byte_en_o => byte_en_w(i),
mem_usgn_o => mem_usgn_w(i),
load_upimm_o => load_upimm_w(i),
auipc_o => auipc_w(i),
csr_enable_o => csr_enable_w(i),
csr_source_imm_o => csr_source_imm_w(i),
csr_maskop_o => csr_maskop_w(i),
csr_clearop_o => csr_clearop_w(i)
);
end generate;
corr_imem_req_w <= ( imem_req_w(2) and imem_req_w(1)) or ( imem_req_w(2) and imem_req_w(0)) or ( imem_req_w(1) and imem_req_w(0));
corr_dmem_req_w <= ( dmem_req_w(2) and dmem_req_w(1)) or ( dmem_req_w(2) and dmem_req_w(0)) or ( dmem_req_w(1) and dmem_req_w(0));
corr_update_pc_w <= ( update_pc_w(2) and update_pc_w(1)) or ( update_pc_w(2) and update_pc_w(0)) or ( update_pc_w(1) and update_pc_w(0));
corr_trap_w <= ( trap_w(2) and trap_w(1)) or ( trap_w(2) and trap_w(0)) or ( trap_w(1) and trap_w(0));
corr_aluop_w <= ( aluop_w(2) and aluop_w(1)) or ( aluop_w(2) and aluop_w(0)) or ( aluop_w(1) and aluop_w(0));
corr_alusrc_imm_w <= ( alusrc_imm_w(2) and alusrc_imm_w(1)) or ( alusrc_imm_w(2) and alusrc_imm_w(0)) or ( alusrc_imm_w(1) and alusrc_imm_w(0));
corr_imm_shamt_w <= ( imm_shamt_w(2) and imm_shamt_w(1)) or ( imm_shamt_w(2) and imm_shamt_w(0)) or ( imm_shamt_w(1) and imm_shamt_w(0));
corr_imm_up_w <= ( imm_up_w(2) and imm_up_w(1)) or ( imm_up_w(2) and imm_up_w(0)) or ( imm_up_w(1) and imm_up_w(0));
corr_regwr_w <= ( regwr_w(2) and regwr_w(1)) or ( regwr_w(2) and regwr_w(0)) or ( regwr_w(1) and regwr_w(0));
corr_inv_branch_w <= ( inv_branch_w(2) and inv_branch_w(1)) or ( inv_branch_w(2) and inv_branch_w(0)) or ( inv_branch_w(1) and inv_branch_w(0));
corr_branch_w <= ( branch_w(2) and branch_w(1)) or ( branch_w(2) and branch_w(0)) or ( branch_w(1) and branch_w(0));
corr_jump_w <= ( jump_w(2) and jump_w(1)) or ( jump_w(2) and jump_w(0)) or ( jump_w(1) and jump_w(0));
corr_jalr_w <= ( jalr_w(2) and jalr_w(1)) or ( jalr_w(2) and jalr_w(0)) or ( jalr_w(1) and jalr_w(0));
corr_ecall_w <= ( ecall_w(2) and ecall_w(1)) or ( ecall_w(2) and ecall_w(0)) or ( ecall_w(1) and ecall_w(0));
corr_memrd_w <= ( memrd_w(2) and memrd_w(1)) or ( memrd_w(2) and memrd_w(0)) or ( memrd_w(1) and memrd_w(0));
corr_memwr_w <= ( memwr_w(2) and memwr_w(1)) or ( memwr_w(2) and memwr_w(0)) or ( memwr_w(1) and memwr_w(0));
corr_byte_en_w <= ( byte_en_w(2) and byte_en_w(1)) or ( byte_en_w(2) and byte_en_w(0)) or ( byte_en_w(1) and byte_en_w(0));
corr_mem_usgn_w <= ( mem_usgn_w(2) and mem_usgn_w(1)) or ( mem_usgn_w(2) and mem_usgn_w(0)) or ( mem_usgn_w(1) and mem_usgn_w(0));
corr_load_upimm_w <= ( load_upimm_w(2) and load_upimm_w(1)) or ( load_upimm_w(2) and load_upimm_w(0)) or ( load_upimm_w(1) and load_upimm_w(0));
corr_auipc_w <= ( auipc_w(2) and auipc_w(1)) or ( auipc_w(2) and auipc_w(0)) or ( auipc_w(1) and auipc_w(0));
corr_csr_enable_w <= ( csr_enable_w(2) and csr_enable_w(1)) or ( csr_enable_w(2) and csr_enable_w(0)) or ( csr_enable_w(1) and csr_enable_w(0));
corr_csr_source_imm_w <= ( csr_source_imm_w(2) and csr_source_imm_w(1)) or ( csr_source_imm_w(2) and csr_source_imm_w(0)) or ( csr_source_imm_w(1) and csr_source_imm_w(0));
corr_csr_maskop_w <= ( csr_maskop_w(2) and csr_maskop_w(1)) or ( csr_maskop_w(2) and csr_maskop_w(0)) or ( csr_maskop_w(1) and csr_maskop_w(0));
corr_csr_clearop_w <= ( csr_clearop_w(2) and csr_clearop_w(1)) or ( csr_clearop_w(2) and csr_clearop_w(0)) or ( csr_clearop_w(1) and csr_clearop_w(0));
error_imem_req_w <= ( imem_req_w(2) xor imem_req_w(1)) or ( imem_req_w(2) xor imem_req_w(0)) or ( imem_req_w(1) xor imem_req_w(0));
error_dmem_req_w <= ( dmem_req_w(2) xor dmem_req_w(1)) or ( dmem_req_w(2) xor dmem_req_w(0)) or ( dmem_req_w(1) xor dmem_req_w(0));
error_update_pc_w <= ( update_pc_w(2) xor update_pc_w(1)) or ( update_pc_w(2) xor update_pc_w(0)) or ( update_pc_w(1) xor update_pc_w(0));
error_trap_w <= ( trap_w(2) xor trap_w(1)) or ( trap_w(2) xor trap_w(0)) or ( trap_w(1) xor trap_w(0));
error_aluop_w <= or_reduce(( aluop_w(2) xor aluop_w(1)) or ( aluop_w(2) xor aluop_w(0)) or ( aluop_w(1) xor aluop_w(0)));
error_alusrc_imm_w <= ( alusrc_imm_w(2) xor alusrc_imm_w(1)) or ( alusrc_imm_w(2) xor alusrc_imm_w(0)) or ( alusrc_imm_w(1) xor alusrc_imm_w(0));
error_imm_shamt_w <= ( imm_shamt_w(2) xor imm_shamt_w(1)) or ( imm_shamt_w(2) xor imm_shamt_w(0)) or ( imm_shamt_w(1) xor imm_shamt_w(0));
error_imm_up_w <= ( imm_up_w(2) xor imm_up_w(1)) or ( imm_up_w(2) xor imm_up_w(0)) or ( imm_up_w(1) xor imm_up_w(0));
error_regwr_w <= ( regwr_w(2) xor regwr_w(1)) or ( regwr_w(2) xor regwr_w(0)) or ( regwr_w(1) xor regwr_w(0));
error_inv_branch_w <= ( inv_branch_w(2) xor inv_branch_w(1)) or ( inv_branch_w(2) xor inv_branch_w(0)) or ( inv_branch_w(1) xor inv_branch_w(0));
error_branch_w <= ( branch_w(2) xor branch_w(1)) or ( branch_w(2) xor branch_w(0)) or ( branch_w(1) xor branch_w(0));
error_jump_w <= ( jump_w(2) xor jump_w(1)) or ( jump_w(2) xor jump_w(0)) or ( jump_w(1) xor jump_w(0));
error_jalr_w <= ( jalr_w(2) xor jalr_w(1)) or ( jalr_w(2) xor jalr_w(0)) or ( jalr_w(1) xor jalr_w(0));
error_ecall_w <= ( ecall_w(2) xor ecall_w(1)) or ( ecall_w(2) xor ecall_w(0)) or ( ecall_w(1) xor ecall_w(0));
error_memrd_w <= ( memrd_w(2) xor memrd_w(1)) or ( memrd_w(2) xor memrd_w(0)) or ( memrd_w(1) xor memrd_w(0));
error_memwr_w <= ( memwr_w(2) xor memwr_w(1)) or ( memwr_w(2) xor memwr_w(0)) or ( memwr_w(1) xor memwr_w(0));
error_byte_en_w <= or_reduce(( byte_en_w(2) xor byte_en_w(1)) or ( byte_en_w(2) xor byte_en_w(0)) or ( byte_en_w(1) xor byte_en_w(0)));
error_mem_usgn_w <= ( mem_usgn_w(2) xor mem_usgn_w(1)) or ( mem_usgn_w(2) xor mem_usgn_w(0)) or ( mem_usgn_w(1) xor mem_usgn_w(0));
error_load_upimm_w <= ( load_upimm_w(2) xor load_upimm_w(1)) or ( load_upimm_w(2) xor load_upimm_w(0)) or ( load_upimm_w(1) xor load_upimm_w(0));
error_auipc_w <= ( auipc_w(2) xor auipc_w(1)) or ( auipc_w(2) xor auipc_w(0)) or ( auipc_w(1) xor auipc_w(0));
error_csr_enable_w <= ( csr_enable_w(2) xor csr_enable_w(1)) or ( csr_enable_w(2) xor csr_enable_w(0)) or ( csr_enable_w(1) xor csr_enable_w(0));
error_csr_source_imm_w <= ( csr_source_imm_w(2) xor csr_source_imm_w(1)) or ( csr_source_imm_w(2) xor csr_source_imm_w(0)) or ( csr_source_imm_w(1) xor csr_source_imm_w(0));
error_csr_maskop_w <= ( csr_maskop_w(2) xor csr_maskop_w(1)) or ( csr_maskop_w(2) xor csr_maskop_w(0)) or ( csr_maskop_w(1) xor csr_maskop_w(0));
error_csr_clearop_w <= ( csr_clearop_w(2) xor csr_clearop_w(1)) or ( csr_clearop_w(2) xor csr_clearop_w(0)) or ( csr_clearop_w(1) xor csr_clearop_w(0));
error_o <= error_imem_req_w or error_dmem_req_w or error_update_pc_w or
error_trap_w or error_aluop_w or error_alusrc_imm_w or
error_imm_shamt_w or error_imm_up_w or error_regwr_w or
error_inv_branch_w or error_branch_w or error_jump_w or
error_jalr_w or error_ecall_w or error_memrd_w or
error_memwr_w or error_byte_en_w or error_mem_usgn_w or
error_load_upimm_w or error_auipc_w or error_csr_enable_w or
error_csr_source_imm_w or error_csr_maskop_w or error_csr_clearop_w;
imem_req_o <= corr_imem_req_w when correct_error_i = '1' else imem_req_w (0);
dmem_req_o <= corr_dmem_req_w when correct_error_i = '1' else dmem_req_w (0);
update_pc_o <= corr_update_pc_w when correct_error_i = '1' else update_pc_w (0);
trap_o <= corr_trap_w when correct_error_i = '1' else trap_w (0);
aluop_o <= corr_aluop_w when correct_error_i = '1' else aluop_w (0);
alusrc_imm_o <= corr_alusrc_imm_w when correct_error_i = '1' else alusrc_imm_w (0);
imm_shamt_o <= corr_imm_shamt_w when correct_error_i = '1' else imm_shamt_w (0);
imm_up_o <= corr_imm_up_w when correct_error_i = '1' else imm_up_w (0);
regwr_o <= corr_regwr_w when correct_error_i = '1' else regwr_w (0);
inv_branch_o <= corr_inv_branch_w when correct_error_i = '1' else inv_branch_w (0);
branch_o <= corr_branch_w when correct_error_i = '1' else branch_w (0);
jump_o <= corr_jump_w when correct_error_i = '1' else jump_w (0);
jalr_o <= corr_jalr_w when correct_error_i = '1' else jalr_w (0);
ecall_o <= corr_ecall_w when correct_error_i = '1' else ecall_w (0);
memrd_o <= corr_memrd_w when correct_error_i = '1' else memrd_w (0);
memwr_o <= corr_memwr_w when correct_error_i = '1' else memwr_w (0);
byte_en_o <= corr_byte_en_w when correct_error_i = '1' else byte_en_w (0);
mem_usgn_o <= corr_mem_usgn_w when correct_error_i = '1' else mem_usgn_w (0);
load_upimm_o <= corr_load_upimm_w when correct_error_i = '1' else load_upimm_w (0);
auipc_o <= corr_auipc_w when correct_error_i = '1' else auipc_w (0);
csr_enable_o <= corr_csr_enable_w when correct_error_i = '1' else csr_enable_w (0);
csr_source_imm_o <= corr_csr_source_imm_w when correct_error_i = '1' else csr_source_imm_w(0);
csr_maskop_o <= corr_csr_maskop_w when correct_error_i = '1' else csr_maskop_w (0);
csr_clearop_o <= corr_csr_clearop_w when correct_error_i = '1' else csr_clearop_w (0);
end architecture;

View file

@ -0,0 +1,80 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_misc.all;
library work;
use work.hamming_pkg.all;
entity hamming_decoder is
generic (
DATA_SIZE : integer := 32; -- 64(7), 32(6), 16(5), 8(4), 4(3)
DETECT_DOUBLE : boolean
);
port (
encoded_i : in std_logic_vector(DATA_SIZE+get_ecc_size(DATA_SIZE, DETECT_DOUBLE)-1 downto 0);
correct_error_i : in std_logic;
single_err_o : out std_logic;
double_err_o : out std_logic;
data_o : out std_logic_vector(DATA_SIZE-1 downto 0)
);
end entity;
architecture arch of hamming_decoder is
constant HAMM_PARITY_SIZE : integer := get_ecc_size(DATA_SIZE, FALSE);
constant TOTAL_PARITY_SIZE : integer := get_ecc_size(DATA_SIZE, DETECT_DOUBLE);
signal parity_data_w : std_logic_vector(HAMM_PARITY_SIZE-1 downto 0);
signal parity_diff_w : std_logic_vector(HAMM_PARITY_SIZE-1 downto 0);
signal corr_mask_w : std_logic_vector(DATA_SIZE-1 downto 0);
signal corr_data_w : std_logic_vector(DATA_SIZE-1 downto 0);
signal single_err_w : std_logic;
signal double_err_w : std_logic;
begin
gen_ENCODE : for i in HAMM_PARITY_SIZE-1 downto 0 generate
constant BITS_QT : integer := get_parity_qt(DATA_SIZE, i);
signal ecc_data_w : std_logic_vector(BITS_QT-1 downto 0);
begin
gen_DATA : for j in ecc_data_w'range generate
ecc_data_w(j) <= encoded_i(PARITY_POS(i, j));
end generate;
parity_data_w(i) <= xor_reduce(ecc_data_w);
end generate;
parity_diff_w <= parity_data_w xor encoded_i(DATA_SIZE+HAMM_PARITY_SIZE-1 downto DATA_SIZE);
gen_CORRECTION_MASK : for i in corr_mask_w'range generate
corr_mask_w(i) <= nor_reduce(ERROR_BIT(i)(HAMM_PARITY_SIZE-1 downto 0) xor parity_diff_w);
end generate;
corr_data_w <= (encoded_i(DATA_SIZE-1 downto 0) xor corr_mask_w) when correct_error_i = '1' else encoded_i(DATA_SIZE-1 downto 0);
gen_DOUBLE_DETECT : if DETECT_DOUBLE generate
signal addit_parity_w : std_logic;
signal hamm_err_w : std_logic;
begin
-- calculate additional parity
addit_parity_w <= xor_reduce(encoded_i);
-- get 1 if hamming has detected an error
hamm_err_w <= or_reduce(parity_diff_w);
-- check double error
double_err_w <= (not addit_parity_w) and hamm_err_w;
-- set single error only when dont have double error
single_err_w <= hamm_err_w and not double_err_w;
end generate;
gen_NOT_DOUBLE_DETECT : if not DETECT_DOUBLE generate
-- set single error when hamming detects one
single_err_w <= or_reduce(parity_diff_w);
-- never detects two errors
double_err_w <= '0';
end generate;
-- assign error wires to output
single_err_o <= single_err_w;
double_err_o <= double_err_w;
-- output corrected data only when has corrected single error. If not, output not-modified data
data_o <= corr_data_w when single_err_w = '1' else encoded_i(DATA_SIZE-1 downto 0);
end architecture;

View file

@ -0,0 +1,45 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_misc.all;
library work;
use work.hamming_pkg.all;
entity hamming_encoder is
generic (
DATA_SIZE : integer := 32; -- 64(7), 32(6), 16(5), 8(4), 4(3)
DETECT_DOUBLE : boolean
);
port (
data_i : in std_logic_vector(DATA_SIZE-1 downto 0);
encoded_o : out std_logic_vector(DATA_SIZE+get_ecc_size(DATA_SIZE, DETECT_DOUBLE)-1 downto 0)
);
end entity;
architecture arch of hamming_encoder is
constant HAMM_PARITY_SIZE : integer := get_ecc_size(DATA_SIZE, FALSE);
constant TOTAL_PARITY_SIZE : integer := get_ecc_size(DATA_SIZE, DETECT_DOUBLE);
signal parity_data_w : std_logic_vector(TOTAL_PARITY_SIZE-1 downto 0);
signal encoded_w : std_logic_vector(DATA_SIZE+TOTAL_PARITY_SIZE-1 downto 0);
begin
gen_ENCODE : for i in HAMM_PARITY_SIZE-1 downto 0 generate
constant BITS_QT : integer := get_parity_qt(DATA_SIZE, i);
signal ecc_data_w : std_logic_vector(BITS_QT-1 downto 0);
begin
gen_DATA : for j in ecc_data_w'range generate
ecc_data_w(j) <= data_i(PARITY_POS(i, j));
end generate;
parity_data_w(i) <= xor_reduce(ecc_data_w);
end generate;
gen_ADDITIONAL_PARITY : if DETECT_DOUBLE generate
signal hamm_encoded_w : std_logic_vector(DATA_SIZE+HAMM_PARITY_SIZE-1 downto 0);
begin
hamm_encoded_w <= parity_data_w(HAMM_PARITY_SIZE-1 downto 0) & data_i;
parity_data_w(TOTAL_PARITY_SIZE-1) <= xor_reduce(hamm_encoded_w);
end generate;
encoded_w <= parity_data_w & data_i;
encoded_o <= encoded_w;
end architecture;

View file

@ -0,0 +1,129 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_misc.all;
package hamming_pkg is
-- TYPES
type parity_pos_t is array (natural range <>, natural range <>) of integer;
type err_bit_t is array(natural range <>) of std_logic_vector(6 downto 0);
-- CONSTANTS
constant PARITY_POS : parity_pos_t := (
0 => ( 0, 1, 3, 4, 6, 8, 10, 11, 13, 15, 17, 19, 21, 23, 25, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 57, 59, 61, 63),
1 => ( 0, 2, 3, 5, 6, 9, 10, 12, 13, 16, 17, 20, 21, 24, 25, 27, 28, 31, 32, 35, 36, 39, 40, 43, 44, 47, 48, 51, 52, 55, 56, 58, 59, 62, 63),
2 => ( 1, 2, 3, 7, 8, 9, 10, 14, 15, 16, 17, 22, 23, 24, 25, 29, 30, 31, 32, 37, 38, 39, 40, 45, 46, 47, 48, 53, 54, 55, 56, 60, 61, 62, 63),
3 => ( 4, 5, 6, 7, 8, 9, 10, 18, 19, 20, 21, 22, 23, 24, 25, 33, 34, 35, 36, 37, 38, 39, 40, 49, 50, 51, 52, 53, 54, 55, 56, 64, -1, -1, -1),
4 => (11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, -1, -1, -1, -1),
5 => (26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, -1, -1, -1, -1),
6 => (57, 58, 59, 60, 61, 62, 63, 64, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)
);
constant ERROR_BIT : err_bit_t := (
0 => "0000011", 1 => "0000101", 2 => "0000110", 3 => "0000111", 4 => "0001001", 5 => "0001010",
6 => "0001011", 7 => "0001100", 8 => "0001101", 9 => "0001110", 10 => "0001111", 11 => "0010001",
12 => "0010010", 13 => "0010011", 14 => "0010100", 15 => "0010101", 16 => "0010110", 17 => "0010111",
18 => "0011000", 19 => "0011001", 20 => "0011010", 21 => "0011011", 22 => "0011100", 23 => "0011101",
24 => "0011110", 25 => "0011111", 26 => "0100001", 27 => "0100010", 28 => "0100011", 29 => "0100100",
30 => "0100101", 31 => "0100110", 32 => "0100111", 33 => "0101000", 34 => "0101001", 35 => "0101010",
36 => "0101011", 37 => "0101100", 38 => "0101101", 39 => "0101110", 40 => "0101111", 41 => "0110000",
42 => "0110001", 43 => "0110010", 44 => "0110011", 45 => "0110100", 46 => "0110101", 47 => "0110110",
48 => "0110111", 49 => "0111000", 50 => "0111001", 51 => "0111010", 52 => "0111011", 53 => "0111100",
54 => "0111101", 55 => "0111110", 56 => "0111111", 57 => "1000001", 58 => "1000010", 59 => "1000011",
60 => "1000100", 61 => "1000101", 62 => "1000110", 63 => "1000111", 64 => "1001000"
);
-- FUNCTIONS -- runs only at synthesis
function get_parity_qt (data_size : in integer; pos : in integer) return integer;
function get_ecc_size (data_size : in integer; detect_double : in boolean) return integer;
function get_parity_data_result (data : in std_logic_vector; detect_double : in boolean) return std_logic_vector;
-- COMPONENTS
component hamming_encoder
generic (
DATA_SIZE : integer;
DETECT_DOUBLE : boolean
);
port (
data_i : in std_logic_vector(DATA_SIZE-1 downto 0);
encoded_o : out std_logic_vector(DATA_SIZE+get_ecc_size(DATA_SIZE, DETECT_DOUBLE)-1 downto 0)
);
end component hamming_encoder;
component hamming_decoder
generic (
DATA_SIZE : integer := 32;
DETECT_DOUBLE : boolean
);
port (
encoded_i : in std_logic_vector(DATA_SIZE+get_ecc_size(DATA_SIZE, DETECT_DOUBLE)-1 downto 0);
correct_error_i : in std_logic;
single_err_o : out std_logic;
double_err_o : out std_logic;
data_o : out std_logic_vector(DATA_SIZE-1 downto 0)
);
end component hamming_decoder;
component hamming_register
generic (
HAMMING_ENABLE : boolean;
RESET_VALUE : std_logic_vector
);
port (
correct_en_i : in std_logic;
write_en_i : in std_logic;
data_i : in std_logic_vector(31 downto 0);
rstn_i : in std_logic;
clk_i : in std_logic;
single_err_o : out std_logic;
double_err_o : out std_logic;
data_o : out std_logic_vector(31 downto 0)
);
end component hamming_register;
end package;
package body hamming_pkg is
function get_parity_qt (data_size : in integer; pos : in integer) return integer is
begin
for j in 0 to PARITY_POS'length(2)-1 loop
if PARITY_POS(pos, j) >= data_size or PARITY_POS(pos, j) = -1 then
return j;
end if;
end loop;
return PARITY_POS'length(2);
end function;
function get_ecc_size (data_size : in integer; detect_double : in boolean) return integer is
begin
if detect_double then
return 1 + get_ecc_size(data_size, FALSE);
end if;
for j in 0 to PARITY_POS'length(1)-1 loop
if data_size < PARITY_POS(j, 0) then
return j;
end if;
end loop;
return PARITY_POS'length(1);
end function;
function get_parity_data_result (data : in std_logic_vector; detect_double : in boolean) return std_logic_vector is
constant HAMM_PARITY_SIZE : integer := get_ecc_size(data'length, FALSE);
constant TOTAL_PARITY_SIZE : integer := get_ecc_size(data'length, detect_double);
variable par_data : std_logic_vector(HAMM_PARITY_SIZE-1 downto 0) := (others => '0');
begin
for i in 0 to HAMM_PARITY_SIZE-1 loop
for j in 0 to get_parity_qt(data'length, i)-1 loop
if PARITY_POS(i, j) < data'length and PARITY_POS(i, j) /= -1 then
par_data(i) := par_data(i) xor data(PARITY_POS(i, j));
end if;
end loop;
end loop;
if detect_double then
return xor_reduce(par_data) & par_data;
end if;
return par_data;
end function;
end hamming_pkg;

View file

@ -0,0 +1,101 @@
library ieee;
use ieee.std_logic_1164.all;
library work;
use work.hamming_pkg.hamming_encoder;
use work.hamming_pkg.hamming_decoder;
use work.hamming_pkg.get_parity_data_result;
use work.hamming_pkg.get_ecc_size;
entity hamming_register is
generic (
HAMMING_ENABLE : boolean;
RESET_VALUE : std_logic_vector(31 downto 0) := x"00000000"
);
port (
correct_en_i : in std_logic;
write_en_i : in std_logic;
data_i : in std_logic_vector(31 downto 0);
rstn_i : in std_logic;
clk_i : in std_logic;
single_err_o : out std_logic;
double_err_o : out std_logic;
data_o : out std_logic_vector(31 downto 0)
);
end entity;
architecture arch of hamming_register is
begin
-----------------------------------------------------------------------------------------------
------------------------------------- HAMMING DISABLED ----------------------------------------
-----------------------------------------------------------------------------------------------
g_NORMAL_REG : if not HAMMING_ENABLE generate
signal reg_r : std_logic_vector(31 downto 0);
begin
p_REG : process(clk_i, rstn_i)
begin
if rstn_i = '0' then
reg_r <= RESET_VALUE;
elsif rising_edge(clk_i) then
if write_en_i = '1' then
reg_r <= data_i;
end if;
end if;
end process;
single_err_o <= '0';
double_err_o <= '0';
data_o <= reg_r;
end generate;
-----------------------------------------------------------------------------------------------
-------------------------------------- HAMMING ENABLED ----------------------------------------
-----------------------------------------------------------------------------------------------
g_HAMMING_REG : if HAMMING_ENABLE generate
constant DETECT_DOUBLE : boolean := TRUE;
constant REG_DATA_WIDTH : integer := 32 + get_ecc_size(32, DETECT_DOUBLE);
constant RESET_VALUE_HAMMING : std_logic_vector(REG_DATA_WIDTH+31 downto 0) := get_parity_data_result(RESET_VALUE, DETECT_DOUBLE) & RESET_VALUE;
signal enc_w : std_logic_vector(REG_DATA_WIDTH-1 downto 0);
signal reg_r : std_logic_vector(REG_DATA_WIDTH-1 downto 0);
begin
-- encode next register data
hamming_encoder_i : hamming_encoder
generic map (
DATA_SIZE => 32,
DETECT_DOUBLE => DETECT_DOUBLE
)
port map (
data_i => data_i,
encoded_o => enc_w
);
-- create register
p_REG : process(clk_i, rstn_i)
begin
if rstn_i = '0' then
reg_r <= RESET_VALUE_HAMMING;
elsif rising_edge(clk_i) then
if write_en_i = '1' then
reg_r <= enc_w;
end if;
end if;
end process;
-- decode the data
hamming_decoder_i : hamming_decoder
generic map (
DATA_SIZE => 32,
DETECT_DOUBLE => DETECT_DOUBLE
)
port map (
encoded_i => reg_r,
correct_error_i => correct_en_i,
single_err_o => single_err_o,
double_err_o => double_err_o,
data_o => data_o
);
end generate;
end architecture;

396
hdl/harv.vhd Normal file
View file

@ -0,0 +1,396 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.harv_pkg.all;
entity harv is
generic (
PROGRAM_START_ADDR : std_logic_vector(31 downto 0) := x"00000000";
TRAP_HANDLER_ADDR : std_logic_vector(31 downto 0) := x"00000000";
TMR_CONTROL : boolean := FALSE;
TMR_ALU : boolean := FALSE;
HAMMING_REGFILE : boolean := FALSE;
HAMMING_PC : boolean := FALSE
);
port (
-- syncronization
rstn_i : in std_logic;
clk_i : in std_logic;
start_i : in std_logic;
-- reset cause
poweron_rstn_i : in std_logic;
wdt_rstn_i : in std_logic;
-- INSTRUCTION MEMORY
imem_instr_i : in std_logic_vector(31 downto 0);
imem_pc_o : out std_logic_vector(31 downto 0);
imem_req_o : out std_logic;
imem_gnt_i : in std_logic;
imem_err_i : in std_logic;
-- DATA MEMORY
hard_dmem_o : out std_logic;
dmem_data_i : in std_logic_vector(31 downto 0);
dmem_req_o : out std_logic;
dmem_wren_o : out std_logic;
dmem_gnt_i : in std_logic;
dmem_outofrange_i : in std_logic;
dmem_sbu_i : in std_logic;
dmem_dbu_i : in std_logic;
dmem_byte_en_o : out std_logic_vector(1 downto 0);
dmem_usgn_dat_o : out std_logic;
dmem_data_o : out std_logic_vector(31 downto 0);
dmem_addr_o : out std_logic_vector(31 downto 0)
);
end entity;
architecture arch of harv is
signal clk_w : std_logic;
---------Instruction Fetch ---------
signal if_pc_w : std_logic_vector(31 downto 0);
signal if_pc_4_w : std_logic_vector(31 downto 0);
signal update_pc_w : std_logic;
signal trap_w : std_logic;
--------- Instruction Decode --------
signal opcode_w : std_logic_vector( 6 downto 0);
signal funct3_w : std_logic_vector( 2 downto 0);
signal funct7_w : std_logic_vector( 6 downto 0);
signal funct12_w : std_logic_vector(11 downto 0);
signal rd_w : std_logic_vector( 4 downto 0);
signal rs1_w : std_logic_vector( 4 downto 0);
signal rs2_w : std_logic_vector( 4 downto 0);
signal imm_shamt_w : std_logic_vector( 4 downto 0);
signal imm_up_w : std_logic_vector(19 downto 0);
signal imm_upj_w : std_logic_vector(20 downto 0);
signal imm_branch_w : std_logic_vector(12 downto 0);
signal imm_store_w : std_logic_vector(11 downto 0);
signal imm_i_w : std_logic_vector(11 downto 0);
-- Immediate value
signal imm_sel_w : std_logic_vector(3 downto 0);
signal imm_w : std_logic_vector(31 downto 0);
-------------- CONTROL -------------
signal ctl_aluop_w : std_logic_vector(ALUOP_SIZE-1 downto 0);
signal ctl_alusrc_imm_w : std_logic;
signal ctl_imm_shamt_w : std_logic;
signal ctl_imm_up_w : std_logic;
signal ctl_regwr_w : std_logic;
signal ctl_inv_branch_w : std_logic;
signal ctl_branch_w : std_logic;
signal ctl_jump_w : std_logic;
signal ctl_jalr_w : std_logic;
signal ctl_ecall_w : std_logic;
signal ctl_memrd_w : std_logic;
signal ctl_memwr_w : std_logic;
signal ctl_byte_en_w : std_logic_vector(1 downto 0);
signal ctl_mem_usgn_w : std_logic;
signal ctl_load_upimm_w : std_logic;
signal ctl_auipc_w : std_logic;
signal ctl_csr_enable_w : std_logic;
signal ctl_csr_source_imm_w : std_logic;
signal ctl_csr_maskop_w : std_logic;
signal ctl_csr_clearop_w : std_logic;
signal instr_w : std_logic_vector(31 downto 0);
------------- REGFILE -------------
signal data_wr_w : std_logic_vector(31 downto 0);
signal reg_data1_w : std_logic_vector(31 downto 0);
signal reg_data2_w : std_logic_vector(31 downto 0);
-------------- ALU -----------------
signal alu_data1_w : std_logic_vector(31 downto 0);
signal alu_data2_w : std_logic_vector(31 downto 0);
signal alu_zero_w : std_logic;
signal alu_data_w : std_logic_vector(31 downto 0);
--------------- CSR -----------------
signal csr_rdata_w : std_logic_vector(31 downto 0);
signal csr_ucause_w : std_logic_vector(31 downto 0);
signal hard_pc_w : std_logic;
signal hard_regfile_w : std_logic;
signal hard_control_w : std_logic;
signal hard_alu_w : std_logic;
----------- ERROR wires -------------
-- signal reg1_cen_w : std_logic;
signal reg1_sbu_w : std_logic;
signal reg1_dbu_w : std_logic;
-- signal reg2_cen_w : std_logic;
signal reg2_sbu_w : std_logic;
signal reg2_dbu_w : std_logic;
-- signal pc_cen_w : std_logic;
signal pc_sbu_w : std_logic;
signal pc_dbu_w : std_logic;
signal control_err_w : std_logic;
signal alu_err_w : std_logic;
begin
clk_w <= clk_i;
instr_fetch_i : instr_fetch
generic map (
PROGRAM_START_ADDR => PROGRAM_START_ADDR,
TRAP_HANDLER_ADDR => TRAP_HANDLER_ADDR,
HAMMING_PC => HAMMING_PC
)
port map (
branch_imm_i => imm_branch_w,
jump_imm_i => alu_data_w,
inv_branch_i => ctl_inv_branch_w,
branch_i => ctl_branch_w,
zero_i => alu_zero_w,
jump_i => ctl_jump_w,
ecall_i => ctl_ecall_w,
correct_error_i => hard_pc_w,
instr_gnt_i => imem_gnt_i,
instr_i => imem_instr_i,
rstn_i => rstn_i,
clk_i => clk_w,
update_pc_i => update_pc_w,
trap_i => trap_w,
instr_o => instr_w,
sbu_o => pc_sbu_w,
dbu_o => pc_dbu_w,
pc_o => if_pc_w,
pc_4_o => if_pc_4_w
);
imem_pc_o <= if_pc_w;
opcode_w <= instr_w( 6 downto 0);
funct3_w <= instr_w(14 downto 12);
funct7_w <= instr_w(31 downto 25);
funct12_w <= instr_w(31 downto 20);
rd_w <= instr_w(11 downto 7);
rs1_w <= instr_w(19 downto 15);
rs2_w <= instr_w(24 downto 20);
imm_shamt_w <= instr_w(24 downto 20);
imm_up_w <= instr_w(31 downto 12);
imm_upj_w <= instr_w(31) & instr_w(19 downto 12) & instr_w(20) & instr_w(30 downto 21) & '0';
imm_branch_w <= instr_w(31) & instr_w(7) & instr_w(30 downto 25) & instr_w(11 downto 8) & '0';
imm_store_w <= instr_w(31 downto 25) & instr_w(11 downto 7);
imm_i_w <= instr_w(31 downto 20);
gen_ft_control : if TMR_CONTROL generate
control_i : control_tmr
port map (
start_i => start_i,
imem_gnt_i => imem_gnt_i,
imem_err_i => imem_err_i,
dmem_gnt_i => dmem_gnt_i,
dmem_outofrange_i => dmem_outofrange_i,
dmem_sbu_i => dmem_sbu_i and dmem_gnt_i and not ctl_memwr_w,
dmem_dbu_i => dmem_dbu_i and dmem_gnt_i and not ctl_memwr_w,
opcode_i => opcode_w,
funct3_i => funct3_w,
funct7_i => funct7_w,
funct12_i => funct12_w,
rstn_i => rstn_i,
clk_i => clk_i,
imem_req_o => imem_req_o,
dmem_req_o => dmem_req_o,
update_pc_o => update_pc_w,
trap_o => trap_w,
aluop_o => ctl_aluop_w,
alusrc_imm_o => ctl_alusrc_imm_w,
imm_shamt_o => ctl_imm_shamt_w,
imm_up_o => ctl_imm_up_w,
regwr_o => ctl_regwr_w,
inv_branch_o => ctl_inv_branch_w,
branch_o => ctl_branch_w,
jump_o => ctl_jump_w,
jalr_o => ctl_jalr_w,
ecall_o => ctl_ecall_w,
memrd_o => ctl_memrd_w,
memwr_o => ctl_memwr_w,
byte_en_o => ctl_byte_en_w,
mem_usgn_o => ctl_mem_usgn_w,
load_upimm_o => ctl_load_upimm_w,
auipc_o => ctl_auipc_w,
csr_enable_o => ctl_csr_enable_w,
csr_source_imm_o => ctl_csr_source_imm_w,
csr_maskop_o => ctl_csr_maskop_w,
csr_clearop_o => ctl_csr_clearop_w,
correct_error_i => hard_control_w,
error_o => control_err_w
);
end generate;
gen_normal_control : if not TMR_CONTROL generate
control_i : control
port map (
-- processor status
start_i => start_i,
imem_gnt_i => imem_gnt_i,
imem_err_i => imem_err_i,
dmem_gnt_i => dmem_gnt_i,
dmem_outofrange_i => dmem_outofrange_i,
dmem_sbu_i => dmem_sbu_i,
dmem_dbu_i => dmem_dbu_i,
-- instruction decode
opcode_i => opcode_w,
funct3_i => funct3_w,
funct7_i => funct7_w,
funct12_i => funct12_w,
rstn_i => rstn_i,
clk_i => clk_i,
-- processor status
imem_req_o => imem_req_o,
dmem_req_o => dmem_req_o,
update_pc_o => update_pc_w,
trap_o => trap_w,
-- instruction decode
aluop_o => ctl_aluop_w,
alusrc_imm_o => ctl_alusrc_imm_w,
imm_shamt_o => ctl_imm_shamt_w,
imm_up_o => ctl_imm_up_w,
regwr_o => ctl_regwr_w,
inv_branch_o => ctl_inv_branch_w,
branch_o => ctl_branch_w,
jump_o => ctl_jump_w,
jalr_o => ctl_jalr_w,
ecall_o => ctl_ecall_w,
memrd_o => ctl_memrd_w,
memwr_o => ctl_memwr_w,
byte_en_o => ctl_byte_en_w,
mem_usgn_o => ctl_mem_usgn_w,
load_upimm_o => ctl_load_upimm_w,
auipc_o => ctl_auipc_w,
csr_enable_o => ctl_csr_enable_w,
csr_source_imm_o => ctl_csr_source_imm_w,
csr_maskop_o => ctl_csr_maskop_w,
csr_clearop_o => ctl_csr_clearop_w
);
end generate;
data_wr_w <= dmem_data_i when ctl_memrd_w = '1' else
imm_w when ctl_load_upimm_w = '1' else
if_pc_4_w when ctl_jump_w = '1' else
csr_rdata_w when ctl_csr_enable_w = '1' else
alu_data_w;
regfile_i : regfile
generic map (
HAMMING_ENABLE => HAMMING_REGFILE
)
port map (
data_i => data_wr_w,
wren_i => ctl_regwr_w,
rd_i => rd_w,
rs1_i => rs1_w,
rs2_i => rs2_w,
correct_en_i => hard_regfile_w,
clk_i => clk_w,
sbu1_o => reg1_sbu_w,
dbu1_o => reg1_dbu_w,
data1_o => reg_data1_w,
sbu2_o => reg2_sbu_w,
dbu2_o => reg2_dbu_w,
data2_o => reg_data2_w
);
imm_sel_w <= ctl_imm_shamt_w & ctl_imm_up_w & ctl_memwr_w & (ctl_jump_w and not ctl_jalr_w);
with imm_sel_w select imm_w <=
std_logic_vector(resize(unsigned(imm_shamt_w), 32)) when "1000", -- ctl_imm_shamt_w = '1' else
std_logic_vector(shift_left(resize(signed(imm_up_w), 32), 12)) when "0100", -- ctl_imm_up_w = '1' else
std_logic_vector(resize(signed(imm_store_w), 32)) when "0010", -- ctl_memwr_w = '1' else
std_logic_vector(resize(signed(imm_upj_w), 32)) when "0001", -- (ctl_jump_w and not ctl_jalr_w) = '1' else
std_logic_vector(resize(signed(imm_i_w), 32)) when others;
alu_data1_w <= if_pc_w when (ctl_auipc_w or (ctl_jump_w and not ctl_jalr_w)) = '1' else
reg_data1_w;
alu_data2_w <= imm_w when ctl_alusrc_imm_w = '1' else reg_data2_w;
gen_ft_alu : if TMR_ALU generate
alu_i : alu_tmr
port map (
data1_i => alu_data1_w,
data2_i => alu_data2_w,
operation_i => ctl_aluop_w,
zero_o => alu_zero_w,
data_o => alu_data_w,
correct_error_i => hard_alu_w,
error_o => alu_err_w
);
end generate;
gen_normal_alu : if not TMR_ALU generate
alu_i : alu
port map (
data1_i => alu_data1_w,
data2_i => alu_data2_w,
operation_i => ctl_aluop_w,
zero_o => alu_zero_w,
data_o => alu_data_w
);
end generate;
---------- CSR registers ---------
csr_ucause_w <= x"00000010" when dmem_sbu_i = '1' else -- SBU
x"00000020" when dmem_dbu_i = '1' else -- DBU
x"00000007" when ctl_memwr_w = '1' else -- store address fault
x"00000005"; -- load address fault
csr_i : csr
generic map (
TMR_CONTROL => TMR_CONTROL,
TMR_ALU => TMR_ALU,
HAMMING_REGFILE => HAMMING_REGFILE,
HAMMING_PC => HAMMING_PC
)
port map (
-- sync
rstn_i => rstn_i,
clk_i => clk_i,
-- access interface
addr_i => imm_i_w,
data_o => csr_rdata_w,
rs1_data_i => reg_data1_w,
imm_data_i => rs1_w,
wren_i => ctl_csr_enable_w,
source_imm_i => ctl_csr_source_imm_w,
csr_maskop_i => ctl_csr_maskop_w,
csr_clearop_i => ctl_csr_clearop_w,
-- trap handling
trap_i => trap_w,
uscratch_i => alu_data_w,
uepc_i => if_pc_w,
ucause_i => csr_ucause_w,
utval_i => reg_data2_w,
uip_i => x"00000000",
-- errors
reg1_cen_i => update_pc_w,
reg1_sbu_i => reg1_sbu_w,
reg1_dbu_i => reg1_dbu_w,
reg2_cen_i => update_pc_w,
reg2_sbu_i => reg2_sbu_w,
reg2_dbu_i => reg2_dbu_w,
pc_cen_i => update_pc_w,
pc_sbu_i => pc_sbu_w,
pc_dbu_i => pc_dbu_w,
dmem_cen_i => dmem_gnt_i and not ctl_memwr_w,
dmem_sbu_i => dmem_sbu_i,
dmem_dbu_i => dmem_dbu_i,
control_cen_i => '1',
control_err_i => control_err_w,
alu_cen_i => dmem_gnt_i or update_pc_w or ctl_regwr_w,
alu_err_i => alu_err_w,
-- hardening
hard_pc_o => hard_pc_w,
hard_regfile_o => hard_regfile_w,
hard_dmem_o => hard_dmem_o,
hard_control_o => hard_control_w,
hard_alu_o => hard_alu_w,
-- resets
poweron_rstn_i => poweron_rstn_i,
wdt_rstn_i => wdt_rstn_i
);
-------- DATA MEMORY --------
-- output signals
-- dmem_req_o is set by the control unit
dmem_wren_o <= ctl_memwr_w;
dmem_byte_en_o <= ctl_byte_en_w;
dmem_usgn_dat_o <= ctl_mem_usgn_w;
dmem_data_o <= reg_data2_w;
dmem_addr_o <= alu_data_w;
end architecture;

265
hdl/harv_pkg.vhd Normal file
View file

@ -0,0 +1,265 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
package harv_pkg is
----- CONSTANTS -------
constant ALUOP_SIZE : integer := 4;
constant ALU_ADD_OP : std_logic_vector(ALUOP_SIZE-1 downto 0) := "0000";
constant ALU_SUB_OP : std_logic_vector(ALUOP_SIZE-1 downto 0) := "1000";
constant ALU_SLL_OP : std_logic_vector(ALUOP_SIZE-1 downto 0) := "0001";
constant ALU_SLT_OP : std_logic_vector(ALUOP_SIZE-1 downto 0) := "0010";
constant ALU_SLTU_OP : std_logic_vector(ALUOP_SIZE-1 downto 0) := "0011";
constant ALU_XOR_OP : std_logic_vector(ALUOP_SIZE-1 downto 0) := "0100";
constant ALU_SRL_OP : std_logic_vector(ALUOP_SIZE-1 downto 0) := "0101";
constant ALU_SRA_OP : std_logic_vector(ALUOP_SIZE-1 downto 0) := "1101";
constant ALU_OR_OP : std_logic_vector(ALUOP_SIZE-1 downto 0) := "0110";
constant ALU_AND_OP : std_logic_vector(ALUOP_SIZE-1 downto 0) := "0111";
------- COMPONENTS -----
component harv
generic (
PROGRAM_START_ADDR : std_logic_vector(31 downto 0);
TRAP_HANDLER_ADDR : std_logic_vector(31 downto 0);
TMR_CONTROL : boolean;
TMR_ALU : boolean;
HAMMING_REGFILE : boolean;
HAMMING_PC : boolean
);
port (
rstn_i : in std_logic;
clk_i : in std_logic;
start_i : in std_logic;
poweron_rstn_i : in std_logic;
wdt_rstn_i : in std_logic;
imem_instr_i : in std_logic_vector(31 downto 0);
imem_pc_o : out std_logic_vector(31 downto 0);
imem_req_o : out std_logic;
imem_gnt_i : in std_logic;
imem_err_i : in std_logic;
hard_dmem_o : out std_logic;
dmem_data_i : in std_logic_vector(31 downto 0);
dmem_req_o : out std_logic;
dmem_wren_o : out std_logic;
dmem_gnt_i : in std_logic;
dmem_outofrange_i : in std_logic;
dmem_sbu_i : in std_logic;
dmem_dbu_i : in std_logic;
dmem_byte_en_o : out std_logic_vector(1 downto 0);
dmem_usgn_dat_o : out std_logic;
dmem_data_o : out std_logic_vector(31 downto 0);
dmem_addr_o : out std_logic_vector(31 downto 0)
);
end component harv;
component control
port (
imem_gnt_i : in std_logic;
imem_err_i : in std_logic;
dmem_gnt_i : in std_logic;
dmem_outofrange_i : in std_logic;
dmem_sbu_i : in std_logic;
dmem_dbu_i : in std_logic;
opcode_i : in std_logic_vector(6 downto 0);
funct3_i : in std_logic_vector(2 downto 0);
funct7_i : in std_logic_vector(6 downto 0);
funct12_i : in std_logic_vector(11 downto 0);
rstn_i : in std_logic;
clk_i : in std_logic;
start_i : in std_logic;
imem_req_o : out std_logic;
dmem_req_o : out std_logic;
update_pc_o : out std_logic;
trap_o : out std_logic;
aluop_o : out std_logic_vector(ALUOP_SIZE-1 downto 0);
alusrc_imm_o : out std_logic;
imm_shamt_o : out std_logic;
imm_up_o : out std_logic;
regwr_o : out std_logic;
inv_branch_o : out std_logic;
branch_o : out std_logic;
jump_o : out std_logic;
jalr_o : out std_logic;
ecall_o : out std_logic;
memrd_o : out std_logic;
memwr_o : out std_logic;
byte_en_o : out std_logic_vector(1 downto 0);
mem_usgn_o : out std_logic;
load_upimm_o : out std_logic;
auipc_o : out std_logic;
csr_enable_o : out std_logic;
csr_source_imm_o : out std_logic;
csr_maskop_o : out std_logic;
csr_clearop_o : out std_logic
);
end component control;
component instr_fetch
generic (
PROGRAM_START_ADDR : std_logic_vector;
TRAP_HANDLER_ADDR : std_logic_vector;
HAMMING_PC : boolean
);
port (
branch_imm_i : in std_logic_vector(12 downto 0);
jump_imm_i : in std_logic_vector(31 downto 0);
inv_branch_i : in std_logic;
branch_i : in std_logic;
zero_i : in std_logic;
jump_i : in std_logic;
ecall_i : in std_logic;
correct_error_i : in std_logic;
instr_gnt_i : in std_logic;
instr_i : in std_logic_vector(31 downto 0);
rstn_i : in std_logic;
clk_i : in std_logic;
update_pc_i : in std_logic;
trap_i : in std_logic;
instr_o : out std_logic_vector(31 downto 0);
sbu_o : out std_logic;
dbu_o : out std_logic;
pc_o : out std_logic_vector(31 downto 0);
pc_4_o : out std_logic_vector(31 downto 0)
);
end component instr_fetch;
component regfile
generic (
HAMMING_ENABLE : boolean
);
port (
data_i : in std_logic_vector(31 downto 0);
wren_i : in std_logic;
rd_i : in std_logic_vector(4 downto 0);
rs1_i : in std_logic_vector(4 downto 0);
rs2_i : in std_logic_vector(4 downto 0);
correct_en_i : in std_logic;
clk_i : in std_logic;
sbu1_o : out std_logic;
dbu1_o : out std_logic;
data1_o : out std_logic_vector(31 downto 0);
sbu2_o : out std_logic;
dbu2_o : out std_logic;
data2_o : out std_logic_vector(31 downto 0)
);
end component regfile;
component alu
port (
data1_i : in std_logic_vector(31 downto 0);
data2_i : in std_logic_vector(31 downto 0);
operation_i : in std_logic_vector(ALUOP_SIZE-1 downto 0);
zero_o : out std_logic;
data_o : out std_logic_vector(31 downto 0)
);
end component alu;
component csr
generic (
TMR_CONTROL : boolean;
TMR_ALU : boolean;
HAMMING_REGFILE : boolean;
HAMMING_PC : boolean
);
port (
rstn_i : in std_logic;
clk_i : in std_logic;
addr_i : in std_logic_vector(11 downto 0);
data_o : out std_logic_vector(31 downto 0);
rs1_data_i : in std_logic_vector(31 downto 0);
imm_data_i : in std_logic_vector(4 downto 0);
wren_i : in std_logic;
source_imm_i : in std_logic;
csr_maskop_i : in std_logic;
csr_clearop_i : in std_logic;
trap_i : in std_logic;
uscratch_i : in std_logic_vector(31 downto 0);
uepc_i : in std_logic_vector(31 downto 0);
ucause_i : in std_logic_vector(31 downto 0);
utval_i : in std_logic_vector(31 downto 0);
uip_i : in std_logic_vector(31 downto 0);
reg1_cen_i : in std_logic;
reg1_sbu_i : in std_logic;
reg1_dbu_i : in std_logic;
reg2_cen_i : in std_logic;
reg2_sbu_i : in std_logic;
reg2_dbu_i : in std_logic;
pc_cen_i : in std_logic;
pc_sbu_i : in std_logic;
pc_dbu_i : in std_logic;
dmem_cen_i : in std_logic;
dmem_sbu_i : in std_logic;
dmem_dbu_i : in std_logic;
control_cen_i : in std_logic;
control_err_i : in std_logic;
alu_cen_i : in std_logic;
alu_err_i : in std_logic;
hard_pc_o : out std_logic;
hard_regfile_o : out std_logic;
hard_dmem_o : out std_logic;
hard_control_o : out std_logic;
hard_alu_o : out std_logic;
poweron_rstn_i : in std_logic;
wdt_rstn_i : in std_logic
);
end component csr;
------------- FAULT TOLERANT COMPONENTS --------------------
component control_tmr
port (
imem_gnt_i : in std_logic;
imem_err_i : in std_logic;
dmem_gnt_i : in std_logic;
dmem_outofrange_i : in std_logic;
dmem_sbu_i : in std_logic;
dmem_dbu_i : in std_logic;
opcode_i : in std_logic_vector(6 downto 0);
funct3_i : in std_logic_vector(2 downto 0);
funct7_i : in std_logic_vector(6 downto 0);
funct12_i : in std_logic_vector(11 downto 0);
correct_error_i : in std_logic;
rstn_i : in std_logic;
clk_i : in std_logic;
start_i : in std_logic;
imem_req_o : out std_logic;
dmem_req_o : out std_logic;
update_pc_o : out std_logic;
trap_o : out std_logic;
error_o : out std_logic;
aluop_o : out std_logic_vector(ALUOP_SIZE-1 downto 0);
alusrc_imm_o : out std_logic;
imm_shamt_o : out std_logic;
imm_up_o : out std_logic;
regwr_o : out std_logic;
inv_branch_o : out std_logic;
branch_o : out std_logic;
jump_o : out std_logic;
jalr_o : out std_logic;
ecall_o : out std_logic;
memrd_o : out std_logic;
memwr_o : out std_logic;
byte_en_o : out std_logic_vector(1 downto 0);
mem_usgn_o : out std_logic;
load_upimm_o : out std_logic;
auipc_o : out std_logic;
csr_enable_o : out std_logic;
csr_source_imm_o : out std_logic;
csr_maskop_o : out std_logic;
csr_clearop_o : out std_logic
);
end component control_tmr;
component alu_tmr
port (
data1_i : in std_logic_vector(31 downto 0);
data2_i : in std_logic_vector(31 downto 0);
operation_i : in std_logic_vector(ALUOP_SIZE-1 downto 0);
correct_error_i : in std_logic;
error_o : out std_logic;
zero_o : out std_logic;
data_o : out std_logic_vector(31 downto 0)
);
end component alu_tmr;
end package;

91
hdl/instr_fetch.vhd Normal file
View file

@ -0,0 +1,91 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.hamming_pkg.hamming_register;
entity instr_fetch is
generic (
PROGRAM_START_ADDR : std_logic_vector(31 downto 0);
TRAP_HANDLER_ADDR : std_logic_vector(31 downto 0);
HAMMING_PC : boolean
);
port (
-- input ports
branch_imm_i : in std_logic_vector(12 downto 0);
jump_imm_i : in std_logic_vector(31 downto 0);
inv_branch_i : in std_logic;
branch_i : in std_logic;
zero_i : in std_logic;
jump_i : in std_logic;
ecall_i : in std_logic;
correct_error_i : in std_logic;
-- instruction data
instr_gnt_i : in std_logic;
instr_i : in std_logic_vector(31 downto 0);
-- sync
rstn_i : in std_logic;
clk_i : in std_logic;
update_pc_i : in std_logic;
trap_i : in std_logic;
-- output ports
instr_o : out std_logic_vector(31 downto 0);
sbu_o : out std_logic;
dbu_o : out std_logic;
pc_o : out std_logic_vector(31 downto 0);
pc_4_o : out std_logic_vector(31 downto 0)
);
end entity;
architecture arch of instr_fetch is
signal pc_par_w : std_logic_vector(31 downto 0);
signal pc_adder_w : std_logic_vector(31 downto 0);
signal next_pc_w : std_logic_vector(31 downto 0);
signal pc_w : std_logic_vector(31 downto 0);
begin
-- calculate (PC + 4) or (PC + branch_eq)
pc_par_w <= std_logic_vector(resize(signed(branch_imm_i), 32)) when (branch_i and (zero_i xor inv_branch_i)) = '1' else x"00000004";
pc_adder_w <= std_logic_vector(signed(pc_w) + signed(pc_par_w));
pc_4_o <= pc_adder_w;
-- define the next PC address
next_pc_w <= TRAP_HANDLER_ADDR when trap_i = '1' else
jump_imm_i when jump_i = '1' else
pc_adder_w;
-- set PC output
pc_o <= pc_w;
register_pc_i : hamming_register
generic map (
HAMMING_ENABLE => HAMMING_PC,
RESET_VALUE => PROGRAM_START_ADDR
)
port map (
correct_en_i => correct_error_i,
write_en_i => update_pc_i,
data_i => next_pc_w,
rstn_i => rstn_i,
clk_i => clk_i,
single_err_o => sbu_o,
double_err_o => dbu_o,
data_o => pc_w
);
register_instr_i : hamming_register
generic map (
HAMMING_ENABLE => HAMMING_PC,
RESET_VALUE => (31 downto 0 => '0')
)
port map (
correct_en_i => correct_error_i,
write_en_i => instr_gnt_i,
data_i => instr_i,
rstn_i => rstn_i,
clk_i => clk_i,
single_err_o => open,
double_err_o => open,
data_o => instr_o
);
end architecture;

142
hdl/regfile.vhd Normal file
View file

@ -0,0 +1,142 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_misc.all;
library work;
use work.hamming_pkg.all;
entity regfile is
generic (
HAMMING_ENABLE : boolean
);
port (
-- input ports
data_i : in std_logic_vector(31 downto 0);
wren_i : in std_logic;
rd_i : in std_logic_vector(4 downto 0);
rs1_i : in std_logic_vector(4 downto 0);
rs2_i : in std_logic_vector(4 downto 0);
correct_en_i : in std_logic;
-- synchronization
clk_i : in std_logic;
-- output ports
sbu1_o : out std_logic;
dbu1_o : out std_logic;
data1_o : out std_logic_vector(31 downto 0);
sbu2_o : out std_logic;
dbu2_o : out std_logic;
data2_o : out std_logic_vector(31 downto 0)
);
end entity;
architecture arch of regfile is
begin
-----------------------------------------------------------------------------------------------
------------------------------------- HAMMING DISABLED ----------------------------------------
-----------------------------------------------------------------------------------------------
g_NORMAL : if not HAMMING_ENABLE generate
type regfile_t is array(natural range <>) of std_logic_vector(31 downto 0);
signal regfile_r : regfile_t(31 downto 1);
signal regfile_w : regfile_t(31 downto 0);
signal rs1_w : std_logic_vector(4 downto 0);
signal rs2_w : std_logic_vector(4 downto 0);
begin
-- WRITE REGISTERS
p_WR : process(clk_i)
begin
if rising_edge(clk_i) then
if wren_i = '1' and rd_i /= "00000" and rd_i /= "UUUUU" then
regfile_r(to_integer(unsigned(rd_i))) <= data_i;
end if;
end if;
end process;
regfile_w(31 downto 1) <= regfile_r;
regfile_w(0) <= (others => '0');
-- READ REGISTERS
sbu1_o <= '0';
dbu1_o <= '0';
data1_o <= regfile_w(to_integer(unsigned(rs1_i)));
sbu2_o <= '0';
dbu2_o <= '0';
data2_o <= regfile_w(to_integer(unsigned(rs2_i)));
end generate;
-----------------------------------------------------------------------------------------------
-------------------------------------- HAMMING ENABLED ----------------------------------------
-----------------------------------------------------------------------------------------------
g_HAMMING : if HAMMING_ENABLE generate
constant DETECT_DOUBLE : boolean := TRUE;
constant PARITY_BITS_QT : integer := get_ecc_size(32, DETECT_DOUBLE);
type regfile_hamming_t is array(natural range <>) of std_logic_vector(31+PARITY_BITS_QT downto 0);
signal regfile_r : regfile_hamming_t(31 downto 1);
signal regfile_w : regfile_hamming_t(31 downto 0);
signal data_wr_enc_w : std_logic_vector(PARITY_BITS_QT+31 downto 0);
signal data_s1_enc_w : std_logic_vector(PARITY_BITS_QT+31 downto 0);
signal data_s2_enc_w : std_logic_vector(PARITY_BITS_QT+31 downto 0);
begin
hamming_encoder_i : hamming_encoder
generic map (
DATA_SIZE => 32,
DETECT_DOUBLE => DETECT_DOUBLE
)
port map (
data_i => data_i,
encoded_o => data_wr_enc_w
);
-- WRITE REGISTER
p_WR : process(clk_i, wren_i)
begin
if rising_edge(clk_i) then
if wren_i = '1' and rd_i /= "00000" then
regfile_r(to_integer(unsigned(rd_i))) <= data_wr_enc_w;
end if;
end if;
end process;
-- READ REGISTERS
regfile_w(31 downto 1) <= regfile_r;
regfile_w(0) <= (others => '0');
data_s1_enc_w <= regfile_w(to_integer(unsigned(rs1_i)));
data_s2_enc_w <= regfile_w(to_integer(unsigned(rs2_i)));
hamming_decoder_data1_i : hamming_decoder
generic map (
DATA_SIZE => 32,
DETECT_DOUBLE => DETECT_DOUBLE
)
port map (
encoded_i => data_s1_enc_w,
correct_error_i => correct_en_i,
single_err_o => sbu1_o,
double_err_o => dbu1_o,
data_o => data1_o
);
hamming_decoder_data2_i : hamming_decoder
generic map (
DATA_SIZE => 32,
DETECT_DOUBLE => DETECT_DOUBLE
)
port map (
encoded_i => data_s2_enc_w,
correct_error_i => correct_en_i,
single_err_o => sbu2_o,
double_err_o => dbu2_o,
data_o => data2_o
);
end generate;
end architecture;

BIN
images/rars-data-export.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

BIN
images/rars-text-export.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

311
script/project.tcl Normal file
View file

@ -0,0 +1,311 @@
#*****************************************************************************************
# Vivado (TM) v2020.2 (64-bit)
#
# project.tcl: Tcl script for re-creating project 'harv'
#
# Generated by Vivado on Tue Jun 15 18:52:54 CEST 2021
# IP Build 3064653 on Wed Nov 18 14:17:31 MST 2020
#
# This file contains the Vivado Tcl commands for re-creating the project to the state*
# when this script was generated. In order to re-create the project, please source this
# file in the Vivado Tcl Shell.
#
# * Note that the runs in the created project will be configured the same way as the
# original project, however they will not be launched automatically. To regenerate the
# run results please launch the synthesis/implementation runs as needed.
#
#*****************************************************************************************
# NOTE: In order to use this script for source control purposes, please make sure that the
# following files are added to the source control system:-
#
# 1. This project restoration tcl script (project.tcl) that was generated.
#
# 2. The following source(s) files that were local or imported into the original project.
# (Please see the '$orig_proj_dir' and '$origin_dir' variable setting below at the start of the script)
#
# "xilinx/sim_from_dump_behav.wcfg"
#
# 3. The following remote source files that were added to the original project:-
#
# "hdl/harv_pkg.vhd"
# "hdl/alu.vhd"
# "hdl/ft_components/alu_tmr.vhd"
# "hdl/control.vhd"
# "hdl/ft_components/control_tmr.vhd"
# "hdl/csr.vhd"
# "hdl/ft_components/hamming_pkg.vhd"
# "hdl/ft_components/hamming_decoder.vhd"
# "hdl/ft_components/hamming_encoder.vhd"
# "hdl/ft_components/hamming_register.vhd"
# "hdl/instr_fetch.vhd"
# "hdl/regfile.vhd"
# "hdl/harv.vhd"
# "sim/sim_from_dump.vhd"
#
#*****************************************************************************************
# Check file required for this script exists
proc checkRequiredFiles { origin_dir} {
set status true
set files [list \
"xilinx/sim_from_dump_behav.wcfg" \
]
foreach ifile $files {
if { ![file isfile $ifile] } {
puts " Could not find local file $ifile "
set status false
}
}
set files [list \
"hdl/harv_pkg.vhd" \
"hdl/alu.vhd" \
"hdl/ft_components/alu_tmr.vhd" \
"hdl/control.vhd" \
"hdl/ft_components/control_tmr.vhd" \
"hdl/csr.vhd" \
"hdl/ft_components/hamming_pkg.vhd" \
"hdl/ft_components/hamming_decoder.vhd" \
"hdl/ft_components/hamming_encoder.vhd" \
"hdl/ft_components/hamming_register.vhd" \
"hdl/instr_fetch.vhd" \
"hdl/regfile.vhd" \
"hdl/harv.vhd" \
"sim/sim_from_dump.vhd" \
]
foreach ifile $files {
if { ![file isfile $ifile] } {
puts " Could not find remote file $ifile "
set status false
}
}
return $status
}
# Set the reference directory for source file relative paths (by default the value is script directory path)
set origin_dir "."
# Use origin directory path location variable, if specified in the tcl shell
if { [info exists ::origin_dir_loc] } {
set origin_dir $::origin_dir_loc
}
# Set the project name
set _xil_proj_name_ "harv"
# Use project name variable, if specified in the tcl shell
if { [info exists ::user_project_name] } {
set _xil_proj_name_ $::user_project_name
}
variable script_file
set script_file "project.tcl"
# Help information for this script
proc print_help {} {
variable script_file
puts "\nDescription:"
puts "Recreate a Vivado project from this script. The created project will be"
puts "functionally equivalent to the original project for which this script was"
puts "generated. The script contains commands for creating a project, filesets,"
puts "runs, adding/importing sources and setting properties on various objects.\n"
puts "Syntax:"
puts "$script_file"
puts "$script_file -tclargs \[--origin_dir <path>\]"
puts "$script_file -tclargs \[--project_name <name>\]"
puts "$script_file -tclargs \[--help\]\n"
puts "Usage:"
puts "Name Description"
puts "-------------------------------------------------------------------------"
puts "\[--origin_dir <path>\] Determine source file paths wrt this path. Default"
puts " origin_dir path value is \".\", otherwise, the value"
puts " that was set with the \"-paths_relative_to\" switch"
puts " when this script was generated.\n"
puts "\[--project_name <name>\] Create project with the specified name. Default"
puts " name is the name of the project from where this"
puts " script was generated.\n"
puts "\[--help\] Print help information for this script"
puts "-------------------------------------------------------------------------\n"
exit 0
}
if { $::argc > 0 } {
for {set i 0} {$i < $::argc} {incr i} {
set option [string trim [lindex $::argv $i]]
switch -regexp -- $option {
"--origin_dir" { incr i; set origin_dir [lindex $::argv $i] }
"--project_name" { incr i; set _xil_proj_name_ [lindex $::argv $i] }
"--help" { print_help }
default {
if { [regexp {^-} $option] } {
puts "ERROR: Unknown option '$option' specified, please type '$script_file -tclargs --help' for usage info.\n"
return 1
}
}
}
}
}
# Set the directory path for the original project from where this script was exported
set orig_proj_dir "[file normalize "$origin_dir/xilinx"]"
# Check for paths and files needed for project creation
set validate_required 0
if { $validate_required } {
if { [checkRequiredFiles $origin_dir] } {
puts "Tcl file $script_file is valid. All files required for project creation is accesable. "
} else {
puts "Tcl file $script_file is not valid. Not all files required for project creation is accesable. "
return
}
}
# Create project
create_project ${_xil_proj_name_} "xilinx/" -part xc7z020clg484-1
# Set the directory path for the new project
set proj_dir [get_property directory [current_project]]
# Set project properties
set obj [current_project]
set_property -name "board_part" -value "em.avnet.com:zed:part0:1.4" -objects $obj
set_property -name "default_lib" -value "xil_defaultlib" -objects $obj
set_property -name "enable_vhdl_2008" -value "1" -objects $obj
set_property -name "ip_cache_permissions" -value "read write" -objects $obj
set_property -name "ip_output_repo" -value "$proj_dir/${_xil_proj_name_}.cache/ip" -objects $obj
set_property -name "mem.enable_memory_map_generation" -value "1" -objects $obj
set_property -name "platform.board_id" -value "zed" -objects $obj
set_property -name "sim.central_dir" -value "$proj_dir/${_xil_proj_name_}.ip_user_files" -objects $obj
set_property -name "sim.ip.auto_export_scripts" -value "1" -objects $obj
set_property -name "simulator_language" -value "VHDL" -objects $obj
set_property -name "target_language" -value "VHDL" -objects $obj
set_property -name "webtalk.xsim_launch_sim" -value "30" -objects $obj
# Create 'sources_1' fileset (if not found)
if {[string equal [get_filesets -quiet sources_1] ""]} {
create_fileset -srcset sources_1
}
# Set 'sources_1' fileset object
set obj [get_filesets sources_1]
set files [list \
[file normalize "${origin_dir}/hdl/harv_pkg.vhd"] \
[file normalize "${origin_dir}/hdl/alu.vhd"] \
[file normalize "${origin_dir}/hdl/ft_components/alu_tmr.vhd"] \
[file normalize "${origin_dir}/hdl/control.vhd"] \
[file normalize "${origin_dir}/hdl/ft_components/control_tmr.vhd"] \
[file normalize "${origin_dir}/hdl/csr.vhd"] \
[file normalize "${origin_dir}/hdl/ft_components/hamming_pkg.vhd"] \
[file normalize "${origin_dir}/hdl/ft_components/hamming_decoder.vhd"] \
[file normalize "${origin_dir}/hdl/ft_components/hamming_encoder.vhd"] \
[file normalize "${origin_dir}/hdl/ft_components/hamming_register.vhd"] \
[file normalize "${origin_dir}/hdl/instr_fetch.vhd"] \
[file normalize "${origin_dir}/hdl/regfile.vhd"] \
[file normalize "${origin_dir}/hdl/harv.vhd"] \
]
add_files -norecurse -fileset $obj $files
# Set 'sources_1' fileset file properties for remote files
set file "$origin_dir/hdl/harv_pkg.vhd"
set file [file normalize $file]
set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]]
set_property -name "file_type" -value "VHDL 2008" -objects $file_obj
set file "$origin_dir/hdl/alu.vhd"
set file [file normalize $file]
set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]]
set_property -name "file_type" -value "VHDL 2008" -objects $file_obj
set file "$origin_dir/hdl/ft_components/alu_tmr.vhd"
set file [file normalize $file]
set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]]
set_property -name "file_type" -value "VHDL 2008" -objects $file_obj
set file "$origin_dir/hdl/control.vhd"
set file [file normalize $file]
set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]]
set_property -name "file_type" -value "VHDL 2008" -objects $file_obj
set file "$origin_dir/hdl/ft_components/control_tmr.vhd"
set file [file normalize $file]
set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]]
set_property -name "file_type" -value "VHDL 2008" -objects $file_obj
set file "$origin_dir/hdl/csr.vhd"
set file [file normalize $file]
set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]]
set_property -name "file_type" -value "VHDL 2008" -objects $file_obj
set file "$origin_dir/hdl/ft_components/hamming_pkg.vhd"
set file [file normalize $file]
set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]]
set_property -name "file_type" -value "VHDL 2008" -objects $file_obj
set file "$origin_dir/hdl/ft_components/hamming_decoder.vhd"
set file [file normalize $file]
set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]]
set_property -name "file_type" -value "VHDL 2008" -objects $file_obj
set file "$origin_dir/hdl/ft_components/hamming_encoder.vhd"
set file [file normalize $file]
set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]]
set_property -name "file_type" -value "VHDL 2008" -objects $file_obj
set file "$origin_dir/hdl/ft_components/hamming_register.vhd"
set file [file normalize $file]
set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]]
set_property -name "file_type" -value "VHDL 2008" -objects $file_obj
set file "$origin_dir/hdl/instr_fetch.vhd"
set file [file normalize $file]
set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]]
set_property -name "file_type" -value "VHDL 2008" -objects $file_obj
set file "$origin_dir/hdl/regfile.vhd"
set file [file normalize $file]
set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]]
set_property -name "file_type" -value "VHDL 2008" -objects $file_obj
set file "$origin_dir/hdl/harv.vhd"
set file [file normalize $file]
set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]]
set_property -name "file_type" -value "VHDL 2008" -objects $file_obj
# Set 'sources_1' fileset properties
set obj [get_filesets sources_1]
set_property -name "top" -value "harv" -objects $obj
# Create 'sim_1' fileset (if not found)
if {[string equal [get_filesets -quiet sim_1] ""]} {
create_fileset -simset sim_1
}
# Set 'sim_1' fileset object
set obj [get_filesets sim_1]
set files [list \
[file normalize "${origin_dir}/sim/sim_from_dump.vhd"] \
]
add_files -norecurse -fileset $obj $files
# Import local files from the original project
set files [list \
[file normalize "${origin_dir}/xilinx/sim_from_dump_behav.wcfg" ]\
]
add_files -norecurse -fileset sim_1 $files
# Set 'sim_1' fileset file properties for remote files
set file "$origin_dir/sim/sim_from_dump.vhd"
set file [file normalize $file]
set file_obj [get_files -of_objects [get_filesets sim_1] [list "*$file"]]
set_property -name "file_type" -value "VHDL 2008" -objects $file_obj
# Set 'sim_1' fileset properties
set obj [get_filesets sim_1]
set_property -name "hbs.configure_design_for_hier_access" -value "1" -objects $obj
set_property -name "top" -value "sim_from_dump" -objects $obj
set_property -name "top_lib" -value "xil_defaultlib" -objects $obj
puts "INFO: Project created: ${_xil_proj_name_}"
exit

240
sim/sim_from_dump.vhd Normal file
View file

@ -0,0 +1,240 @@
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;

20
src/test.asm Normal file
View file

@ -0,0 +1,20 @@
.data
var0: 100
var1: 200
var3:
.text
lw t0, var0
lw t1, var1
sub t2, t1, t0
add t3, t1, t2
add t3, t3, t3
la t4, var3
sw t3, 0(t4)
lw t4, 0(t4)
end_loop:
j end_loop

View file

@ -0,0 +1,210 @@
<?xml version="1.0" encoding="UTF-8"?>
<wave_config>
<wave_state>
</wave_state>
<db_ref_list>
<db_ref path="sim_from_dump_behav.wdb" id="1">
<top_modules>
<top_module name="hamming_pkg" />
<top_module name="harv_pkg" />
<top_module name="sim_from_dump" />
</top_modules>
</db_ref>
</db_ref_list>
<zoom_setting>
<ZoomStartTime time="0fs"></ZoomStartTime>
<ZoomEndTime time="4890001fs"></ZoomEndTime>
<Cursor1Time time="2070000fs"></Cursor1Time>
</zoom_setting>
<column_width_setting>
<NameColumnWidth column_width="204"></NameColumnWidth>
<ValueColumnWidth column_width="66"></ValueColumnWidth>
</column_width_setting>
<WVObjectSize size="28" />
<wvobject type="array" fp_name="/sim_from_dump/INST_DUMP_FILE_PATH">
<obj_property name="ElementShortName">INST_DUMP_FILE_PATH[1:33]</obj_property>
<obj_property name="ObjectShortName">INST_DUMP_FILE_PATH[1:33]</obj_property>
</wvobject>
<wvobject type="array" fp_name="/sim_from_dump/DATA_DUMP_FILE_PATH">
<obj_property name="ElementShortName">DATA_DUMP_FILE_PATH[1:33]</obj_property>
<obj_property name="ObjectShortName">DATA_DUMP_FILE_PATH[1:33]</obj_property>
</wvobject>
<wvobject type="other" fp_name="/sim_from_dump/period">
<obj_property name="ElementShortName">period</obj_property>
<obj_property name="ObjectShortName">period</obj_property>
</wvobject>
<wvobject type="logic" fp_name="/sim_from_dump/rstn">
<obj_property name="ElementShortName">rstn</obj_property>
<obj_property name="ObjectShortName">rstn</obj_property>
</wvobject>
<wvobject type="logic" fp_name="/sim_from_dump/clk">
<obj_property name="ElementShortName">clk</obj_property>
<obj_property name="ObjectShortName">clk</obj_property>
</wvobject>
<wvobject type="logic" fp_name="/sim_from_dump/start">
<obj_property name="ElementShortName">start</obj_property>
<obj_property name="ObjectShortName">start</obj_property>
</wvobject>
<wvobject type="logic" fp_name="/sim_from_dump/imem_gnt_i">
<obj_property name="ElementShortName">imem_gnt_i</obj_property>
<obj_property name="ObjectShortName">imem_gnt_i</obj_property>
</wvobject>
<wvobject type="array" fp_name="/sim_from_dump/harv_i/if_pc_w">
<obj_property name="ElementShortName">if_pc_w[31:0]</obj_property>
<obj_property name="ObjectShortName">if_pc_w[31:0]</obj_property>
</wvobject>
<wvobject type="array" fp_name="/sim_from_dump/harv_i/instr_fetch_i/instr_o">
<obj_property name="ElementShortName">instr_o[31:0]</obj_property>
<obj_property name="ObjectShortName">instr_o[31:0]</obj_property>
</wvobject>
<wvobject type="array" fp_name="/sim_from_dump/harv_i/regfile_i/g_normal/regfile_w[29]">
<obj_property name="DisplayName">label</obj_property>
<obj_property name="ElementShortName">[29][31:0]</obj_property>
<obj_property name="ObjectShortName">[29][31:0]</obj_property>
<obj_property name="label">reg_t4</obj_property>
<obj_property name="Radix">SIGNEDDECRADIX</obj_property>
</wvobject>
<wvobject type="array" fp_name="/sim_from_dump/harv_i/regfile_i/g_normal/regfile_w[28]">
<obj_property name="DisplayName">label</obj_property>
<obj_property name="ElementShortName">[28][31:0]</obj_property>
<obj_property name="ObjectShortName">[28][31:0]</obj_property>
<obj_property name="label">reg_t3</obj_property>
<obj_property name="Radix">SIGNEDDECRADIX</obj_property>
</wvobject>
<wvobject type="array" fp_name="/sim_from_dump/harv_i/regfile_i/g_normal/regfile_w[7]">
<obj_property name="DisplayName">label</obj_property>
<obj_property name="ElementShortName">[7][31:0]</obj_property>
<obj_property name="ObjectShortName">[7][31:0]</obj_property>
<obj_property name="label">reg_t2</obj_property>
<obj_property name="Radix">SIGNEDDECRADIX</obj_property>
</wvobject>
<wvobject type="array" fp_name="/sim_from_dump/harv_i/regfile_i/g_normal/regfile_w[6]">
<obj_property name="DisplayName">label</obj_property>
<obj_property name="ElementShortName">[6][31:0]</obj_property>
<obj_property name="ObjectShortName">[6][31:0]</obj_property>
<obj_property name="label">reg_t1</obj_property>
<obj_property name="Radix">SIGNEDDECRADIX</obj_property>
</wvobject>
<wvobject type="array" fp_name="/sim_from_dump/harv_i/regfile_i/g_normal/regfile_w[5]">
<obj_property name="DisplayName">label</obj_property>
<obj_property name="ElementShortName">[5][31:0]</obj_property>
<obj_property name="ObjectShortName">[5][31:0]</obj_property>
<obj_property name="label">reg_t0</obj_property>
<obj_property name="Radix">SIGNEDDECRADIX</obj_property>
</wvobject>
<wvobject type="array" fp_name="/sim_from_dump/harv_i/regfile_i/g_normal/regfile_w">
<obj_property name="ElementShortName">regfile_w[31:0][31:0]</obj_property>
<obj_property name="ObjectShortName">regfile_w[31:0][31:0]</obj_property>
</wvobject>
<wvobject fp_name="divider12650" type="divider">
<obj_property name="label">CORE</obj_property>
<obj_property name="DisplayName">label</obj_property>
</wvobject>
<wvobject type="array" fp_name="/sim_from_dump/harv_i/gen_normal_control/control_i/proc_status_r">
<obj_property name="ElementShortName">proc_status_r[2:0]</obj_property>
<obj_property name="ObjectShortName">proc_status_r[2:0]</obj_property>
</wvobject>
<wvobject type="array" fp_name="/sim_from_dump/harv_i/regfile_i/data_i">
<obj_property name="ElementShortName">data_i[31:0]</obj_property>
<obj_property name="ObjectShortName">data_i[31:0]</obj_property>
</wvobject>
<wvobject type="logic" fp_name="/sim_from_dump/harv_i/regfile_i/wren_i">
<obj_property name="ElementShortName">wren_i</obj_property>
<obj_property name="ObjectShortName">wren_i</obj_property>
</wvobject>
<wvobject fp_name="divider12648" type="divider">
<obj_property name="label">MEMORIES</obj_property>
<obj_property name="DisplayName">label</obj_property>
</wvobject>
<wvobject type="group" fp_name="group177">
<obj_property name="label">imem</obj_property>
<obj_property name="DisplayName">label</obj_property>
<wvobject type="other" fp_name="/sim_from_dump/DATA_SIZE">
<obj_property name="ElementShortName">DATA_SIZE</obj_property>
<obj_property name="ObjectShortName">DATA_SIZE</obj_property>
</wvobject>
<wvobject type="array" fp_name="/sim_from_dump/imem_instr_i">
<obj_property name="ElementShortName">imem_instr_i[31:0]</obj_property>
<obj_property name="ObjectShortName">imem_instr_i[31:0]</obj_property>
</wvobject>
<wvobject type="array" fp_name="/sim_from_dump/imem_pc_o">
<obj_property name="ElementShortName">imem_pc_o[31:0]</obj_property>
<obj_property name="ObjectShortName">imem_pc_o[31:0]</obj_property>
</wvobject>
<wvobject type="logic" fp_name="/sim_from_dump/imem_req_o">
<obj_property name="ElementShortName">imem_req_o</obj_property>
<obj_property name="ObjectShortName">imem_req_o</obj_property>
</wvobject>
<wvobject type="logic" fp_name="/sim_from_dump/imem_gnt_i">
<obj_property name="ElementShortName">imem_gnt_i</obj_property>
<obj_property name="ObjectShortName">imem_gnt_i</obj_property>
</wvobject>
</wvobject>
<wvobject type="group" fp_name="group4275">
<obj_property name="label">dmem</obj_property>
<obj_property name="DisplayName">label</obj_property>
<obj_property name="isExpanded"></obj_property>
<wvobject type="array" fp_name="/sim_from_dump/dmem_data_i">
<obj_property name="ElementShortName">dmem_data_i[31:0]</obj_property>
<obj_property name="ObjectShortName">dmem_data_i[31:0]</obj_property>
</wvobject>
<wvobject type="logic" fp_name="/sim_from_dump/dmem_req_o">
<obj_property name="ElementShortName">dmem_req_o</obj_property>
<obj_property name="ObjectShortName">dmem_req_o</obj_property>
</wvobject>
<wvobject type="logic" fp_name="/sim_from_dump/dmem_wren_o">
<obj_property name="ElementShortName">dmem_wren_o</obj_property>
<obj_property name="ObjectShortName">dmem_wren_o</obj_property>
</wvobject>
<wvobject type="logic" fp_name="/sim_from_dump/dmem_gnt_i">
<obj_property name="ElementShortName">dmem_gnt_i</obj_property>
<obj_property name="ObjectShortName">dmem_gnt_i</obj_property>
</wvobject>
<wvobject type="logic" fp_name="/sim_from_dump/dmem_outofrange_i">
<obj_property name="ElementShortName">dmem_outofrange_i</obj_property>
<obj_property name="ObjectShortName">dmem_outofrange_i</obj_property>
</wvobject>
<wvobject type="array" fp_name="/sim_from_dump/dmem_byte_en_o">
<obj_property name="ElementShortName">dmem_byte_en_o[1:0]</obj_property>
<obj_property name="ObjectShortName">dmem_byte_en_o[1:0]</obj_property>
<obj_property name="Radix">BINARYRADIX</obj_property>
</wvobject>
<wvobject type="logic" fp_name="/sim_from_dump/dmem_usgn_dat_o">
<obj_property name="ElementShortName">dmem_usgn_dat_o</obj_property>
<obj_property name="ObjectShortName">dmem_usgn_dat_o</obj_property>
</wvobject>
<wvobject type="array" fp_name="/sim_from_dump/dmem_data_o">
<obj_property name="ElementShortName">dmem_data_o[31:0]</obj_property>
<obj_property name="ObjectShortName">dmem_data_o[31:0]</obj_property>
</wvobject>
<wvobject type="array" fp_name="/sim_from_dump/dmem_addr_o">
<obj_property name="ElementShortName">dmem_addr_o[31:0]</obj_property>
<obj_property name="ObjectShortName">dmem_addr_o[31:0]</obj_property>
<obj_property name="Radix">HEXRADIX</obj_property>
</wvobject>
</wvobject>
<wvobject type="array" fp_name="/sim_from_dump/data_mem">
<obj_property name="ElementShortName">data_mem[12287:8192][7:0]</obj_property>
<obj_property name="ObjectShortName">data_mem[12287:8192][7:0]</obj_property>
</wvobject>
<wvobject type="array" fp_name="/sim_from_dump/inst_mem">
<obj_property name="ElementShortName">inst_mem[4095:0][7:0]</obj_property>
<obj_property name="ObjectShortName">inst_mem[4095:0][7:0]</obj_property>
</wvobject>
<wvobject type="other" fp_name="/sim_from_dump/INST_BASE_ADDR">
<obj_property name="ElementShortName">INST_BASE_ADDR</obj_property>
<obj_property name="ObjectShortName">INST_BASE_ADDR</obj_property>
</wvobject>
<wvobject type="other" fp_name="/sim_from_dump/INST_SIZE">
<obj_property name="ElementShortName">INST_SIZE</obj_property>
<obj_property name="ObjectShortName">INST_SIZE</obj_property>
</wvobject>
<wvobject type="other" fp_name="/sim_from_dump/DATA_BASE_ADDR">
<obj_property name="ElementShortName">DATA_BASE_ADDR</obj_property>
<obj_property name="ObjectShortName">DATA_BASE_ADDR</obj_property>
</wvobject>
<wvobject type="other" fp_name="/sim_from_dump/DATA_SIZE">
<obj_property name="ElementShortName">DATA_SIZE</obj_property>
<obj_property name="ObjectShortName">DATA_SIZE</obj_property>
</wvobject>
</wave_config>