1 |
5 |
sergeykhbr |
-----------------------------------------------------------------------------
|
2 |
|
|
--! @file
|
3 |
|
|
--! @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
|
4 |
|
|
--! @author Sergey Khabarov - sergeykhbr@gmail.com
|
5 |
|
|
--! @brief CPU Instruction Execution stage.
|
6 |
|
|
------------------------------------------------------------------------------
|
7 |
|
|
|
8 |
|
|
library ieee;
|
9 |
|
|
use ieee.std_logic_1164.all;
|
10 |
|
|
use IEEE.std_logic_arith.all; -- UNSIGNED function
|
11 |
|
|
library commonlib;
|
12 |
|
|
use commonlib.types_common.all;
|
13 |
|
|
--! RIVER CPU specific library.
|
14 |
|
|
library riverlib;
|
15 |
|
|
--! RIVER CPU configuration constants.
|
16 |
|
|
use riverlib.river_cfg.all;
|
17 |
|
|
|
18 |
|
|
|
19 |
|
|
entity InstrExecute is
|
20 |
|
|
port (
|
21 |
|
|
i_clk : in std_logic;
|
22 |
|
|
i_nrst : in std_logic; -- Reset active LOW
|
23 |
|
|
i_pipeline_hold : in std_logic; -- Hold execution by any reason
|
24 |
|
|
i_d_valid : in std_logic; -- Decoded instruction is valid
|
25 |
|
|
i_d_pc : in std_logic_vector(BUS_ADDR_WIDTH-1 downto 0); -- Instruction pointer on decoded instruction
|
26 |
|
|
i_d_instr : in std_logic_vector(31 downto 0); -- Decoded instruction value
|
27 |
|
|
i_wb_done : in std_logic; -- write back done (Used to clear hazardness)
|
28 |
|
|
i_memop_store : in std_logic; -- Store to memory operation
|
29 |
|
|
i_memop_load : in std_logic; -- Load from memoru operation
|
30 |
|
|
i_memop_sign_ext : in std_logic; -- Load memory value with sign extending
|
31 |
|
|
i_memop_size : in std_logic_vector(1 downto 0); -- Memory transaction size
|
32 |
|
|
i_unsigned_op : in std_logic; -- Unsigned operands
|
33 |
|
|
i_rv32 : in std_logic; -- 32-bits instruction
|
34 |
|
|
i_compressed : in std_logic; -- C-extension (2-bytes length)
|
35 |
|
|
i_isa_type : in std_logic_vector(ISA_Total-1 downto 0); -- Type of the instruction's structure (ISA spec.)
|
36 |
|
|
i_ivec : in std_logic_vector(Instr_Total-1 downto 0); -- One pulse per supported instruction.
|
37 |
|
|
i_ie : in std_logic; -- Interrupt enable bit
|
38 |
|
|
i_mtvec : in std_logic_vector(BUS_ADDR_WIDTH-1 downto 0); -- Interrupt descriptor table
|
39 |
|
|
i_mode : in std_logic_vector(1 downto 0); -- Current processor mode
|
40 |
|
|
i_break_mode : in std_logic; -- Behaviour on EBREAK instruction: 0 = halt; 1 = generate trap
|
41 |
|
|
i_unsup_exception : in std_logic; -- Unsupported instruction exception
|
42 |
|
|
i_ext_irq : in std_logic; -- External interrupt from PLIC (todo: timer & software interrupts)
|
43 |
|
|
i_dport_npc_write : in std_logic; -- Write npc value from debug port
|
44 |
|
|
i_dport_npc : in std_logic_vector(BUS_ADDR_WIDTH-1 downto 0);-- Debug port npc value to write
|
45 |
|
|
|
46 |
|
|
o_radr1 : out std_logic_vector(4 downto 0); -- Integer register index 1
|
47 |
|
|
i_rdata1 : in std_logic_vector(RISCV_ARCH-1 downto 0); -- Integer register value 1
|
48 |
|
|
o_radr2 : out std_logic_vector(4 downto 0); -- Integer register index 2
|
49 |
|
|
i_rdata2 : in std_logic_vector(RISCV_ARCH-1 downto 0); -- Integer register value 2
|
50 |
|
|
o_res_addr : out std_logic_vector(4 downto 0); -- Address to store result of the instruction (0=do not store)
|
51 |
|
|
o_res_data : out std_logic_vector(RISCV_ARCH-1 downto 0); -- Value to store
|
52 |
|
|
o_pipeline_hold : out std_logic; -- Hold pipeline while 'writeback' not done or multi-clock instruction.
|
53 |
|
|
o_xret : out std_logic; -- XRET instruction: MRET, URET or other.
|
54 |
|
|
o_csr_addr : out std_logic_vector(11 downto 0); -- CSR address. 0 if not a CSR instruction with xret signals mode switching
|
55 |
|
|
o_csr_wena : out std_logic; -- Write new CSR value
|
56 |
|
|
i_csr_rdata : in std_logic_vector(RISCV_ARCH-1 downto 0); -- CSR current value
|
57 |
|
|
o_csr_wdata : out std_logic_vector(RISCV_ARCH-1 downto 0); -- CSR new value
|
58 |
|
|
o_trap_ena : out std_logic; -- Trap occurs pulse
|
59 |
|
|
o_trap_code : out std_logic_vector(4 downto 0); -- bit[4] : 1=interrupt; 0=exception; bits[3:0]=code
|
60 |
|
|
o_trap_pc : out std_logic_vector(BUS_ADDR_WIDTH-1 downto 0);-- trap on pc
|
61 |
|
|
|
62 |
|
|
o_memop_sign_ext : out std_logic; -- Load data with sign extending
|
63 |
|
|
o_memop_load : out std_logic; -- Load data instruction
|
64 |
|
|
o_memop_store : out std_logic; -- Store data instruction
|
65 |
|
|
o_memop_size : out std_logic_vector(1 downto 0); -- 0=1bytes; 1=2bytes; 2=4bytes; 3=8bytes
|
66 |
|
|
o_memop_addr : out std_logic_vector(BUS_ADDR_WIDTH-1 downto 0);-- Memory access address
|
67 |
|
|
|
68 |
|
|
o_valid : out std_logic; -- Output is valid
|
69 |
|
|
o_pc : out std_logic_vector(BUS_ADDR_WIDTH-1 downto 0); -- Valid instruction pointer
|
70 |
|
|
o_npc : out std_logic_vector(BUS_ADDR_WIDTH-1 downto 0); -- Next instruction pointer. Next decoded pc must match to this value or will be ignored.
|
71 |
|
|
o_instr : out std_logic_vector(31 downto 0); -- Valid instruction value
|
72 |
|
|
o_breakpoint : out std_logic; -- ebreak instruction
|
73 |
|
|
o_call : out std_logic; -- CALL pseudo instruction detected
|
74 |
|
|
o_ret : out std_logic -- RET pseudoinstruction detected
|
75 |
|
|
);
|
76 |
|
|
end;
|
77 |
|
|
|
78 |
|
|
architecture arch_InstrExecute of InstrExecute is
|
79 |
|
|
|
80 |
|
|
constant Multi_MUL : integer := 0;
|
81 |
|
|
constant Multi_DIV : integer := 1;
|
82 |
|
|
constant Multi_Total : integer := 2;
|
83 |
|
|
constant zero64 : std_logic_vector(63 downto 0) := (others => '0');
|
84 |
|
|
|
85 |
|
|
type multi_arith_type is array (0 to Multi_Total-1)
|
86 |
|
|
of std_logic_vector(RISCV_ARCH-1 downto 0);
|
87 |
|
|
|
88 |
|
|
type RegistersType is record
|
89 |
|
|
d_valid : std_logic; -- Valid decoded instruction latch
|
90 |
|
|
pc : std_logic_vector(BUS_ADDR_WIDTH-1 downto 0);
|
91 |
|
|
npc : std_logic_vector(BUS_ADDR_WIDTH-1 downto 0);
|
92 |
|
|
instr : std_logic_vector(31 downto 0);
|
93 |
|
|
res_addr : std_logic_vector(4 downto 0);
|
94 |
|
|
res_val : std_logic_vector(RISCV_ARCH-1 downto 0);
|
95 |
|
|
memop_load : std_logic;
|
96 |
|
|
memop_store : std_logic;
|
97 |
|
|
memop_sign_ext : std_logic;
|
98 |
|
|
memop_size : std_logic_vector(1 downto 0);
|
99 |
|
|
memop_addr : std_logic_vector(BUS_ADDR_WIDTH-1 downto 0);
|
100 |
|
|
|
101 |
|
|
multi_res_addr : std_logic_vector(4 downto 0); -- latched output reg. address while multi-cycle instruction
|
102 |
|
|
multi_pc : std_logic_vector(BUS_ADDR_WIDTH-1 downto 0);-- latched pc-value while multi-cycle instruction
|
103 |
|
|
multi_npc : std_logic_vector(BUS_ADDR_WIDTH-1 downto 0);-- latched npc-value while multi-cycle instruction
|
104 |
|
|
multi_instr : std_logic_vector(31 downto 0); -- Multi-cycle instruction is under processing
|
105 |
|
|
multi_ena : std_logic_vector(Multi_Total-1 downto 0); -- Enable pulse for Operation that takes more than 1 clock
|
106 |
|
|
multi_rv32 : std_logic; -- Long operation with 32-bits operands
|
107 |
|
|
multi_unsigned : std_logic; -- Long operation with unsiged operands
|
108 |
|
|
multi_residual_high : std_logic; -- Flag for Divider module: 0=divsion output; 1=residual output
|
109 |
|
|
-- Flag for multiplier: 0=usual; 1=get high bits
|
110 |
|
|
multiclock_ena : std_logic;
|
111 |
|
|
multi_a1 : std_logic_vector(RISCV_ARCH-1 downto 0); -- Multi-cycle operand 1
|
112 |
|
|
multi_a2 : std_logic_vector(RISCV_ARCH-1 downto 0); -- Multi-cycle operand 2
|
113 |
|
|
|
114 |
|
|
hazard_addr0 : std_logic_vector(4 downto 0); -- Updated register address on previous step
|
115 |
|
|
hazard_addr1 : std_logic_vector(4 downto 0); -- Updated register address on pre-previous step
|
116 |
|
|
hazard_depth : std_logic_vector(1 downto 0); -- Number of modificated registers that wasn't done yet
|
117 |
|
|
|
118 |
|
|
ext_irq_pulser : std_logic; -- Form 1 clock pulse from strob
|
119 |
|
|
trap_ena : std_logic; -- Trap occur, switch mode
|
120 |
|
|
breakpoint : std_logic;
|
121 |
|
|
trap_code_waiting : std_logic_vector(4 downto 0); -- To avoid multi-cycle instruction collision
|
122 |
|
|
trap_code : std_logic_vector(4 downto 0); -- bit[4] : 1 = interrupt; 0 = exception
|
123 |
|
|
-- bit[3:0] : trap code
|
124 |
|
|
trap_pc : std_logic_vector(BUS_ADDR_WIDTH-1 downto 0); -- pc that caused a trap
|
125 |
|
|
call : std_logic;
|
126 |
|
|
ret : std_logic;
|
127 |
|
|
end record;
|
128 |
|
|
|
129 |
|
|
signal r, rin : RegistersType;
|
130 |
|
|
|
131 |
|
|
signal wb_arith_res : multi_arith_type;
|
132 |
|
|
signal w_arith_valid : std_logic_vector(Multi_Total-1 downto 0);
|
133 |
|
|
signal w_arith_busy : std_logic_vector(Multi_Total-1 downto 0);
|
134 |
|
|
signal w_hazard_detected : std_logic;
|
135 |
|
|
|
136 |
|
|
signal wb_shifter_a1 : std_logic_vector(RISCV_ARCH-1 downto 0); -- Shifters operand 1
|
137 |
|
|
signal wb_shifter_a2 : std_logic_vector(5 downto 0); -- Shifters operand 2
|
138 |
|
|
signal wb_sll : std_logic_vector(RISCV_ARCH-1 downto 0);
|
139 |
|
|
signal wb_sllw : std_logic_vector(RISCV_ARCH-1 downto 0);
|
140 |
|
|
signal wb_srl : std_logic_vector(RISCV_ARCH-1 downto 0);
|
141 |
|
|
signal wb_srlw : std_logic_vector(RISCV_ARCH-1 downto 0);
|
142 |
|
|
signal wb_sra : std_logic_vector(RISCV_ARCH-1 downto 0);
|
143 |
|
|
signal wb_sraw : std_logic_vector(RISCV_ARCH-1 downto 0);
|
144 |
|
|
|
145 |
|
|
component IntMul is port (
|
146 |
|
|
i_clk : in std_logic;
|
147 |
|
|
i_nrst : in std_logic;
|
148 |
|
|
i_ena : in std_logic;
|
149 |
|
|
i_unsigned : in std_logic;
|
150 |
|
|
i_high : in std_logic;
|
151 |
|
|
i_rv32 : in std_logic;
|
152 |
|
|
i_a1 : in std_logic_vector(RISCV_ARCH-1 downto 0);
|
153 |
|
|
i_a2 : in std_logic_vector(RISCV_ARCH-1 downto 0);
|
154 |
|
|
o_res : out std_logic_vector(RISCV_ARCH-1 downto 0);
|
155 |
|
|
o_valid : out std_logic;
|
156 |
|
|
o_busy : out std_logic
|
157 |
|
|
);
|
158 |
|
|
end component;
|
159 |
|
|
|
160 |
|
|
component IntDiv is port (
|
161 |
|
|
i_clk : in std_logic;
|
162 |
|
|
i_nrst : in std_logic;
|
163 |
|
|
i_ena : in std_logic;
|
164 |
|
|
i_unsigned : in std_logic;
|
165 |
|
|
i_rv32 : in std_logic;
|
166 |
|
|
i_residual : in std_logic;
|
167 |
|
|
i_a1 : in std_logic_vector(RISCV_ARCH-1 downto 0);
|
168 |
|
|
i_a2 : in std_logic_vector(RISCV_ARCH-1 downto 0);
|
169 |
|
|
o_res : out std_logic_vector(RISCV_ARCH-1 downto 0);
|
170 |
|
|
o_valid : out std_logic;
|
171 |
|
|
o_busy : out std_logic
|
172 |
|
|
);
|
173 |
|
|
end component;
|
174 |
|
|
|
175 |
|
|
component Shifter is port (
|
176 |
|
|
i_a1 : in std_logic_vector(RISCV_ARCH-1 downto 0);
|
177 |
|
|
i_a2 : in std_logic_vector(5 downto 0);
|
178 |
|
|
o_sll : out std_logic_vector(RISCV_ARCH-1 downto 0);
|
179 |
|
|
o_sllw : out std_logic_vector(RISCV_ARCH-1 downto 0);
|
180 |
|
|
o_srl : out std_logic_vector(RISCV_ARCH-1 downto 0);
|
181 |
|
|
o_sra : out std_logic_vector(RISCV_ARCH-1 downto 0);
|
182 |
|
|
o_srlw : out std_logic_vector(RISCV_ARCH-1 downto 0);
|
183 |
|
|
o_sraw : out std_logic_vector(RISCV_ARCH-1 downto 0)
|
184 |
|
|
);
|
185 |
|
|
end component;
|
186 |
|
|
|
187 |
|
|
begin
|
188 |
|
|
|
189 |
|
|
mul0 : IntMul port map (
|
190 |
|
|
i_clk => i_clk,
|
191 |
|
|
i_nrst => i_nrst,
|
192 |
|
|
i_ena => r.multi_ena(Multi_MUL),
|
193 |
|
|
i_unsigned => r.multi_unsigned,
|
194 |
|
|
i_high => r.multi_residual_high,
|
195 |
|
|
i_rv32 => r.multi_rv32,
|
196 |
|
|
i_a1 => r.multi_a1,
|
197 |
|
|
i_a2 => r.multi_a2,
|
198 |
|
|
o_res => wb_arith_res(Multi_MUL),
|
199 |
|
|
o_valid => w_arith_valid(Multi_MUL),
|
200 |
|
|
o_busy => w_arith_busy(Multi_MUL));
|
201 |
|
|
|
202 |
|
|
div0 : IntDiv port map (
|
203 |
|
|
i_clk => i_clk,
|
204 |
|
|
i_nrst => i_nrst,
|
205 |
|
|
i_ena => r.multi_ena(Multi_DIV),
|
206 |
|
|
i_unsigned => r.multi_unsigned,
|
207 |
|
|
i_residual => r.multi_residual_high,
|
208 |
|
|
i_rv32 => r.multi_rv32,
|
209 |
|
|
i_a1 => r.multi_a1,
|
210 |
|
|
i_a2 => r.multi_a2,
|
211 |
|
|
o_res => wb_arith_res(Multi_DIV),
|
212 |
|
|
o_valid => w_arith_valid(Multi_DIV),
|
213 |
|
|
o_busy => w_arith_busy(Multi_DIV));
|
214 |
|
|
|
215 |
|
|
sh0 : Shifter port map (
|
216 |
|
|
i_a1 => wb_shifter_a1,
|
217 |
|
|
i_a2 => wb_shifter_a2,
|
218 |
|
|
o_sll => wb_sll,
|
219 |
|
|
o_sllw => wb_sllw,
|
220 |
|
|
o_srl => wb_srl,
|
221 |
|
|
o_sra => wb_sra,
|
222 |
|
|
o_srlw => wb_srlw,
|
223 |
|
|
o_sraw => wb_sraw);
|
224 |
|
|
|
225 |
|
|
comb : process(i_nrst, i_pipeline_hold, i_d_valid, i_d_pc, i_d_instr,
|
226 |
|
|
i_wb_done, i_memop_load, i_memop_store, i_memop_sign_ext,
|
227 |
|
|
i_memop_size, i_unsigned_op, i_rv32, i_compressed, i_isa_type, i_ivec,
|
228 |
|
|
i_rdata1, i_rdata2, i_csr_rdata, i_ext_irq, i_dport_npc_write,
|
229 |
|
|
i_dport_npc, i_ie, i_mtvec, i_mode, i_break_mode, i_unsup_exception,
|
230 |
|
|
wb_arith_res, w_arith_valid, w_arith_busy, w_hazard_detected,
|
231 |
|
|
wb_sll, wb_sllw, wb_srl, wb_srlw, wb_sra, wb_sraw, r)
|
232 |
|
|
variable v : RegistersType;
|
233 |
|
|
variable w_interrupt : std_logic;
|
234 |
|
|
variable w_exception : std_logic;
|
235 |
|
|
variable w_exception_store : std_logic;
|
236 |
|
|
variable w_exception_load : std_logic;
|
237 |
|
|
variable w_exception_xret : std_logic;
|
238 |
|
|
variable wb_exception_code : std_logic_vector(4 downto 0);
|
239 |
|
|
variable wb_radr1 : std_logic_vector(4 downto 0);
|
240 |
|
|
variable wb_rdata1 : std_logic_vector(RISCV_ARCH-1 downto 0);
|
241 |
|
|
variable wb_radr2 : std_logic_vector(4 downto 0);
|
242 |
|
|
variable wb_rdata2 : std_logic_vector(RISCV_ARCH-1 downto 0);
|
243 |
|
|
variable w_xret : std_logic;
|
244 |
|
|
variable w_csr_wena : std_logic;
|
245 |
|
|
variable wb_res_addr : std_logic_vector(4 downto 0);
|
246 |
|
|
variable wb_csr_addr : std_logic_vector(11 downto 0);
|
247 |
|
|
variable wb_csr_wdata : std_logic_vector(RISCV_ARCH-1 downto 0);
|
248 |
|
|
variable wb_res : std_logic_vector(RISCV_ARCH-1 downto 0);
|
249 |
|
|
variable wb_npc : std_logic_vector(BUS_ADDR_WIDTH-1 downto 0);
|
250 |
|
|
variable wb_off : std_logic_vector(RISCV_ARCH-1 downto 0);
|
251 |
|
|
variable wb_mask_i31 : std_logic_vector(RISCV_ARCH-1 downto 0); -- Bits depending instr[31] bits
|
252 |
|
|
variable wb_sum64 : std_logic_vector(RISCV_ARCH-1 downto 0);
|
253 |
|
|
variable wb_sum32 : std_logic_vector(RISCV_ARCH-1 downto 0);
|
254 |
|
|
variable wb_sub64 : std_logic_vector(RISCV_ARCH-1 downto 0);
|
255 |
|
|
variable wb_sub32 : std_logic_vector(RISCV_ARCH-1 downto 0);
|
256 |
|
|
variable wb_and64 : std_logic_vector(RISCV_ARCH-1 downto 0);
|
257 |
|
|
variable wb_or64 : std_logic_vector(RISCV_ARCH-1 downto 0);
|
258 |
|
|
variable wb_xor64 : std_logic_vector(RISCV_ARCH-1 downto 0);
|
259 |
|
|
variable w_memop_load : std_logic;
|
260 |
|
|
variable w_memop_store : std_logic;
|
261 |
|
|
variable w_memop_sign_ext : std_logic;
|
262 |
|
|
variable wb_memop_size : std_logic_vector(1 downto 0);
|
263 |
|
|
variable wb_memop_addr : std_logic_vector(BUS_ADDR_WIDTH-1 downto 0);
|
264 |
|
|
|
265 |
|
|
variable w_pc_valid : std_logic;
|
266 |
|
|
variable w_d_acceptable : std_logic;
|
267 |
|
|
variable w_multi_valid : std_logic;
|
268 |
|
|
variable w_multi_ena : std_logic;
|
269 |
|
|
variable w_res_wena : std_logic;
|
270 |
|
|
variable w_pc_branch : std_logic;
|
271 |
|
|
variable w_hazard_lvl1 : std_logic;
|
272 |
|
|
variable w_hazard_lvl2 : std_logic;
|
273 |
|
|
variable w_d_valid : std_logic;
|
274 |
|
|
variable w_o_valid : std_logic;
|
275 |
|
|
variable w_o_pipeline_hold : std_logic;
|
276 |
|
|
variable w_less : std_logic;
|
277 |
|
|
variable w_gr_equal : std_logic;
|
278 |
|
|
variable wv : std_logic_vector(Instr_Total-1 downto 0);
|
279 |
|
|
variable opcode_len : integer;
|
280 |
|
|
|
281 |
|
|
begin
|
282 |
|
|
|
283 |
|
|
wb_radr1 := (others => '0');
|
284 |
|
|
wb_radr2 := (others => '0');
|
285 |
|
|
w_xret := '0';
|
286 |
|
|
w_csr_wena := '0';
|
287 |
|
|
wb_res_addr := (others => '0');
|
288 |
|
|
wb_csr_addr := (others => '0');
|
289 |
|
|
wb_csr_wdata := (others => '0');
|
290 |
|
|
wb_res := (others => '0');
|
291 |
|
|
wb_off := (others => '0');
|
292 |
|
|
wb_rdata1 := (others => '0');
|
293 |
|
|
wb_rdata2 := (others => '0');
|
294 |
|
|
w_memop_load := '0';
|
295 |
|
|
w_memop_store := '0';
|
296 |
|
|
w_memop_sign_ext := '0';
|
297 |
|
|
wb_memop_size := (others => '0');
|
298 |
|
|
wb_memop_addr := (others => '0');
|
299 |
|
|
wv := i_ivec;
|
300 |
|
|
|
301 |
|
|
v := r;
|
302 |
|
|
v.breakpoint := '0';
|
303 |
|
|
|
304 |
|
|
wb_mask_i31 := (others => i_d_instr(31));
|
305 |
|
|
|
306 |
|
|
w_pc_valid := '0';
|
307 |
|
|
if i_d_pc = r.npc then
|
308 |
|
|
w_pc_valid := '1';
|
309 |
|
|
end if;
|
310 |
|
|
w_d_acceptable := not i_pipeline_hold and i_d_valid
|
311 |
|
|
and w_pc_valid and not r.multiclock_ena;
|
312 |
|
|
|
313 |
|
|
v.ext_irq_pulser := i_ext_irq and i_ie;
|
314 |
|
|
w_interrupt := '0';
|
315 |
|
|
if w_d_acceptable = '1' and (r.trap_code_waiting /= "00000") then
|
316 |
|
|
w_interrupt := '1';
|
317 |
|
|
end if;
|
318 |
|
|
|
319 |
|
|
if i_isa_type(ISA_R_type) = '1' then
|
320 |
|
|
wb_radr1 := i_d_instr(19 downto 15);
|
321 |
|
|
wb_rdata1 := i_rdata1;
|
322 |
|
|
wb_radr2 := i_d_instr(24 downto 20);
|
323 |
|
|
wb_rdata2 := i_rdata2;
|
324 |
|
|
elsif i_isa_type(ISA_I_type) = '1' then
|
325 |
|
|
wb_radr1 := i_d_instr(19 downto 15);
|
326 |
|
|
wb_rdata1 := i_rdata1;
|
327 |
|
|
wb_radr2 := (others => '0');
|
328 |
|
|
wb_rdata2 := wb_mask_i31(63 downto 12) & i_d_instr(31 downto 20);
|
329 |
|
|
elsif i_isa_type(ISA_SB_type) = '1' then
|
330 |
|
|
wb_radr1 := i_d_instr(19 downto 15);
|
331 |
|
|
wb_rdata1 := i_rdata1;
|
332 |
|
|
wb_radr2 := i_d_instr(24 downto 20);
|
333 |
|
|
wb_rdata2 := i_rdata2;
|
334 |
|
|
wb_off(RISCV_ARCH-1 downto 12) := wb_mask_i31(RISCV_ARCH-1 downto 12);
|
335 |
|
|
wb_off(12) := i_d_instr(31);
|
336 |
|
|
wb_off(11) := i_d_instr(7);
|
337 |
|
|
wb_off(10 downto 5) := i_d_instr(30 downto 25);
|
338 |
|
|
wb_off(4 downto 1) := i_d_instr(11 downto 8);
|
339 |
|
|
wb_off(0) := '0';
|
340 |
|
|
elsif i_isa_type(ISA_UJ_type) = '1' then
|
341 |
|
|
wb_radr1 := (others => '0');
|
342 |
|
|
wb_rdata1 := X"00000000" & i_d_pc;
|
343 |
|
|
wb_radr2 := (others => '0');
|
344 |
|
|
wb_off(RISCV_ARCH-1 downto 20) := wb_mask_i31(RISCV_ARCH-1 downto 20);
|
345 |
|
|
wb_off(19 downto 12) := i_d_instr(19 downto 12);
|
346 |
|
|
wb_off(11) := i_d_instr(20);
|
347 |
|
|
wb_off(10 downto 1) := i_d_instr(30 downto 21);
|
348 |
|
|
wb_off(0) := '0';
|
349 |
|
|
elsif i_isa_type(ISA_U_type) = '1'then
|
350 |
|
|
wb_radr1 := (others => '0');
|
351 |
|
|
wb_rdata1 := X"00000000" & i_d_pc;
|
352 |
|
|
wb_radr2 := (others => '0');
|
353 |
|
|
wb_rdata2(31 downto 0) := i_d_instr(31 downto 12) & X"000";
|
354 |
|
|
wb_rdata2(RISCV_ARCH-1 downto 32) := wb_mask_i31(RISCV_ARCH-1 downto 32);
|
355 |
|
|
elsif i_isa_type(ISA_S_type) = '1' then
|
356 |
|
|
wb_radr1 := i_d_instr(19 downto 15);
|
357 |
|
|
wb_rdata1 := i_rdata1;
|
358 |
|
|
wb_radr2 := i_d_instr(24 downto 20);
|
359 |
|
|
wb_rdata2 := i_rdata2;
|
360 |
|
|
wb_off(RISCV_ARCH-1 downto 12) := wb_mask_i31(RISCV_ARCH-1 downto 12);
|
361 |
|
|
wb_off(11 downto 5) := i_d_instr(31 downto 25);
|
362 |
|
|
wb_off(4 downto 0) := i_d_instr(11 downto 7);
|
363 |
|
|
end if;
|
364 |
|
|
|
365 |
|
|
-- parallel ALU:
|
366 |
|
|
wb_sum64 := wb_rdata1 + wb_rdata2;
|
367 |
|
|
wb_sum32(31 downto 0) := wb_rdata1(31 downto 0) + wb_rdata2(31 downto 0);
|
368 |
|
|
wb_sum32(63 downto 32) := (others => wb_sum32(31));
|
369 |
|
|
wb_sub64 := wb_rdata1 - wb_rdata2;
|
370 |
|
|
wb_sub32(31 downto 0) := wb_rdata1(31 downto 0) - wb_rdata2(31 downto 0);
|
371 |
|
|
wb_sub32(63 downto 32) := (others => wb_sub32(31));
|
372 |
|
|
wb_and64 := wb_rdata1 and wb_rdata2;
|
373 |
|
|
wb_or64 := wb_rdata1 or wb_rdata2;
|
374 |
|
|
wb_xor64 := wb_rdata1 xor wb_rdata2;
|
375 |
|
|
|
376 |
|
|
wb_shifter_a1 <= wb_rdata1;
|
377 |
|
|
wb_shifter_a2 <= wb_rdata2(5 downto 0);
|
378 |
|
|
|
379 |
|
|
w_multi_valid := w_arith_valid(Multi_MUL) or w_arith_valid(Multi_DIV);
|
380 |
|
|
|
381 |
|
|
-- Don't modify registers on conditional jumps:
|
382 |
|
|
w_res_wena := not (wv(Instr_BEQ) or wv(Instr_BGE) or wv(Instr_BGEU)
|
383 |
|
|
or wv(Instr_BLT) or wv(Instr_BLTU) or wv(Instr_BNE)
|
384 |
|
|
or wv(Instr_SD) or wv(Instr_SW) or wv(Instr_SH) or wv(Instr_SB)
|
385 |
|
|
or wv(Instr_MRET) or wv(Instr_URET)
|
386 |
|
|
or wv(Instr_ECALL) or wv(Instr_EBREAK));
|
387 |
|
|
|
388 |
|
|
if w_multi_valid = '1' then
|
389 |
|
|
wb_res_addr := r.multi_res_addr;
|
390 |
|
|
v.multiclock_ena := '0';
|
391 |
|
|
elsif w_res_wena = '1' then
|
392 |
|
|
wb_res_addr := i_d_instr(11 downto 7);
|
393 |
|
|
else
|
394 |
|
|
wb_res_addr := (others => '0');
|
395 |
|
|
end if;
|
396 |
|
|
w_less := '0';
|
397 |
|
|
w_gr_equal := '0';
|
398 |
|
|
if UNSIGNED(wb_rdata1) < UNSIGNED(wb_rdata2) then
|
399 |
|
|
w_less := '1';
|
400 |
|
|
end if;
|
401 |
|
|
if UNSIGNED(wb_rdata1) >= UNSIGNED(wb_rdata2) then
|
402 |
|
|
w_gr_equal := '1';
|
403 |
|
|
end if;
|
404 |
|
|
|
405 |
|
|
-- Relative Branch on some condition:
|
406 |
|
|
w_pc_branch := '0';
|
407 |
|
|
if ((wv(Instr_BEQ) = '1' and (wb_sub64 = zero64))
|
408 |
|
|
or (wv(Instr_BGE) = '1' and (wb_sub64(63) = '0'))
|
409 |
|
|
or (wv(Instr_BGEU) = '1' and (w_gr_equal = '1'))
|
410 |
|
|
or (wv(Instr_BLT) = '1' and (wb_sub64(63) = '1'))
|
411 |
|
|
or (wv(Instr_BLTU) = '1' and (w_less = '1'))
|
412 |
|
|
or (wv(Instr_BNE) = '1' and (wb_sub64 /= zero64))) then
|
413 |
|
|
w_pc_branch := '1';
|
414 |
|
|
end if;
|
415 |
|
|
|
416 |
|
|
opcode_len := 4;
|
417 |
|
|
if i_compressed = '1' then
|
418 |
|
|
opcode_len := 2;
|
419 |
|
|
end if;
|
420 |
|
|
|
421 |
|
|
if w_pc_branch = '1' then
|
422 |
|
|
wb_npc := i_d_pc + wb_off(BUS_ADDR_WIDTH-1 downto 0);
|
423 |
|
|
elsif wv(Instr_JAL) = '1' then
|
424 |
|
|
wb_res(63 downto 32) := (others => '0');
|
425 |
|
|
wb_res(31 downto 0) := i_d_pc + opcode_len;
|
426 |
|
|
wb_npc := wb_rdata1(BUS_ADDR_WIDTH-1 downto 0) + wb_off(BUS_ADDR_WIDTH-1 downto 0);
|
427 |
|
|
elsif wv(Instr_JALR) = '1' then
|
428 |
|
|
wb_res(63 downto 32) := (others => '0');
|
429 |
|
|
wb_res(31 downto 0) := i_d_pc + opcode_len;
|
430 |
|
|
wb_npc := wb_rdata1(BUS_ADDR_WIDTH-1 downto 0) + wb_rdata2(BUS_ADDR_WIDTH-1 downto 0);
|
431 |
|
|
wb_npc(0) := '0';
|
432 |
|
|
elsif wv(Instr_MRET) = '1' or wv(Instr_URET) = '1' then
|
433 |
|
|
wb_res(63 downto 32) := (others => '0');
|
434 |
|
|
wb_res(31 downto 0) := i_d_pc + opcode_len;
|
435 |
|
|
w_xret := i_d_valid and w_pc_valid;
|
436 |
|
|
w_csr_wena := '0';
|
437 |
|
|
if wv(Instr_URET) = '1' then
|
438 |
|
|
wb_csr_addr := CSR_uepc;
|
439 |
|
|
else
|
440 |
|
|
wb_csr_addr := CSR_mepc;
|
441 |
|
|
end if;
|
442 |
|
|
wb_npc := i_csr_rdata(BUS_ADDR_WIDTH-1 downto 0);
|
443 |
|
|
else
|
444 |
|
|
-- Instr_HRET, Instr_SRET, Instr_FENCE, Instr_FENCE_I:
|
445 |
|
|
wb_npc := i_d_pc + opcode_len;
|
446 |
|
|
end if;
|
447 |
|
|
|
448 |
|
|
if i_memop_load = '1' then
|
449 |
|
|
wb_memop_addr := wb_rdata1(BUS_ADDR_WIDTH-1 downto 0)
|
450 |
|
|
+ wb_rdata2(BUS_ADDR_WIDTH-1 downto 0);
|
451 |
|
|
elsif i_memop_store = '1' then
|
452 |
|
|
wb_memop_addr := wb_rdata1(BUS_ADDR_WIDTH-1 downto 0)
|
453 |
|
|
+ wb_off(BUS_ADDR_WIDTH-1 downto 0);
|
454 |
|
|
end if;
|
455 |
|
|
|
456 |
|
|
v.memop_addr := (others => '0');
|
457 |
|
|
v.memop_load := '0';
|
458 |
|
|
v.memop_store := '0';
|
459 |
|
|
v.memop_sign_ext := '0';
|
460 |
|
|
v.memop_size := (others => '0');
|
461 |
|
|
w_exception_store := '0';
|
462 |
|
|
w_exception_load := '0';
|
463 |
|
|
w_exception_xret := '0';
|
464 |
|
|
|
465 |
|
|
if ((wv(Instr_LD) = '1' and wb_memop_addr(2 downto 0) /= "000")
|
466 |
|
|
or ((wv(Instr_LW) or wv(Instr_LWU)) = '1' and wb_memop_addr(1 downto 0) /= "00")
|
467 |
|
|
or ((wv(Instr_LH) or wv(Instr_LHU)) = '1' and wb_memop_addr(0) /= '0')) then
|
468 |
|
|
w_exception_load := not w_hazard_detected;
|
469 |
|
|
end if;
|
470 |
|
|
if ((wv(Instr_SD) = '1' and wb_memop_addr(2 downto 0) /= "000")
|
471 |
|
|
or (wv(Instr_SW) = '1' and wb_memop_addr(1 downto 0) /= "00")
|
472 |
|
|
or (wv(Instr_SH) = '1' and wb_memop_addr(0) /= '0')) then
|
473 |
|
|
w_exception_store := not w_hazard_detected;
|
474 |
|
|
end if;
|
475 |
|
|
if (wv(Instr_MRET) = '1' and i_mode /= PRV_M)
|
476 |
|
|
or (wv(Instr_URET) = '1' and i_mode /= PRV_U) then
|
477 |
|
|
w_exception_xret := '1';
|
478 |
|
|
end if;
|
479 |
|
|
|
480 |
|
|
|
481 |
|
|
w_exception := w_d_acceptable
|
482 |
|
|
and ((i_unsup_exception and w_pc_valid) or w_exception_load
|
483 |
|
|
or w_exception_store or w_exception_xret
|
484 |
|
|
or wv(Instr_ECALL) or wv(Instr_EBREAK));
|
485 |
|
|
|
486 |
|
|
|
487 |
|
|
--! Default number of cycles per instruction = 0 (1 clock per instr)
|
488 |
|
|
--! If instruction is multicycle then modify this value.
|
489 |
|
|
--!
|
490 |
|
|
v.multi_ena := (others => '0');
|
491 |
|
|
v.multi_rv32 := i_rv32;
|
492 |
|
|
v.multi_unsigned := i_unsigned_op;
|
493 |
|
|
v.multi_residual_high := '0';
|
494 |
|
|
v.multi_a1 := i_rdata1;
|
495 |
|
|
v.multi_a2 := i_rdata2;
|
496 |
|
|
|
497 |
|
|
w_multi_ena := wv(Instr_MUL) or wv(Instr_MULW) or wv(Instr_DIV)
|
498 |
|
|
or wv(Instr_DIVU) or wv(Instr_DIVW) or wv(Instr_DIVUW)
|
499 |
|
|
or wv(Instr_REM) or wv(Instr_REMU) or wv(Instr_REMW)
|
500 |
|
|
or wv(Instr_REMUW);
|
501 |
|
|
if (w_multi_ena and w_d_acceptable and (not w_exception)
|
502 |
|
|
and (not w_interrupt)) = '1' then
|
503 |
|
|
v.multiclock_ena := '1';
|
504 |
|
|
v.multi_res_addr := wb_res_addr;
|
505 |
|
|
v.multi_pc := i_d_pc;
|
506 |
|
|
v.multi_instr := i_d_instr;
|
507 |
|
|
v.multi_npc := wb_npc;
|
508 |
|
|
end if;
|
509 |
|
|
|
510 |
|
|
|
511 |
|
|
-- ALU block selector:
|
512 |
|
|
if w_arith_valid(Multi_MUL) = '1' then
|
513 |
|
|
wb_res := wb_arith_res(Multi_MUL);
|
514 |
|
|
elsif w_arith_valid(Multi_DIV) = '1' then
|
515 |
|
|
wb_res := wb_arith_res(Multi_DIV);
|
516 |
|
|
elsif i_memop_load = '1' then
|
517 |
|
|
w_memop_load := not w_hazard_detected;
|
518 |
|
|
w_memop_sign_ext := i_memop_sign_ext;
|
519 |
|
|
wb_memop_size := i_memop_size;
|
520 |
|
|
elsif i_memop_store = '1' then
|
521 |
|
|
w_memop_store := not w_hazard_detected;
|
522 |
|
|
wb_memop_size := i_memop_size;
|
523 |
|
|
wb_res := wb_rdata2;
|
524 |
|
|
elsif (wv(Instr_ADD) or wv(Instr_ADDI) or wv(Instr_AUIPC)) = '1' then
|
525 |
|
|
wb_res := wb_sum64;
|
526 |
|
|
elsif (wv(Instr_ADDW) or wv(Instr_ADDIW)) = '1' then
|
527 |
|
|
wb_res := wb_sum32;
|
528 |
|
|
elsif wv(Instr_SUB) = '1' then
|
529 |
|
|
wb_res := wb_sub64;
|
530 |
|
|
elsif wv(Instr_SUBW) = '1' then
|
531 |
|
|
wb_res := wb_sub32;
|
532 |
|
|
elsif (wv(Instr_SLL) or wv(Instr_SLLI)) = '1' then
|
533 |
|
|
wb_res := wb_sll;
|
534 |
|
|
elsif (wv(Instr_SLLW) or wv(Instr_SLLIW)) = '1' then
|
535 |
|
|
wb_res := wb_sllw;
|
536 |
|
|
elsif (wv(Instr_SRL) or wv(Instr_SRLI)) = '1' then
|
537 |
|
|
wb_res := wb_srl;
|
538 |
|
|
elsif (wv(Instr_SRLW) or wv(Instr_SRLIW)) = '1' then
|
539 |
|
|
wb_res := wb_srlw;
|
540 |
|
|
elsif (wv(Instr_SRA) or wv(Instr_SRAI)) = '1' then
|
541 |
|
|
wb_res := wb_sra;
|
542 |
|
|
elsif (wv(Instr_SRAW) or wv(Instr_SRAW) or wv(Instr_SRAIW)) = '1' then
|
543 |
|
|
wb_res := wb_sraw;
|
544 |
|
|
elsif (wv(Instr_AND) or wv(Instr_ANDI)) = '1' then
|
545 |
|
|
wb_res := wb_and64;
|
546 |
|
|
elsif (wv(Instr_OR) or wv(Instr_ORI)) = '1' then
|
547 |
|
|
wb_res := wb_or64;
|
548 |
|
|
elsif (wv(Instr_XOR) or wv(Instr_XORI)) = '1' then
|
549 |
|
|
wb_res := wb_xor64;
|
550 |
|
|
elsif (wv(Instr_SLT) or wv(Instr_SLTI)) = '1' then
|
551 |
|
|
wb_res(RISCV_ARCH-1 downto 1) := (others => '0');
|
552 |
|
|
wb_res(0) := wb_sub64(63);
|
553 |
|
|
elsif (wv(Instr_SLTU) or wv(Instr_SLTIU)) = '1' then
|
554 |
|
|
wb_res(63 downto 1) := (others => '0');
|
555 |
|
|
wb_res(0) := w_less;
|
556 |
|
|
elsif wv(Instr_LUI) = '1' then
|
557 |
|
|
wb_res := wb_rdata2;
|
558 |
|
|
elsif (wv(Instr_MUL) or wv(Instr_MULW)) = '1' then
|
559 |
|
|
v.multi_ena(Multi_MUL) := w_d_acceptable and (not w_exception)
|
560 |
|
|
and (not w_interrupt);
|
561 |
|
|
elsif (wv(Instr_DIV) or wv(Instr_DIVU)
|
562 |
|
|
or wv(Instr_DIVW) or wv(Instr_DIVUW)) = '1' then
|
563 |
|
|
v.multi_ena(Multi_DIV) := w_d_acceptable and (not w_exception)
|
564 |
|
|
and (not w_interrupt);
|
565 |
|
|
elsif (wv(Instr_REM) or wv(Instr_REMU)
|
566 |
|
|
or wv(Instr_REMW) or wv(Instr_REMUW)) = '1' then
|
567 |
|
|
v.multi_ena(Multi_DIV) := w_d_acceptable and (not w_exception)
|
568 |
|
|
and (not w_interrupt);
|
569 |
|
|
v.multi_residual_high := '1';
|
570 |
|
|
elsif wv(Instr_CSRRC) = '1' then
|
571 |
|
|
wb_res := i_csr_rdata;
|
572 |
|
|
w_csr_wena := '1';
|
573 |
|
|
wb_csr_addr := wb_rdata2(11 downto 0);
|
574 |
|
|
wb_csr_wdata := i_csr_rdata and (not i_rdata1);
|
575 |
|
|
elsif wv(Instr_CSRRCI) = '1' then
|
576 |
|
|
wb_res := i_csr_rdata;
|
577 |
|
|
w_csr_wena := '1';
|
578 |
|
|
wb_csr_addr := wb_rdata2(11 downto 0);
|
579 |
|
|
wb_csr_wdata(RISCV_ARCH-1 downto 5) := i_csr_rdata(RISCV_ARCH-1 downto 5);
|
580 |
|
|
wb_csr_wdata(4 downto 0) := i_csr_rdata(4 downto 0) and not wb_radr1; -- zero-extending 5 to 64-bits
|
581 |
|
|
elsif wv(Instr_CSRRS) = '1' then
|
582 |
|
|
wb_res := i_csr_rdata;
|
583 |
|
|
w_csr_wena := '1';
|
584 |
|
|
wb_csr_addr := wb_rdata2(11 downto 0);
|
585 |
|
|
wb_csr_wdata := i_csr_rdata or i_rdata1;
|
586 |
|
|
elsif wv(Instr_CSRRSI) = '1' then
|
587 |
|
|
wb_res := i_csr_rdata;
|
588 |
|
|
w_csr_wena := '1';
|
589 |
|
|
wb_csr_addr := wb_rdata2(11 downto 0);
|
590 |
|
|
wb_csr_wdata(RISCV_ARCH-1 downto 5) := i_csr_rdata(RISCV_ARCH-1 downto 5);
|
591 |
|
|
wb_csr_wdata(4 downto 0) := i_csr_rdata(4 downto 0) or wb_radr1; -- zero-extending 5 to 64-bits
|
592 |
|
|
elsif wv(Instr_CSRRW) = '1' then
|
593 |
|
|
wb_res := i_csr_rdata;
|
594 |
|
|
w_csr_wena := '1';
|
595 |
|
|
wb_csr_addr := wb_rdata2(11 downto 0);
|
596 |
|
|
wb_csr_wdata := i_rdata1;
|
597 |
|
|
elsif wv(Instr_CSRRWI) = '1' then
|
598 |
|
|
wb_res := i_csr_rdata;
|
599 |
|
|
w_csr_wena := '1';
|
600 |
|
|
wb_csr_addr := wb_rdata2(11 downto 0);
|
601 |
|
|
wb_csr_wdata(RISCV_ARCH-1 downto 5) := (others => '0');
|
602 |
|
|
wb_csr_wdata(4 downto 0) := wb_radr1; -- zero-extending 5 to 64-bits
|
603 |
|
|
end if;
|
604 |
|
|
|
605 |
|
|
wb_exception_code := (others => '0');
|
606 |
|
|
if (i_ext_irq and i_ie and not r.ext_irq_pulser) = '1' then -- Maskable traps (interrupts)
|
607 |
|
|
v.trap_code_waiting(4) := '1';
|
608 |
|
|
-- INTERRUPT_MExternal - INTERRUPT_USoftware
|
609 |
|
|
v.trap_code_waiting(3 downto 0) := X"B";
|
610 |
|
|
elsif w_exception = '1' then -- Unmaskable traps (exceptions)
|
611 |
|
|
wb_exception_code(4) := '0';
|
612 |
|
|
if w_exception_load = '1' then
|
613 |
|
|
wb_exception_code(3 downto 0) := EXCEPTION_LoadMisalign;
|
614 |
|
|
elsif w_exception_store = '1' then
|
615 |
|
|
wb_exception_code(3 downto 0) := EXCEPTION_StoreMisalign;
|
616 |
|
|
elsif w_exception_xret = '1' then
|
617 |
|
|
wb_exception_code(3 downto 0) := EXCEPTION_InstrIllegal;
|
618 |
|
|
elsif wv(Instr_ECALL) = '1' then
|
619 |
|
|
if i_mode = PRV_M then
|
620 |
|
|
wb_exception_code(3 downto 0) := EXCEPTION_CallFromMmode;
|
621 |
|
|
else
|
622 |
|
|
wb_exception_code(3 downto 0) := EXCEPTION_CallFromUmode;
|
623 |
|
|
end if;
|
624 |
|
|
elsif wv(Instr_EBREAK) = '1' then
|
625 |
|
|
v.breakpoint := '1';
|
626 |
|
|
wb_exception_code(3 downto 0) := EXCEPTION_Breakpoint;
|
627 |
|
|
else
|
628 |
|
|
wb_exception_code(3 downto 0) := EXCEPTION_InstrIllegal;
|
629 |
|
|
end if;
|
630 |
|
|
elsif w_interrupt = '1' then
|
631 |
|
|
v.trap_code_waiting := (others => '0');
|
632 |
|
|
end if;
|
633 |
|
|
|
634 |
|
|
w_d_valid :=
|
635 |
|
|
(w_d_acceptable and (not w_interrupt) and (not w_exception)
|
636 |
|
|
and (not w_multi_ena)) or w_multi_valid;
|
637 |
|
|
|
638 |
|
|
|
639 |
|
|
v.trap_ena := '0';
|
640 |
|
|
v.call := '0';
|
641 |
|
|
v.ret := '0';
|
642 |
|
|
if i_dport_npc_write = '1' then
|
643 |
|
|
v.npc := i_dport_npc;
|
644 |
|
|
elsif w_interrupt = '1' then
|
645 |
|
|
v.trap_ena := '1';
|
646 |
|
|
v.trap_pc := i_d_pc;
|
647 |
|
|
v.trap_code := r.trap_code_waiting;
|
648 |
|
|
v.npc := i_mtvec;
|
649 |
|
|
elsif w_exception = '1' then
|
650 |
|
|
v.trap_ena := '1';
|
651 |
|
|
v.trap_pc := i_d_pc;
|
652 |
|
|
v.trap_code := wb_exception_code;
|
653 |
|
|
if wv(Instr_EBREAK) = '1' and i_break_mode = '0' then
|
654 |
|
|
v.npc := i_d_pc;
|
655 |
|
|
else
|
656 |
|
|
v.npc := i_mtvec;
|
657 |
|
|
end if;
|
658 |
|
|
elsif w_d_valid = '1' then
|
659 |
|
|
if w_multi_valid = '1' then
|
660 |
|
|
v.pc := r.multi_pc;
|
661 |
|
|
v.instr := r.multi_instr;
|
662 |
|
|
v.npc := r.multi_npc;
|
663 |
|
|
v.memop_load := '0';
|
664 |
|
|
v.memop_sign_ext := '0';
|
665 |
|
|
v.memop_store := '0';
|
666 |
|
|
v.memop_size := (others => '0');
|
667 |
|
|
v.memop_addr := (others => '0');
|
668 |
|
|
else
|
669 |
|
|
v.pc := i_d_pc;
|
670 |
|
|
v.instr := i_d_instr;
|
671 |
|
|
v.npc := wb_npc;
|
672 |
|
|
v.memop_load := w_memop_load;
|
673 |
|
|
v.memop_sign_ext := w_memop_sign_ext;
|
674 |
|
|
v.memop_store := w_memop_store;
|
675 |
|
|
v.memop_size := wb_memop_size;
|
676 |
|
|
v.memop_addr := wb_memop_addr;
|
677 |
|
|
end if;
|
678 |
|
|
v.res_addr := wb_res_addr;
|
679 |
|
|
v.res_val := wb_res;
|
680 |
|
|
|
681 |
|
|
v.hazard_addr1 := r.hazard_addr0;
|
682 |
|
|
v.hazard_addr0 := wb_res_addr;
|
683 |
|
|
|
684 |
|
|
if wv(Instr_JAL) = '1' and conv_integer(wb_res_addr) = Reg_ra then
|
685 |
|
|
v.call := '1';
|
686 |
|
|
end if;
|
687 |
|
|
if wv(Instr_JALR) = '1' then
|
688 |
|
|
if conv_integer(wb_res_addr) = Reg_ra then
|
689 |
|
|
v.call := '1';
|
690 |
|
|
elsif wb_rdata2 = zero64 and conv_integer(wb_radr1) = Reg_ra then
|
691 |
|
|
v.ret := '1';
|
692 |
|
|
end if;
|
693 |
|
|
end if;
|
694 |
|
|
end if;
|
695 |
|
|
|
696 |
|
|
v.d_valid := w_d_valid;
|
697 |
|
|
|
698 |
|
|
if w_d_valid = '1' and i_wb_done = '0' then
|
699 |
|
|
v.hazard_depth := r.hazard_depth + 1;
|
700 |
|
|
v.hazard_addr0 := wb_res_addr;
|
701 |
|
|
elsif w_d_valid = '0' and i_wb_done = '1' then
|
702 |
|
|
v.hazard_depth := r.hazard_depth - 1;
|
703 |
|
|
end if;
|
704 |
|
|
w_hazard_lvl1 := '0';
|
705 |
|
|
if (wb_radr1 /= "00000" and wb_radr1 = r.hazard_addr0) or
|
706 |
|
|
(wb_radr2 /= "00000" and wb_radr2 = r.hazard_addr0) then
|
707 |
|
|
w_hazard_lvl1 := '1';
|
708 |
|
|
end if;
|
709 |
|
|
w_hazard_lvl2 := '0';
|
710 |
|
|
if (wb_radr1 /= "00000" and wb_radr1 = r.hazard_addr1) or
|
711 |
|
|
(wb_radr2 /= "00000" and wb_radr2 = r.hazard_addr1) then
|
712 |
|
|
w_hazard_lvl2 := '1';
|
713 |
|
|
end if;
|
714 |
|
|
|
715 |
|
|
if r.hazard_depth = "01" then
|
716 |
|
|
w_hazard_detected <= w_hazard_lvl1;
|
717 |
|
|
elsif r.hazard_depth = "10" then
|
718 |
|
|
w_hazard_detected <= w_hazard_lvl1 or w_hazard_lvl2;
|
719 |
|
|
else
|
720 |
|
|
w_hazard_detected <= '0';
|
721 |
|
|
end if;
|
722 |
|
|
|
723 |
|
|
w_o_valid := r.d_valid;
|
724 |
|
|
w_o_pipeline_hold := w_hazard_detected or r.multiclock_ena;
|
725 |
|
|
|
726 |
|
|
|
727 |
|
|
if i_nrst = '0' then
|
728 |
|
|
v.d_valid := '0';
|
729 |
|
|
v.pc := (others => '0');
|
730 |
|
|
v.npc := RESET_VECTOR;
|
731 |
|
|
v.instr := (others => '0');
|
732 |
|
|
v.res_addr := (others => '0');
|
733 |
|
|
v.res_val := (others => '0');
|
734 |
|
|
v.memop_load := '0';
|
735 |
|
|
v.memop_sign_ext := '0';
|
736 |
|
|
v.memop_store := '0';
|
737 |
|
|
v.memop_size := (others => '0');
|
738 |
|
|
v.memop_addr := (others => '0');
|
739 |
|
|
v.hazard_depth := (others => '0');
|
740 |
|
|
v.hazard_addr0 := (others => '0');
|
741 |
|
|
v.hazard_addr1 := (others => '0');
|
742 |
|
|
|
743 |
|
|
v.multiclock_ena := '0';
|
744 |
|
|
v.multi_pc := (others => '0');
|
745 |
|
|
v.multi_instr := (others => '0');
|
746 |
|
|
v.multi_npc := (others => '0');
|
747 |
|
|
v.multi_res_addr := (others => '0');
|
748 |
|
|
v.multi_ena := (others => '0');
|
749 |
|
|
v.multi_rv32 := '0';
|
750 |
|
|
v.multi_unsigned := '0';
|
751 |
|
|
v.multi_residual_high := '0';
|
752 |
|
|
v.multi_a1 := (others => '0');
|
753 |
|
|
v.multi_a2 := (others => '0');
|
754 |
|
|
|
755 |
|
|
v.ext_irq_pulser := '0';
|
756 |
|
|
v.trap_code_waiting := (others => '0');
|
757 |
|
|
v.trap_ena := '0';
|
758 |
|
|
v.trap_code := (others => '0');
|
759 |
|
|
v.trap_pc := (others => '0');
|
760 |
|
|
v.call := '0';
|
761 |
|
|
v.ret := '0';
|
762 |
|
|
end if;
|
763 |
|
|
|
764 |
|
|
o_radr1 <= wb_radr1;
|
765 |
|
|
o_radr2 <= wb_radr2;
|
766 |
|
|
o_res_addr <= r.res_addr;
|
767 |
|
|
o_res_data <= r.res_val;
|
768 |
|
|
o_pipeline_hold <= w_o_pipeline_hold;
|
769 |
|
|
|
770 |
|
|
o_xret <= w_xret;
|
771 |
|
|
o_csr_wena <= w_csr_wena and w_pc_valid and not w_hazard_detected;
|
772 |
|
|
o_csr_addr <= wb_csr_addr;
|
773 |
|
|
o_csr_wdata <= wb_csr_wdata;
|
774 |
|
|
o_trap_ena <= r.trap_ena;
|
775 |
|
|
o_trap_code <= r.trap_code;
|
776 |
|
|
o_trap_pc <= r.trap_pc;
|
777 |
|
|
|
778 |
|
|
o_memop_sign_ext <= r.memop_sign_ext;
|
779 |
|
|
o_memop_load <= r.memop_load;
|
780 |
|
|
o_memop_store <= r.memop_store;
|
781 |
|
|
o_memop_size <= r.memop_size;
|
782 |
|
|
o_memop_addr <= r.memop_addr;
|
783 |
|
|
|
784 |
|
|
o_valid <= w_o_valid;
|
785 |
|
|
o_pc <= r.pc;
|
786 |
|
|
o_npc <= r.npc;
|
787 |
|
|
o_instr <= r.instr;
|
788 |
|
|
o_breakpoint <= r.breakpoint;
|
789 |
|
|
o_call <= r.call;
|
790 |
|
|
o_ret <= r.ret;
|
791 |
|
|
|
792 |
|
|
rin <= v;
|
793 |
|
|
end process;
|
794 |
|
|
|
795 |
|
|
-- registers:
|
796 |
|
|
regs : process(i_clk)
|
797 |
|
|
begin
|
798 |
|
|
if rising_edge(i_clk) then
|
799 |
|
|
r <= rin;
|
800 |
|
|
end if;
|
801 |
|
|
end process;
|
802 |
|
|
|
803 |
|
|
end;
|