1 |
11 |
dinesha |
/// Copyright by Syntacore LLC © 2016-2020. See LICENSE for details
|
2 |
|
|
/// @file
|
3 |
|
|
/// @brief Execution Unit (EXU)
|
4 |
|
|
///
|
5 |
|
|
|
6 |
|
|
//------------------------------------------------------------------------------
|
7 |
|
|
//
|
8 |
|
|
// Functionality:
|
9 |
|
|
// - Performs instructions execution:
|
10 |
|
|
// - Prevents instructions from execution if the HART is in WFI or Debug Halted
|
11 |
|
|
// state
|
12 |
|
|
// - Fetches operands for IALU
|
13 |
|
|
// - Calculates operation results via IALU
|
14 |
|
|
// - Stores IALU results in MPRF
|
15 |
|
|
// - Performs LOAD/STORE operations via LSU
|
16 |
|
|
// - Handles exceptions:
|
17 |
|
|
// - Generates exception request
|
18 |
|
|
// - Encodes exception code
|
19 |
|
|
// - Calculates exception trap value
|
20 |
|
|
// - Controls WFI instruction execution
|
21 |
|
|
// - Calculates PC value:
|
22 |
|
|
// - Initializes PC on reset
|
23 |
|
|
// - Stores the current PC value
|
24 |
|
|
// - Calculates a New PC value and generates a New PC request to IFU
|
25 |
|
|
//
|
26 |
|
|
// Structure:
|
27 |
|
|
// - Instruction queue
|
28 |
|
|
// - Integer Arithmetic Logic Unit (IALU)
|
29 |
|
|
// - Exceptions logic
|
30 |
|
|
// - WFI logic
|
31 |
|
|
// - Program Counter logic
|
32 |
|
|
// - Load-Store Unit (LSU)
|
33 |
|
|
// - EXU status logic
|
34 |
|
|
// - EXU <-> MPRF i/f
|
35 |
|
|
// - EXU <-> CSR i/f
|
36 |
|
|
// - EXU <-> TDU i/f
|
37 |
|
|
//
|
38 |
|
|
//------------------------------------------------------------------------------
|
39 |
|
|
|
40 |
|
|
`include "scr1_arch_description.svh"
|
41 |
|
|
`include "scr1_arch_types.svh"
|
42 |
|
|
`include "scr1_memif.svh"
|
43 |
|
|
`include "scr1_riscv_isa_decoding.svh"
|
44 |
|
|
`include "scr1_csr.svh"
|
45 |
|
|
|
46 |
|
|
`ifdef SCR1_DBG_EN
|
47 |
|
|
`include "scr1_hdu.svh"
|
48 |
|
|
`endif // SCR1_DBG_EN
|
49 |
|
|
|
50 |
|
|
`ifdef SCR1_TDU_EN
|
51 |
|
|
`include "scr1_tdu.svh"
|
52 |
|
|
`endif // SCR1_TDU_EN
|
53 |
|
|
|
54 |
|
|
module scr1_pipe_exu (
|
55 |
|
|
// Common
|
56 |
|
|
input logic rst_n, // EXU reset
|
57 |
|
|
input logic clk, // Gated EXU clock
|
58 |
|
|
`ifdef SCR1_CLKCTRL_EN
|
59 |
|
|
input logic clk_alw_on, // Not-gated EXU clock
|
60 |
|
|
input logic clk_pipe_en, // EXU clock enabled flag
|
61 |
|
|
`endif // SCR1_CLKCTRL_EN
|
62 |
|
|
|
63 |
|
|
// EXU <-> IDU interface
|
64 |
|
|
input logic idu2exu_req_i, // Request form IDU to EXU
|
65 |
|
|
output logic exu2idu_rdy_o, // EXU ready for new data from IDU
|
66 |
|
|
input type_scr1_exu_cmd_s idu2exu_cmd_i, // EXU command
|
67 |
|
|
input logic idu2exu_use_rs1_i, // Clock gating on rs1_addr field
|
68 |
|
|
input logic idu2exu_use_rs2_i, // Clock gating on rs2_addr field
|
69 |
|
|
`ifndef SCR1_NO_EXE_STAGE
|
70 |
|
|
input logic idu2exu_use_rd_i, // Clock gating on rd_addr field
|
71 |
|
|
input logic idu2exu_use_imm_i, // Clock gating on imm field
|
72 |
|
|
`endif // SCR1_NO_EXE_STAGE
|
73 |
|
|
|
74 |
|
|
// EXU <-> MPRF interface
|
75 |
|
|
output logic [`SCR1_MPRF_AWIDTH-1:0] exu2mprf_rs1_addr_o, // MPRF rs1 read address
|
76 |
|
|
input logic [`SCR1_XLEN-1:0] mprf2exu_rs1_data_i, // MPRF rs1 read data
|
77 |
|
|
output logic [`SCR1_MPRF_AWIDTH-1:0] exu2mprf_rs2_addr_o, // MPRF rs2 read address
|
78 |
|
|
input logic [`SCR1_XLEN-1:0] mprf2exu_rs2_data_i, // MPRF rs2 read data
|
79 |
|
|
output logic exu2mprf_w_req_o, // MPRF write request
|
80 |
|
|
output logic [`SCR1_MPRF_AWIDTH-1:0] exu2mprf_rd_addr_o, // MPRF rd write address
|
81 |
|
|
output logic [`SCR1_XLEN-1:0] exu2mprf_rd_data_o, // MPRF rd write data
|
82 |
|
|
|
83 |
|
|
// EXU <-> CSR read/write interface
|
84 |
|
|
output logic [SCR1_CSR_ADDR_WIDTH-1:0] exu2csr_rw_addr_o, // CSR read/write address
|
85 |
|
|
output logic exu2csr_r_req_o, // CSR read request
|
86 |
|
|
input logic [`SCR1_XLEN-1:0] csr2exu_r_data_i, // CSR read data
|
87 |
|
|
output logic exu2csr_w_req_o, // CSR write request
|
88 |
|
|
output type_scr1_csr_cmd_sel_e exu2csr_w_cmd_o, // CSR write command
|
89 |
|
|
output logic [`SCR1_XLEN-1:0] exu2csr_w_data_o, // CSR write data
|
90 |
|
|
input logic csr2exu_rw_exc_i, // CSR read/write access exception
|
91 |
|
|
|
92 |
|
|
// EXU <-> CSR events interface
|
93 |
|
|
output logic exu2csr_take_irq_o, // Take IRQ trap
|
94 |
|
|
output logic exu2csr_take_exc_o, // Take exception trap
|
95 |
|
|
output logic exu2csr_mret_update_o, // MRET update CSR
|
96 |
|
|
output logic exu2csr_mret_instr_o, // MRET instruction
|
97 |
|
|
output logic [SCR1_EXC_CODE_WIDTH_E-1:0] exu2csr_exc_code_o, // Exception code (see scr1_arch_types.svh) - cp.7
|
98 |
|
|
output logic [`SCR1_XLEN-1:0] exu2csr_trap_val_o, // Trap value
|
99 |
|
|
input logic [`SCR1_XLEN-1:0] csr2exu_new_pc_i, // Exception/IRQ/MRET new PC
|
100 |
|
|
input logic csr2exu_irq_i, // IRQ request
|
101 |
|
|
input logic csr2exu_ip_ie_i, // Some IRQ pending and locally enabled
|
102 |
|
|
input logic csr2exu_mstatus_mie_up_i, // MSTATUS or MIE update in the current cycle
|
103 |
|
|
|
104 |
|
|
// EXU <-> DMEM interface
|
105 |
|
|
output logic exu2dmem_req_o, // Data memory request
|
106 |
|
|
output logic exu2dmem_cmd_o, // Data memory command - cp.7
|
107 |
21 |
dinesha |
output logic [1:0] exu2dmem_width_o, // Data memory width
|
108 |
11 |
dinesha |
output logic [`SCR1_DMEM_AWIDTH-1:0] exu2dmem_addr_o, // Data memory address
|
109 |
|
|
output logic [`SCR1_DMEM_DWIDTH-1:0] exu2dmem_wdata_o, // Data memory write data
|
110 |
|
|
input logic dmem2exu_req_ack_i, // Data memory request acknowledge
|
111 |
|
|
input logic [`SCR1_DMEM_DWIDTH-1:0] dmem2exu_rdata_i, // Data memory read data
|
112 |
|
|
input logic [1:0] dmem2exu_resp_i, // Data memory response - cp.7
|
113 |
|
|
|
114 |
|
|
// EXU control
|
115 |
|
|
output logic exu2pipe_exc_req_o, // Exception on last instruction
|
116 |
|
|
output logic exu2pipe_brkpt_o, // Software Breakpoint (EBREAK)
|
117 |
|
|
output logic exu2pipe_init_pc_o, // Reset exit
|
118 |
|
|
output logic exu2pipe_wfi_run2halt_o, // Transition to WFI halted state
|
119 |
|
|
output logic exu2pipe_instret_o, // Instruction retired (with or without exception)
|
120 |
|
|
output logic exu2csr_instret_no_exc_o, // Instruction retired (without exception)
|
121 |
|
|
output logic exu2pipe_exu_busy_o, // EXU busy
|
122 |
|
|
|
123 |
|
|
`ifdef SCR1_DBG_EN
|
124 |
|
|
// EXU <-> HDU interface
|
125 |
|
|
input logic hdu2exu_no_commit_i, // Forbid instruction commitment
|
126 |
|
|
input logic hdu2exu_irq_dsbl_i, // Disable IRQ
|
127 |
|
|
input logic hdu2exu_pc_advmt_dsbl_i, // Forbid PC advancement
|
128 |
|
|
input logic hdu2exu_dmode_sstep_en_i, // Enable single-step
|
129 |
|
|
input logic hdu2exu_pbuf_fetch_i, // Take instructions from Program Buffer
|
130 |
|
|
input logic hdu2exu_dbg_halted_i, // Debug halted state
|
131 |
|
|
input logic hdu2exu_dbg_run2halt_i, // Transition to debug halted state
|
132 |
|
|
input logic hdu2exu_dbg_halt2run_i, // Transition to run state
|
133 |
|
|
input logic hdu2exu_dbg_run_start_i, // First cycle of run state
|
134 |
|
|
input logic [`SCR1_XLEN-1:0] hdu2exu_dbg_new_pc_i, // New PC as starting point for HART Resume
|
135 |
|
|
`endif // SCR1_DBG_EN
|
136 |
|
|
|
137 |
|
|
`ifdef SCR1_TDU_EN
|
138 |
|
|
// EXU <-> TDU interface
|
139 |
|
|
output type_scr1_brkm_instr_mon_s exu2tdu_imon_o, // Instruction monitor
|
140 |
|
|
input logic [SCR1_TDU_ALLTRIG_NUM-1:0] tdu2exu_ibrkpt_match_i, // Instruction breakpoint(s) match
|
141 |
|
|
input logic tdu2exu_ibrkpt_exc_req_i, // Instruction breakpoint exception
|
142 |
|
|
output type_scr1_brkm_lsu_mon_s lsu2tdu_dmon_o, // Data monitor
|
143 |
|
|
input logic tdu2lsu_ibrkpt_exc_req_i, // Instruction breakpoint exception
|
144 |
|
|
input logic [SCR1_TDU_MTRIG_NUM-1:0] tdu2lsu_dbrkpt_match_i, // Data breakpoint(s) match
|
145 |
|
|
input logic tdu2lsu_dbrkpt_exc_req_i, // Data breakpoint exception
|
146 |
|
|
output logic [SCR1_TDU_ALLTRIG_NUM-1:0] exu2tdu_ibrkpt_ret_o, // Instruction with breakpoint flag retire
|
147 |
|
|
output logic exu2hdu_ibrkpt_hw_o, // Hardware breakpoint on current instruction
|
148 |
|
|
`endif // SCR1_TDU_EN
|
149 |
|
|
|
150 |
|
|
// PC interface
|
151 |
|
|
`ifdef SCR1_CLKCTRL_EN
|
152 |
|
|
output logic exu2pipe_wfi_halted_o, // WFI halted state
|
153 |
|
|
`endif // SCR1_CLKCTRL_EN
|
154 |
|
|
output logic [`SCR1_XLEN-1:0] exu2pipe_pc_curr_o, // Current PC
|
155 |
|
|
output logic [`SCR1_XLEN-1:0] exu2csr_pc_next_o, // Next PC
|
156 |
|
|
output logic exu2ifu_pc_new_req_o, // New PC request
|
157 |
|
|
output logic [`SCR1_XLEN-1:0] exu2ifu_pc_new_o // New PC data
|
158 |
|
|
);
|
159 |
|
|
|
160 |
|
|
//------------------------------------------------------------------------------
|
161 |
|
|
// Local parameters declaration
|
162 |
|
|
//------------------------------------------------------------------------------
|
163 |
|
|
|
164 |
|
|
localparam SCR1_JUMP_MASK = `SCR1_XLEN'hFFFF_FFFE;
|
165 |
|
|
|
166 |
|
|
//------------------------------------------------------------------------------
|
167 |
|
|
// Local types declaration
|
168 |
|
|
//------------------------------------------------------------------------------
|
169 |
|
|
|
170 |
21 |
dinesha |
//typedef enum logic {
|
171 |
|
|
parameter SCR1_CSR_INIT = 1'b0;
|
172 |
|
|
parameter SCR1_CSR_RDY = 1'b1;
|
173 |
|
|
//} scr1_csr_access_e;
|
174 |
11 |
dinesha |
|
175 |
|
|
//------------------------------------------------------------------------------
|
176 |
|
|
// Local signals declaration
|
177 |
|
|
//------------------------------------------------------------------------------
|
178 |
|
|
|
179 |
|
|
// Instruction queue signals
|
180 |
|
|
//------------------------------------------------------------------------------
|
181 |
|
|
logic exu_queue_vd;
|
182 |
|
|
type_scr1_exu_cmd_s exu_queue;
|
183 |
|
|
logic exu_queue_barrier;
|
184 |
|
|
|
185 |
|
|
`ifdef SCR1_DBG_EN
|
186 |
|
|
logic dbg_run_start_npbuf;
|
187 |
|
|
`endif // SCR1_DBG_EN
|
188 |
|
|
logic exu_queue_en;
|
189 |
|
|
logic [`SCR1_XLEN-1:0] exu_illegal_instr;
|
190 |
|
|
|
191 |
|
|
`ifndef SCR1_NO_EXE_STAGE
|
192 |
|
|
logic idu2exu_use_rs1_ff;
|
193 |
|
|
logic idu2exu_use_rs2_ff;
|
194 |
|
|
|
195 |
|
|
// EXU queue valid flag register signals
|
196 |
|
|
logic exu_queue_vd_upd;
|
197 |
|
|
logic exu_queue_vd_ff;
|
198 |
|
|
logic exu_queue_vd_next;
|
199 |
|
|
`endif // SCR1_NO_EXE_STAGE
|
200 |
|
|
|
201 |
|
|
// IALU signals
|
202 |
|
|
//------------------------------------------------------------------------------
|
203 |
|
|
`ifdef SCR1_RVM_EXT
|
204 |
|
|
logic ialu_rdy;
|
205 |
|
|
logic ialu_vd;
|
206 |
|
|
`endif // SCR1_RVM_EXT
|
207 |
|
|
logic [`SCR1_XLEN-1:0] ialu_main_op1;
|
208 |
|
|
logic [`SCR1_XLEN-1:0] ialu_main_op2;
|
209 |
|
|
logic [`SCR1_XLEN-1:0] ialu_main_res;
|
210 |
|
|
logic [`SCR1_XLEN-1:0] ialu_addr_op1;
|
211 |
|
|
logic [`SCR1_XLEN-1:0] ialu_addr_op2;
|
212 |
|
|
logic [`SCR1_XLEN-1:0] ialu_addr_res;
|
213 |
|
|
logic ialu_cmp;
|
214 |
|
|
|
215 |
|
|
// Exceptions signals
|
216 |
|
|
//------------------------------------------------------------------------------
|
217 |
|
|
logic exu_exc_req;
|
218 |
|
|
`ifdef SCR1_DBG_EN
|
219 |
|
|
logic exu_exc_req_ff;
|
220 |
|
|
logic exu_exc_req_next;
|
221 |
|
|
`endif // SCR1_DBG_EN
|
222 |
|
|
logic [SCR1_EXC_CODE_WIDTH_E-1:0] exc_code; // cp.7
|
223 |
|
|
logic [`SCR1_XLEN-1:0] exc_trap_val;
|
224 |
|
|
logic instr_fault_rvi_hi;
|
225 |
|
|
|
226 |
|
|
// WFI signals
|
227 |
|
|
//------------------------------------------------------------------------------
|
228 |
|
|
// WFI control signals
|
229 |
|
|
logic wfi_halt_cond;
|
230 |
|
|
logic wfi_run_req;
|
231 |
|
|
logic wfi_halt_req;
|
232 |
|
|
|
233 |
|
|
// WFI Run Start register
|
234 |
|
|
logic wfi_run_start_ff;
|
235 |
|
|
logic wfi_run_start_next;
|
236 |
|
|
|
237 |
|
|
// WFI halted register
|
238 |
|
|
logic wfi_halted_upd;
|
239 |
|
|
logic wfi_halted_ff;
|
240 |
|
|
logic wfi_halted_next;
|
241 |
|
|
|
242 |
|
|
// PC signals
|
243 |
|
|
//------------------------------------------------------------------------------
|
244 |
|
|
logic [3:0] init_pc_v;
|
245 |
|
|
logic init_pc;
|
246 |
|
|
logic [`SCR1_XLEN-1:0] inc_pc;
|
247 |
|
|
|
248 |
|
|
logic branch_taken;
|
249 |
|
|
logic jb_taken;
|
250 |
|
|
logic [`SCR1_XLEN-1:0] jb_new_pc;
|
251 |
|
|
`ifndef SCR1_RVC_EXT
|
252 |
|
|
logic jb_misalign;
|
253 |
|
|
`endif
|
254 |
|
|
|
255 |
|
|
// Current PC register
|
256 |
|
|
logic pc_curr_upd;
|
257 |
|
|
logic [`SCR1_XLEN-1:0] pc_curr_ff;
|
258 |
|
|
logic [`SCR1_XLEN-1:0] pc_curr_next;
|
259 |
|
|
|
260 |
|
|
// LSU signals
|
261 |
|
|
//------------------------------------------------------------------------------
|
262 |
|
|
logic lsu_req;
|
263 |
|
|
logic lsu_rdy;
|
264 |
|
|
logic [`SCR1_XLEN-1:0] lsu_l_data;
|
265 |
|
|
logic lsu_exc_req;
|
266 |
|
|
logic [SCR1_EXC_CODE_WIDTH_E-1:0] lsu_exc_code; // cp.7
|
267 |
|
|
|
268 |
|
|
// EXU status signals
|
269 |
|
|
//------------------------------------------------------------------------------
|
270 |
|
|
logic exu_rdy;
|
271 |
|
|
|
272 |
|
|
// MPRF signals
|
273 |
|
|
//------------------------------------------------------------------------------
|
274 |
|
|
logic mprf_rs1_req;
|
275 |
|
|
logic mprf_rs2_req;
|
276 |
|
|
|
277 |
|
|
logic [`SCR1_MPRF_AWIDTH-1:0] mprf_rs1_addr;
|
278 |
|
|
logic [`SCR1_MPRF_AWIDTH-1:0] mprf_rs2_addr;
|
279 |
|
|
|
280 |
|
|
// CSR signals
|
281 |
|
|
//------------------------------------------------------------------------------
|
282 |
|
|
// CSR access register
|
283 |
21 |
dinesha |
logic csr_access_ff;
|
284 |
|
|
logic csr_access_next;
|
285 |
11 |
dinesha |
logic csr_access_init;
|
286 |
|
|
|
287 |
|
|
//------------------------------------------------------------------------------
|
288 |
|
|
// Instruction execution queue
|
289 |
|
|
//------------------------------------------------------------------------------
|
290 |
|
|
//
|
291 |
|
|
// Instruction execution queue consists of the following functional units:
|
292 |
|
|
// - EXU queue control logic
|
293 |
|
|
// - EXU queue valid flag register
|
294 |
|
|
// - EXU queue register
|
295 |
|
|
// - EXU queue status logic
|
296 |
|
|
//
|
297 |
|
|
|
298 |
|
|
`ifdef SCR1_DBG_EN
|
299 |
|
|
assign dbg_run_start_npbuf = hdu2exu_dbg_run_start_i & ~hdu2exu_pbuf_fetch_i;
|
300 |
|
|
`endif // SCR1_DBG_EN
|
301 |
|
|
|
302 |
|
|
`ifndef SCR1_NO_EXE_STAGE
|
303 |
|
|
|
304 |
|
|
// EXU queue control logic
|
305 |
|
|
//------------------------------------------------------------------------------
|
306 |
|
|
|
307 |
|
|
assign exu_queue_barrier = wfi_halted_ff | wfi_halt_req | wfi_run_start_ff
|
308 |
|
|
`ifdef SCR1_DBG_EN
|
309 |
|
|
| hdu2exu_dbg_halted_i | hdu2exu_dbg_run2halt_i
|
310 |
|
|
| dbg_run_start_npbuf
|
311 |
|
|
`endif // SCR1_DBG_EN
|
312 |
|
|
;
|
313 |
|
|
|
314 |
|
|
assign exu_queue_en = exu2idu_rdy_o & idu2exu_req_i;
|
315 |
|
|
|
316 |
|
|
// EXU queue valid flag register
|
317 |
|
|
//------------------------------------------------------------------------------
|
318 |
|
|
|
319 |
|
|
assign exu_queue_vd_upd = exu_queue_barrier | exu_rdy;
|
320 |
|
|
|
321 |
|
|
always_ff @(posedge clk, negedge rst_n) begin
|
322 |
|
|
if (~rst_n) begin
|
323 |
|
|
exu_queue_vd_ff <= 1'b0;
|
324 |
|
|
end else if (exu_queue_vd_upd) begin
|
325 |
|
|
exu_queue_vd_ff <= exu_queue_vd_next;
|
326 |
|
|
end
|
327 |
|
|
end
|
328 |
|
|
|
329 |
|
|
assign exu_queue_vd_next = ~exu_queue_barrier & idu2exu_req_i & ~exu2ifu_pc_new_req_o;
|
330 |
|
|
assign exu_queue_vd = exu_queue_vd_ff;
|
331 |
|
|
|
332 |
|
|
// EXU queue register
|
333 |
|
|
//------------------------------------------------------------------------------
|
334 |
|
|
|
335 |
|
|
always_ff @(posedge clk) begin
|
336 |
|
|
if (exu_queue_en) begin
|
337 |
|
|
exu_queue.instr_rvc <= idu2exu_cmd_i.instr_rvc;
|
338 |
|
|
exu_queue.ialu_op <= idu2exu_cmd_i.ialu_op;
|
339 |
|
|
exu_queue.ialu_cmd <= idu2exu_cmd_i.ialu_cmd;
|
340 |
|
|
exu_queue.sum2_op <= idu2exu_cmd_i.sum2_op;
|
341 |
|
|
exu_queue.lsu_cmd <= idu2exu_cmd_i.lsu_cmd;
|
342 |
|
|
exu_queue.csr_op <= idu2exu_cmd_i.csr_op;
|
343 |
|
|
exu_queue.csr_cmd <= idu2exu_cmd_i.csr_cmd;
|
344 |
|
|
exu_queue.rd_wb_sel <= idu2exu_cmd_i.rd_wb_sel;
|
345 |
|
|
exu_queue.jump_req <= idu2exu_cmd_i.jump_req;
|
346 |
|
|
exu_queue.branch_req <= idu2exu_cmd_i.branch_req;
|
347 |
|
|
exu_queue.mret_req <= idu2exu_cmd_i.mret_req;
|
348 |
|
|
exu_queue.fencei_req <= idu2exu_cmd_i.fencei_req;
|
349 |
|
|
exu_queue.wfi_req <= idu2exu_cmd_i.wfi_req;
|
350 |
|
|
exu_queue.exc_req <= idu2exu_cmd_i.exc_req;
|
351 |
|
|
exu_queue.exc_code <= idu2exu_cmd_i.exc_code;
|
352 |
|
|
idu2exu_use_rs1_ff <= idu2exu_use_rs1_i;
|
353 |
|
|
idu2exu_use_rs2_ff <= idu2exu_use_rs2_i;
|
354 |
|
|
if (idu2exu_use_rs1_i) begin
|
355 |
|
|
exu_queue.rs1_addr <= idu2exu_cmd_i.rs1_addr;
|
356 |
|
|
end
|
357 |
|
|
if (idu2exu_use_rs2_i) begin
|
358 |
|
|
exu_queue.rs2_addr <= idu2exu_cmd_i.rs2_addr;
|
359 |
|
|
end
|
360 |
|
|
if (idu2exu_use_rd_i) begin
|
361 |
|
|
exu_queue.rd_addr <= idu2exu_cmd_i.rd_addr;
|
362 |
|
|
end
|
363 |
|
|
if (idu2exu_use_imm_i) begin
|
364 |
|
|
exu_queue.imm <= idu2exu_cmd_i.imm;
|
365 |
|
|
end
|
366 |
|
|
end
|
367 |
|
|
end
|
368 |
|
|
|
369 |
|
|
`else // ~SCR1_NO_EXE_STAGE
|
370 |
|
|
|
371 |
|
|
assign exu_queue_barrier = wfi_halted_ff | wfi_run_start_ff
|
372 |
|
|
`ifdef SCR1_DBG_EN
|
373 |
|
|
| hdu2exu_dbg_halted_i | dbg_run_start_npbuf
|
374 |
|
|
`endif // SCR1_DBG_EN
|
375 |
|
|
;
|
376 |
|
|
assign exu_queue_vd = idu2exu_req_i & ~exu_queue_barrier;
|
377 |
|
|
assign exu_queue = idu2exu_cmd_i;
|
378 |
|
|
|
379 |
|
|
`endif // ~SCR1_NO_EXE_STAGE
|
380 |
|
|
|
381 |
|
|
//------------------------------------------------------------------------------
|
382 |
|
|
// Integer Arithmetic Logic Unit (IALU)
|
383 |
|
|
//------------------------------------------------------------------------------
|
384 |
|
|
//
|
385 |
|
|
// Functionality:
|
386 |
|
|
// - Performs addition/subtraction and arithmetic and branch comparisons
|
387 |
|
|
// - Performs logical operations (AND(I), OR(I), XOR(I))
|
388 |
|
|
// - Performs address calculation for branch, jump, DMEM load and store and AUIPC
|
389 |
|
|
// instructions
|
390 |
|
|
// - Performs shift operations
|
391 |
|
|
// - Performs MUL/DIV operations
|
392 |
|
|
//
|
393 |
|
|
//------------------------------------------------------------------------------
|
394 |
|
|
|
395 |
|
|
// IALU main operands fetch
|
396 |
|
|
//------------------------------------------------------------------------------
|
397 |
|
|
|
398 |
|
|
`ifdef SCR1_RVM_EXT
|
399 |
|
|
assign ialu_vd = exu_queue_vd & (exu_queue.ialu_cmd != SCR1_IALU_CMD_NONE)
|
400 |
|
|
`ifdef SCR1_TDU_EN
|
401 |
|
|
& ~tdu2exu_ibrkpt_exc_req_i
|
402 |
|
|
`endif // SCR1_TDU_EN
|
403 |
|
|
;
|
404 |
|
|
`endif // SCR1_RVM_EXT
|
405 |
|
|
|
406 |
|
|
always_comb begin
|
407 |
|
|
`ifdef SCR1_RVM_EXT
|
408 |
|
|
if (~ialu_vd) begin
|
409 |
|
|
ialu_main_op1 = '0;
|
410 |
|
|
ialu_main_op2 = '0;
|
411 |
|
|
end else begin
|
412 |
|
|
`endif // SCR1_RVM_EXT
|
413 |
|
|
if (exu_queue.ialu_op == SCR1_IALU_OP_REG_REG) begin
|
414 |
|
|
ialu_main_op1 = mprf2exu_rs1_data_i;
|
415 |
|
|
ialu_main_op2 = mprf2exu_rs2_data_i;
|
416 |
|
|
end else begin
|
417 |
|
|
ialu_main_op1 = mprf2exu_rs1_data_i;
|
418 |
|
|
ialu_main_op2 = exu_queue.imm;
|
419 |
|
|
end
|
420 |
|
|
`ifdef SCR1_RVM_EXT
|
421 |
|
|
end
|
422 |
|
|
`endif // SCR1_RVM_EXT
|
423 |
|
|
end
|
424 |
|
|
|
425 |
|
|
// IALU address operands fetch
|
426 |
|
|
//------------------------------------------------------------------------------
|
427 |
|
|
|
428 |
|
|
always_comb begin
|
429 |
|
|
if (exu_queue.sum2_op == SCR1_SUM2_OP_REG_IMM) begin
|
430 |
|
|
ialu_addr_op1 = mprf2exu_rs1_data_i;
|
431 |
|
|
ialu_addr_op2 = exu_queue.imm;
|
432 |
|
|
end else begin
|
433 |
|
|
ialu_addr_op1 = pc_curr_ff;
|
434 |
|
|
ialu_addr_op2 = exu_queue.imm;
|
435 |
|
|
end
|
436 |
|
|
end
|
437 |
|
|
|
438 |
|
|
// IALU module instantiation
|
439 |
|
|
//------------------------------------------------------------------------------
|
440 |
|
|
|
441 |
|
|
scr1_pipe_ialu i_ialu(
|
442 |
|
|
`ifdef SCR1_RVM_EXT
|
443 |
|
|
// Common
|
444 |
|
|
.clk (clk ),
|
445 |
|
|
.rst_n (rst_n ),
|
446 |
|
|
.exu2ialu_rvm_cmd_vd_i (ialu_vd ),
|
447 |
|
|
.ialu2exu_rvm_res_rdy_o (ialu_rdy ),
|
448 |
|
|
`endif // SCR1_RVM_EXT
|
449 |
|
|
|
450 |
|
|
// IALU
|
451 |
|
|
.exu2ialu_main_op1_i (ialu_main_op1 ),
|
452 |
|
|
.exu2ialu_main_op2_i (ialu_main_op2 ),
|
453 |
|
|
.exu2ialu_cmd_i (exu_queue.ialu_cmd),
|
454 |
|
|
.ialu2exu_main_res_o (ialu_main_res ),
|
455 |
|
|
.ialu2exu_cmp_res_o (ialu_cmp ),
|
456 |
|
|
|
457 |
|
|
// Address adder signals
|
458 |
|
|
.exu2ialu_addr_op1_i (ialu_addr_op1 ),
|
459 |
|
|
.exu2ialu_addr_op2_i (ialu_addr_op2 ),
|
460 |
|
|
.ialu2exu_addr_res_o (ialu_addr_res )
|
461 |
|
|
);
|
462 |
|
|
|
463 |
|
|
//------------------------------------------------------------------------------
|
464 |
|
|
// Exceptions logic
|
465 |
|
|
//------------------------------------------------------------------------------
|
466 |
|
|
//
|
467 |
|
|
// Exceptions logic consists of the following functional units:
|
468 |
|
|
// - Exception request logic
|
469 |
|
|
// - Exception code encoder
|
470 |
|
|
// - Exception trap value multiplexer
|
471 |
|
|
//
|
472 |
|
|
//
|
473 |
|
|
|
474 |
|
|
`ifndef SCR1_RVC_EXT
|
475 |
|
|
assign jb_misalign = exu_queue_vd & jb_taken & |jb_new_pc[1:0];
|
476 |
|
|
`endif // ~SCR1_RVC_EXT
|
477 |
|
|
|
478 |
|
|
// Exception request
|
479 |
|
|
assign exu_exc_req = exu_queue_vd & (exu_queue.exc_req | lsu_exc_req
|
480 |
|
|
| csr2exu_rw_exc_i
|
481 |
|
|
`ifndef SCR1_RVC_EXT
|
482 |
|
|
| jb_misalign
|
483 |
|
|
`endif // ~SCR1_RVC_EXT
|
484 |
|
|
`ifdef SCR1_TDU_EN
|
485 |
|
|
| exu2hdu_ibrkpt_hw_o
|
486 |
|
|
`endif // SCR1_TDU_EN
|
487 |
|
|
);
|
488 |
|
|
|
489 |
|
|
// EXU exception request register
|
490 |
|
|
//------------------------------------------------------------------------------
|
491 |
|
|
|
492 |
|
|
`ifdef SCR1_DBG_EN
|
493 |
|
|
|
494 |
|
|
always_ff @(posedge clk, negedge rst_n) begin
|
495 |
|
|
if (~rst_n) begin
|
496 |
|
|
exu_exc_req_ff <= 1'b0;
|
497 |
|
|
end else begin
|
498 |
|
|
exu_exc_req_ff <= exu_exc_req_next;
|
499 |
|
|
end
|
500 |
|
|
end
|
501 |
|
|
|
502 |
|
|
assign exu_exc_req_next = hdu2exu_dbg_halt2run_i ? 1'b0 : exu_exc_req;
|
503 |
|
|
`endif // SCR1_DBG_EN
|
504 |
|
|
|
505 |
|
|
// Exception code encoder
|
506 |
|
|
//------------------------------------------------------------------------------
|
507 |
|
|
|
508 |
|
|
always_comb begin
|
509 |
|
|
case (1'b1)
|
510 |
|
|
`ifdef SCR1_TDU_EN
|
511 |
|
|
exu2hdu_ibrkpt_hw_o: exc_code = SCR1_EXC_CODE_BREAKPOINT;
|
512 |
|
|
`endif // SCR1_TDU_EN
|
513 |
|
|
exu_queue.exc_req : exc_code = exu_queue.exc_code;
|
514 |
|
|
lsu_exc_req : exc_code = lsu_exc_code;
|
515 |
|
|
csr2exu_rw_exc_i : exc_code = SCR1_EXC_CODE_ILLEGAL_INSTR;
|
516 |
|
|
`ifndef SCR1_RVC_EXT
|
517 |
|
|
jb_misalign : exc_code = SCR1_EXC_CODE_INSTR_MISALIGN;
|
518 |
|
|
`endif // ~SCR1_RVC_EXT
|
519 |
|
|
default : exc_code = SCR1_EXC_CODE_ECALL_M;
|
520 |
|
|
endcase // 1'b1
|
521 |
|
|
end
|
522 |
|
|
|
523 |
|
|
// Exception trap value multiplexer
|
524 |
|
|
//------------------------------------------------------------------------------
|
525 |
|
|
|
526 |
|
|
assign instr_fault_rvi_hi = exu_queue.instr_rvc;
|
527 |
|
|
assign exu_illegal_instr = {exu2csr_rw_addr_o, // CSR address
|
528 |
|
|
5'(exu_queue.rs1_addr), // rs1 / zimm
|
529 |
|
|
exu_queue.imm[14:12], // funct3
|
530 |
|
|
5'(exu_queue.rd_addr), // rd
|
531 |
|
|
SCR1_OPCODE_SYSTEM,
|
532 |
|
|
SCR1_INSTR_RVI
|
533 |
|
|
};
|
534 |
|
|
|
535 |
|
|
// If Instruction Access Fault occurred on high part of RVI instruction trap
|
536 |
|
|
// value is set to point on the high part of the instruction (inc_pc=pc+2)
|
537 |
|
|
always_comb begin
|
538 |
|
|
case (exc_code)
|
539 |
|
|
`ifndef SCR1_RVC_EXT
|
540 |
|
|
SCR1_EXC_CODE_INSTR_MISALIGN : exc_trap_val = jb_new_pc;
|
541 |
|
|
`endif // SCR1_RVC_EXT
|
542 |
|
|
SCR1_EXC_CODE_INSTR_ACCESS_FAULT: exc_trap_val = instr_fault_rvi_hi
|
543 |
|
|
? inc_pc
|
544 |
|
|
: pc_curr_ff;
|
545 |
|
|
`ifdef SCR1_MTVAL_ILLEGAL_INSTR_EN
|
546 |
|
|
SCR1_EXC_CODE_ILLEGAL_INSTR : exc_trap_val = exu_queue.exc_req
|
547 |
|
|
? exu_queue.imm
|
548 |
|
|
: exu_illegal_instr;
|
549 |
|
|
`else // SCR1_MTVAL_ILLEGAL_INSTR_EN
|
550 |
|
|
SCR1_EXC_CODE_ILLEGAL_INSTR : exc_trap_val = '0;
|
551 |
|
|
`endif // SCR1_MTVAL_ILLEGAL_INSTR_EN
|
552 |
|
|
`ifdef SCR1_TDU_EN
|
553 |
|
|
SCR1_EXC_CODE_BREAKPOINT: begin
|
554 |
|
|
case (1'b1)
|
555 |
|
|
tdu2exu_ibrkpt_exc_req_i: exc_trap_val = pc_curr_ff;
|
556 |
|
|
tdu2lsu_dbrkpt_exc_req_i: exc_trap_val = ialu_addr_res;
|
557 |
|
|
default : exc_trap_val = '0;
|
558 |
|
|
endcase
|
559 |
|
|
end
|
560 |
|
|
`endif // SCR1_TDU_EN
|
561 |
|
|
SCR1_EXC_CODE_LD_ADDR_MISALIGN,
|
562 |
|
|
SCR1_EXC_CODE_LD_ACCESS_FAULT,
|
563 |
|
|
SCR1_EXC_CODE_ST_ADDR_MISALIGN,
|
564 |
|
|
SCR1_EXC_CODE_ST_ACCESS_FAULT : exc_trap_val = ialu_addr_res;
|
565 |
|
|
default : exc_trap_val = '0;
|
566 |
|
|
endcase // exc_code
|
567 |
|
|
end
|
568 |
|
|
|
569 |
|
|
//------------------------------------------------------------------------------
|
570 |
|
|
// WFI logic
|
571 |
|
|
//------------------------------------------------------------------------------
|
572 |
|
|
//
|
573 |
|
|
// Wait for interrupt (WFI) logic consists of the following functional units:
|
574 |
|
|
// - WFI control logic
|
575 |
|
|
// - WFI Run Start register
|
576 |
|
|
// - WFI Halted flag register
|
577 |
|
|
// - WFI status signals
|
578 |
|
|
//
|
579 |
|
|
|
580 |
|
|
// WFI control logic
|
581 |
|
|
//------------------------------------------------------------------------------
|
582 |
|
|
|
583 |
|
|
assign wfi_halt_cond = ~csr2exu_ip_ie_i
|
584 |
|
|
& ((exu_queue_vd & exu_queue.wfi_req) | wfi_run_start_ff)
|
585 |
|
|
`ifdef SCR1_DBG_EN
|
586 |
|
|
& ~hdu2exu_no_commit_i & ~hdu2exu_dmode_sstep_en_i & ~hdu2exu_dbg_run2halt_i
|
587 |
|
|
`endif // SCR1_DBG_EN
|
588 |
|
|
;
|
589 |
|
|
assign wfi_halt_req = ~wfi_halted_ff & wfi_halt_cond;
|
590 |
|
|
|
591 |
|
|
// HART will exit WFI halted state if the event that causes the HART to resume
|
592 |
|
|
// execution occurs even if it doesn't cause an interrupt to be taken
|
593 |
|
|
assign wfi_run_req = wfi_halted_ff & (csr2exu_ip_ie_i
|
594 |
|
|
`ifdef SCR1_DBG_EN
|
595 |
|
|
| hdu2exu_dbg_halt2run_i
|
596 |
|
|
`endif // SCR1_DBG_EN
|
597 |
|
|
);
|
598 |
|
|
|
599 |
|
|
// WFI Run Start register
|
600 |
|
|
//------------------------------------------------------------------------------
|
601 |
|
|
|
602 |
|
|
`ifndef SCR1_CLKCTRL_EN
|
603 |
|
|
always_ff @(negedge rst_n, posedge clk) begin
|
604 |
|
|
`else // SCR1_CLKCTRL_EN
|
605 |
|
|
always_ff @(negedge rst_n, posedge clk_alw_on) begin
|
606 |
|
|
`endif // SCR1_CLKCTRL_EN
|
607 |
|
|
if (~rst_n) begin
|
608 |
|
|
wfi_run_start_ff <= 1'b0;
|
609 |
|
|
end else begin
|
610 |
|
|
wfi_run_start_ff <= wfi_run_start_next;
|
611 |
|
|
end
|
612 |
|
|
end
|
613 |
|
|
|
614 |
|
|
assign wfi_run_start_next = wfi_halted_ff & csr2exu_ip_ie_i & ~exu2csr_take_irq_o;
|
615 |
|
|
|
616 |
|
|
// WFI halted flag register
|
617 |
|
|
//------------------------------------------------------------------------------
|
618 |
|
|
|
619 |
|
|
assign wfi_halted_upd = wfi_halt_req | wfi_run_req;
|
620 |
|
|
|
621 |
|
|
`ifndef SCR1_CLKCTRL_EN
|
622 |
|
|
always_ff @(negedge rst_n, posedge clk) begin
|
623 |
|
|
`else // SCR1_CLKCTRL_EN
|
624 |
|
|
always_ff @(negedge rst_n, posedge clk_alw_on) begin
|
625 |
|
|
`endif // SCR1_CLKCTRL_EN
|
626 |
|
|
if (~rst_n) begin
|
627 |
|
|
wfi_halted_ff <= 1'b0;
|
628 |
|
|
end else if (wfi_halted_upd) begin
|
629 |
|
|
wfi_halted_ff <= wfi_halted_next;
|
630 |
|
|
end
|
631 |
|
|
end
|
632 |
|
|
|
633 |
|
|
assign wfi_halted_next = wfi_halt_req | ~wfi_run_req;
|
634 |
|
|
|
635 |
|
|
// WFI status signals
|
636 |
|
|
//------------------------------------------------------------------------------
|
637 |
|
|
|
638 |
|
|
assign exu2pipe_wfi_run2halt_o = wfi_halt_req;
|
639 |
|
|
`ifdef SCR1_CLKCTRL_EN
|
640 |
|
|
assign exu2pipe_wfi_halted_o = wfi_halted_ff;
|
641 |
|
|
`endif // SCR1_CLKCTRL_EN
|
642 |
|
|
|
643 |
|
|
//------------------------------------------------------------------------------
|
644 |
|
|
// Program Counter logic
|
645 |
|
|
//------------------------------------------------------------------------------
|
646 |
|
|
//
|
647 |
|
|
// PC logic consists of the following functional units:
|
648 |
|
|
// - PC initialization logic
|
649 |
|
|
// - Current PC register
|
650 |
|
|
// - New PC multiplexer
|
651 |
|
|
|
652 |
|
|
// PC initialization logic
|
653 |
|
|
//------------------------------------------------------------------------------
|
654 |
|
|
// Generates a New PC request to set PC to reset value
|
655 |
|
|
|
656 |
|
|
always_ff @(posedge clk, negedge rst_n) begin
|
657 |
|
|
if (~rst_n) begin
|
658 |
|
|
init_pc_v <= '0;
|
659 |
|
|
end else begin
|
660 |
|
|
if (~&init_pc_v) begin
|
661 |
|
|
init_pc_v <= {init_pc_v[2:0], 1'b1};
|
662 |
|
|
end
|
663 |
|
|
end
|
664 |
|
|
end
|
665 |
|
|
|
666 |
|
|
assign init_pc = ~init_pc_v[3] & init_pc_v[2];
|
667 |
|
|
|
668 |
|
|
// Current PC register
|
669 |
|
|
//------------------------------------------------------------------------------
|
670 |
|
|
|
671 |
|
|
assign pc_curr_upd = ((exu2pipe_instret_o | exu2csr_take_irq_o
|
672 |
|
|
`ifdef SCR1_DBG_EN
|
673 |
|
|
| dbg_run_start_npbuf) & ( ~hdu2exu_pc_advmt_dsbl_i
|
674 |
|
|
& ~hdu2exu_no_commit_i
|
675 |
|
|
`endif // SCR1_DBG_EN
|
676 |
|
|
));
|
677 |
|
|
|
678 |
|
|
always_ff @(negedge rst_n, posedge clk) begin
|
679 |
|
|
if (~rst_n) begin
|
680 |
|
|
pc_curr_ff <= SCR1_RST_VECTOR;
|
681 |
|
|
end else if (pc_curr_upd) begin
|
682 |
|
|
pc_curr_ff <= pc_curr_next;
|
683 |
|
|
end
|
684 |
|
|
end
|
685 |
|
|
|
686 |
|
|
`ifdef SCR1_RVC_EXT
|
687 |
|
|
assign inc_pc = pc_curr_ff + (exu_queue.instr_rvc ? `SCR1_XLEN'd2 : `SCR1_XLEN'd4);
|
688 |
|
|
`else // ~SCR1_RVC_EXT
|
689 |
|
|
assign inc_pc = pc_curr_ff + `SCR1_XLEN'd4;
|
690 |
|
|
`endif // ~SCR1_RVC_EXT
|
691 |
|
|
|
692 |
|
|
assign pc_curr_next = exu2ifu_pc_new_req_o ? exu2ifu_pc_new_o
|
693 |
|
|
: (inc_pc[6] ^ pc_curr_ff[6]) ? inc_pc
|
694 |
|
|
: {pc_curr_ff[`SCR1_XLEN-1:6], inc_pc[5:0]};
|
695 |
|
|
|
696 |
|
|
// New PC multiplexer
|
697 |
|
|
//------------------------------------------------------------------------------
|
698 |
|
|
|
699 |
|
|
always_comb begin
|
700 |
|
|
case (1'b1)
|
701 |
|
|
init_pc : exu2ifu_pc_new_o = SCR1_RST_VECTOR;
|
702 |
|
|
exu2csr_take_exc_o,
|
703 |
|
|
exu2csr_take_irq_o,
|
704 |
|
|
exu2csr_mret_instr_o: exu2ifu_pc_new_o = csr2exu_new_pc_i;
|
705 |
|
|
`ifdef SCR1_DBG_EN
|
706 |
|
|
dbg_run_start_npbuf : exu2ifu_pc_new_o = hdu2exu_dbg_new_pc_i;
|
707 |
|
|
`endif // SCR1_DBG_EN
|
708 |
|
|
wfi_run_start_ff : exu2ifu_pc_new_o = pc_curr_ff;
|
709 |
|
|
exu_queue.fencei_req: exu2ifu_pc_new_o = inc_pc;
|
710 |
|
|
default : exu2ifu_pc_new_o = ialu_addr_res & SCR1_JUMP_MASK;
|
711 |
|
|
endcase
|
712 |
|
|
end
|
713 |
|
|
|
714 |
|
|
assign exu2ifu_pc_new_req_o = init_pc // reset
|
715 |
|
|
| exu2csr_take_irq_o
|
716 |
|
|
| exu2csr_take_exc_o
|
717 |
|
|
| (exu2csr_mret_instr_o & ~csr2exu_mstatus_mie_up_i)
|
718 |
|
|
| (exu_queue_vd & exu_queue.fencei_req)
|
719 |
|
|
| (wfi_run_start_ff
|
720 |
|
|
`ifdef SCR1_CLKCTRL_EN
|
721 |
|
|
& clk_pipe_en
|
722 |
|
|
`endif // SCR1_CLKCTRL_EN
|
723 |
|
|
)
|
724 |
|
|
`ifdef SCR1_DBG_EN
|
725 |
|
|
| dbg_run_start_npbuf
|
726 |
|
|
`endif // SCR1_DBG_EN
|
727 |
|
|
| (exu_queue_vd & jb_taken);
|
728 |
|
|
|
729 |
|
|
// Jump/branch signals
|
730 |
|
|
assign branch_taken = exu_queue.branch_req & ialu_cmp;
|
731 |
|
|
assign jb_taken = exu_queue.jump_req | branch_taken;
|
732 |
|
|
assign jb_new_pc = ialu_addr_res & SCR1_JUMP_MASK;
|
733 |
|
|
|
734 |
|
|
// PC to be loaded on MRET from interrupt trap
|
735 |
|
|
assign exu2csr_pc_next_o = ~exu_queue_vd ? pc_curr_ff
|
736 |
|
|
: jb_taken ? jb_new_pc
|
737 |
|
|
: inc_pc;
|
738 |
|
|
assign exu2pipe_pc_curr_o = pc_curr_ff;
|
739 |
|
|
|
740 |
|
|
//------------------------------------------------------------------------------
|
741 |
|
|
// Load/Store Unit (LSU)
|
742 |
|
|
//------------------------------------------------------------------------------
|
743 |
|
|
//
|
744 |
|
|
// Functionality:
|
745 |
|
|
// - Performs load and store operations in Data Memory
|
746 |
|
|
// - Generates DMEM address misalign and access fault exceptions
|
747 |
|
|
// - Passes DMEM operations information to TDU and generates LSU breakpoint exception
|
748 |
|
|
//
|
749 |
|
|
//------------------------------------------------------------------------------
|
750 |
|
|
|
751 |
|
|
assign lsu_req = ((exu_queue.lsu_cmd != SCR1_LSU_CMD_NONE) & exu_queue_vd);
|
752 |
|
|
|
753 |
|
|
scr1_pipe_lsu i_lsu(
|
754 |
|
|
.rst_n (rst_n ),
|
755 |
|
|
.clk (clk ),
|
756 |
|
|
|
757 |
|
|
// EXU <-> LSU interface
|
758 |
|
|
.exu2lsu_req_i (lsu_req ), // Request to LSU
|
759 |
|
|
.exu2lsu_cmd_i (exu_queue.lsu_cmd ), // LSU command
|
760 |
|
|
.exu2lsu_addr_i (ialu_addr_res ), // DMEM address
|
761 |
|
|
.exu2lsu_sdata_i (mprf2exu_rs2_data_i ), // Data for store to DMEM
|
762 |
|
|
.lsu2exu_rdy_o (lsu_rdy ), // LSU ready
|
763 |
|
|
.lsu2exu_ldata_o (lsu_l_data ), // Loaded data form DMEM
|
764 |
|
|
.lsu2exu_exc_o (lsu_exc_req ), // LSU exception
|
765 |
|
|
.lsu2exu_exc_code_o (lsu_exc_code ), // LSU exception code
|
766 |
|
|
|
767 |
|
|
`ifdef SCR1_TDU_EN
|
768 |
|
|
// TDU <-> LSU interface
|
769 |
|
|
.lsu2tdu_dmon_o (lsu2tdu_dmon_o ),
|
770 |
|
|
.tdu2lsu_ibrkpt_exc_req_i (tdu2lsu_ibrkpt_exc_req_i),
|
771 |
|
|
.tdu2lsu_dbrkpt_exc_req_i (tdu2lsu_dbrkpt_exc_req_i),
|
772 |
|
|
`endif // SCR1_TDU_EN
|
773 |
|
|
|
774 |
|
|
// Data memory interface
|
775 |
|
|
.lsu2dmem_req_o (exu2dmem_req_o ), // DMEM request
|
776 |
|
|
.lsu2dmem_cmd_o (exu2dmem_cmd_o ), // DMEM command
|
777 |
|
|
.lsu2dmem_width_o (exu2dmem_width_o ), // DMEM width
|
778 |
|
|
.lsu2dmem_addr_o (exu2dmem_addr_o ), // DMEM address
|
779 |
|
|
.lsu2dmem_wdata_o (exu2dmem_wdata_o ), // DMEM write data
|
780 |
|
|
.dmem2lsu_req_ack_i (dmem2exu_req_ack_i ), // DMEM request acknowledge
|
781 |
|
|
.dmem2lsu_rdata_i (dmem2exu_rdata_i ), // DMEM read data
|
782 |
|
|
.dmem2lsu_resp_i (dmem2exu_resp_i ) // DMEM response
|
783 |
|
|
);
|
784 |
|
|
|
785 |
|
|
//------------------------------------------------------------------------------
|
786 |
|
|
// EXU status logic
|
787 |
|
|
//------------------------------------------------------------------------------
|
788 |
|
|
|
789 |
|
|
// EXU ready flag
|
790 |
|
|
always_comb begin
|
791 |
|
|
case (1'b1)
|
792 |
|
|
lsu_req : exu_rdy = lsu_rdy | lsu_exc_req;
|
793 |
|
|
`ifdef SCR1_RVM_EXT
|
794 |
|
|
ialu_vd : exu_rdy = ialu_rdy;
|
795 |
|
|
`endif // SCR1_RVM_EXT
|
796 |
|
|
csr2exu_mstatus_mie_up_i: exu_rdy = 1'b0;
|
797 |
|
|
default : exu_rdy = 1'b1;
|
798 |
|
|
endcase
|
799 |
|
|
end
|
800 |
|
|
|
801 |
|
|
assign exu2pipe_init_pc_o = init_pc;
|
802 |
|
|
assign exu2idu_rdy_o = exu_rdy & ~exu_queue_barrier;
|
803 |
|
|
assign exu2pipe_exu_busy_o = exu_queue_vd & ~exu_rdy;
|
804 |
|
|
assign exu2pipe_instret_o = exu_queue_vd & exu_rdy;
|
805 |
|
|
assign exu2csr_instret_no_exc_o = exu2pipe_instret_o & ~exu_exc_req;
|
806 |
|
|
|
807 |
|
|
// Exceptions
|
808 |
|
|
`ifdef SCR1_DBG_EN
|
809 |
|
|
assign exu2pipe_exc_req_o = exu_queue_vd ? exu_exc_req : exu_exc_req_ff;
|
810 |
|
|
`else // SCR1_DBG_EN
|
811 |
|
|
assign exu2pipe_exc_req_o = exu_exc_req;
|
812 |
|
|
`endif // SCR1_DBG_EN
|
813 |
|
|
|
814 |
|
|
// Breakpoints
|
815 |
|
|
assign exu2pipe_brkpt_o = exu_queue_vd & (exu_queue.exc_code == SCR1_EXC_CODE_BREAKPOINT);
|
816 |
|
|
`ifdef SCR1_TDU_EN
|
817 |
|
|
assign exu2hdu_ibrkpt_hw_o = tdu2exu_ibrkpt_exc_req_i | tdu2lsu_dbrkpt_exc_req_i;
|
818 |
|
|
`endif // SCR1_TDU_EN
|
819 |
|
|
|
820 |
|
|
//------------------------------------------------------------------------------
|
821 |
|
|
// EXU <-> MPRF interface
|
822 |
|
|
//------------------------------------------------------------------------------
|
823 |
|
|
|
824 |
|
|
// Operands fetching stage
|
825 |
|
|
//------------------------------------------------------------------------------
|
826 |
|
|
|
827 |
|
|
`ifdef SCR1_NO_EXE_STAGE
|
828 |
|
|
assign mprf_rs1_req = exu_queue_vd & idu2exu_use_rs1_i;
|
829 |
|
|
assign mprf_rs2_req = exu_queue_vd & idu2exu_use_rs2_i;
|
830 |
|
|
`else // SCR1_NO_EXE_STAGE
|
831 |
|
|
`ifdef SCR1_MPRF_RAM
|
832 |
|
|
assign mprf_rs1_req = exu_queue_en
|
833 |
|
|
? (exu_queue_vd_next & idu2exu_use_rs1_i)
|
834 |
|
|
: (exu_queue_vd & idu2exu_use_rs1_ff);
|
835 |
|
|
assign mprf_rs2_req = exu_queue_en
|
836 |
|
|
? (exu_queue_vd_next & idu2exu_use_rs2_i)
|
837 |
|
|
: (exu_queue_vd & idu2exu_use_rs2_ff);
|
838 |
|
|
`else // SCR1_MPRF_RAM
|
839 |
|
|
assign mprf_rs1_req = exu_queue_vd & idu2exu_use_rs1_ff;
|
840 |
|
|
assign mprf_rs2_req = exu_queue_vd & idu2exu_use_rs2_ff;
|
841 |
|
|
`endif // SCR1_MPRF_RAM
|
842 |
|
|
`endif // SCR1_NO_EXE_STAGE
|
843 |
|
|
|
844 |
|
|
// If exu_queue isn't enabled we need previous addresses and usage flags because
|
845 |
|
|
// RAM blocks read operation is SYNCHRONOUS
|
846 |
|
|
`ifdef SCR1_MPRF_RAM
|
847 |
|
|
assign mprf_rs1_addr = exu_queue_en ? idu2exu_cmd_i.rs1_addr : exu_queue.rs1_addr;
|
848 |
|
|
assign mprf_rs2_addr = exu_queue_en ? idu2exu_cmd_i.rs2_addr : exu_queue.rs2_addr;
|
849 |
|
|
`else // SCR1_MPRF_RAM
|
850 |
|
|
assign mprf_rs1_addr = exu_queue.rs1_addr;
|
851 |
|
|
assign mprf_rs2_addr = exu_queue.rs2_addr;
|
852 |
|
|
`endif // SCR1_MPRF_RAM
|
853 |
|
|
|
854 |
|
|
assign exu2mprf_rs1_addr_o = mprf_rs1_req ? `SCR1_MPRF_AWIDTH'(mprf_rs1_addr) : '0;
|
855 |
|
|
assign exu2mprf_rs2_addr_o = mprf_rs2_req ? `SCR1_MPRF_AWIDTH'(mprf_rs2_addr) : '0;
|
856 |
|
|
|
857 |
|
|
// Write back stage
|
858 |
|
|
//------------------------------------------------------------------------------
|
859 |
|
|
|
860 |
|
|
assign exu2mprf_w_req_o = (exu_queue.rd_wb_sel != SCR1_RD_WB_NONE) & exu_queue_vd & ~exu_exc_req
|
861 |
|
|
`ifdef SCR1_DBG_EN
|
862 |
|
|
& ~hdu2exu_no_commit_i
|
863 |
|
|
`endif // SCR1_DBG_EN
|
864 |
|
|
& ((exu_queue.rd_wb_sel == SCR1_RD_WB_CSR) ? csr_access_init : exu_rdy);
|
865 |
|
|
|
866 |
|
|
assign exu2mprf_rd_addr_o = `SCR1_MPRF_AWIDTH'(exu_queue.rd_addr);
|
867 |
|
|
|
868 |
|
|
// MRPF RD data multiplexer
|
869 |
|
|
always_comb begin
|
870 |
|
|
case (exu_queue.rd_wb_sel)
|
871 |
|
|
SCR1_RD_WB_SUM2 : exu2mprf_rd_data_o = ialu_addr_res;
|
872 |
|
|
SCR1_RD_WB_IMM : exu2mprf_rd_data_o = exu_queue.imm;
|
873 |
|
|
SCR1_RD_WB_INC_PC: exu2mprf_rd_data_o = inc_pc;
|
874 |
|
|
SCR1_RD_WB_LSU : exu2mprf_rd_data_o = lsu_l_data;
|
875 |
|
|
SCR1_RD_WB_CSR : exu2mprf_rd_data_o = csr2exu_r_data_i;
|
876 |
|
|
default : exu2mprf_rd_data_o = ialu_main_res;
|
877 |
|
|
endcase
|
878 |
|
|
end
|
879 |
|
|
|
880 |
|
|
//------------------------------------------------------------------------------
|
881 |
|
|
// EXU <-> CSR interface
|
882 |
|
|
//------------------------------------------------------------------------------
|
883 |
|
|
//
|
884 |
|
|
// EXU <-> CSR interface consists of the following functional units:
|
885 |
|
|
// - CSR write/read interface
|
886 |
|
|
// - CSR access FSM
|
887 |
|
|
// - CSR events interface:
|
888 |
|
|
// - Exceptions signals
|
889 |
|
|
// - Interrupts signals
|
890 |
|
|
// - MRET signals
|
891 |
|
|
//
|
892 |
|
|
|
893 |
|
|
// CSRs write/read interface
|
894 |
|
|
//------------------------------------------------------------------------------
|
895 |
|
|
|
896 |
|
|
// CSR write/read request signals calculation
|
897 |
|
|
always_comb begin
|
898 |
|
|
if (~exu_queue_vd
|
899 |
|
|
`ifdef SCR1_TDU_EN
|
900 |
|
|
| tdu2exu_ibrkpt_exc_req_i
|
901 |
|
|
`endif // SCR1_TDU_EN
|
902 |
|
|
) begin
|
903 |
|
|
exu2csr_r_req_o = 1'b0;
|
904 |
|
|
exu2csr_w_req_o = 1'b0;
|
905 |
|
|
end else begin
|
906 |
|
|
case (exu_queue.csr_cmd)
|
907 |
|
|
SCR1_CSR_CMD_WRITE : begin
|
908 |
|
|
exu2csr_r_req_o = |exu_queue.rd_addr;
|
909 |
|
|
exu2csr_w_req_o = csr_access_init;
|
910 |
|
|
end
|
911 |
|
|
SCR1_CSR_CMD_SET,
|
912 |
|
|
SCR1_CSR_CMD_CLEAR : begin
|
913 |
|
|
exu2csr_r_req_o = 1'b1;
|
914 |
|
|
exu2csr_w_req_o = |exu_queue.rs1_addr & csr_access_init;
|
915 |
|
|
end
|
916 |
|
|
default : begin
|
917 |
|
|
exu2csr_r_req_o = 1'b0;
|
918 |
|
|
exu2csr_w_req_o = 1'b0;
|
919 |
|
|
end
|
920 |
|
|
endcase
|
921 |
|
|
end
|
922 |
|
|
end
|
923 |
|
|
|
924 |
|
|
assign exu2csr_w_cmd_o = exu_queue.csr_cmd;
|
925 |
|
|
assign exu2csr_rw_addr_o = exu_queue.imm[SCR1_CSR_ADDR_WIDTH-1:0];
|
926 |
|
|
assign exu2csr_w_data_o = (exu_queue.csr_op == SCR1_CSR_OP_REG)
|
927 |
|
|
? mprf2exu_rs1_data_i
|
928 |
|
|
: {'0, exu_queue.rs1_addr}; // zimm
|
929 |
|
|
|
930 |
|
|
|
931 |
|
|
// CSR access FSM
|
932 |
|
|
//------------------------------------------------------------------------------
|
933 |
|
|
|
934 |
|
|
always_ff @(posedge clk, negedge rst_n) begin
|
935 |
|
|
if (~rst_n) begin
|
936 |
|
|
csr_access_ff <= SCR1_CSR_INIT;
|
937 |
|
|
end else begin
|
938 |
|
|
csr_access_ff <= csr_access_next;
|
939 |
|
|
end
|
940 |
|
|
end
|
941 |
|
|
|
942 |
|
|
assign csr_access_next = (csr_access_init & csr2exu_mstatus_mie_up_i)
|
943 |
|
|
? SCR1_CSR_RDY
|
944 |
|
|
: SCR1_CSR_INIT;
|
945 |
|
|
|
946 |
|
|
assign csr_access_init = (csr_access_ff == SCR1_CSR_INIT);
|
947 |
|
|
|
948 |
|
|
// CSR events interface
|
949 |
|
|
//------------------------------------------------------------------------------
|
950 |
|
|
|
951 |
|
|
// Exceptions signals
|
952 |
|
|
assign exu2csr_take_exc_o = exu_exc_req
|
953 |
|
|
`ifdef SCR1_DBG_EN
|
954 |
|
|
& ~hdu2exu_dbg_halted_i
|
955 |
|
|
`endif // SCR1_DBG_EN
|
956 |
|
|
;
|
957 |
|
|
assign exu2csr_exc_code_o = exc_code;
|
958 |
|
|
assign exu2csr_trap_val_o = exc_trap_val;
|
959 |
|
|
|
960 |
|
|
// Interrupts signals
|
961 |
|
|
assign exu2csr_take_irq_o = csr2exu_irq_i & ~exu2pipe_exu_busy_o
|
962 |
|
|
`ifdef SCR1_DBG_EN
|
963 |
|
|
& ~hdu2exu_irq_dsbl_i
|
964 |
|
|
& ~hdu2exu_dbg_halted_i
|
965 |
|
|
`endif // SCR1_DBG_EN
|
966 |
|
|
`ifdef SCR1_CLKCTRL_EN
|
967 |
|
|
& clk_pipe_en
|
968 |
|
|
`endif // SCR1_CLKCTRL_EN
|
969 |
|
|
;
|
970 |
|
|
|
971 |
|
|
// MRET signals
|
972 |
|
|
// MRET instruction flag
|
973 |
|
|
assign exu2csr_mret_instr_o = exu_queue_vd & exu_queue.mret_req
|
974 |
|
|
`ifdef SCR1_TDU_EN
|
975 |
|
|
& ~tdu2exu_ibrkpt_exc_req_i
|
976 |
|
|
`endif // SCR1_TDU_EN
|
977 |
|
|
`ifdef SCR1_DBG_EN
|
978 |
|
|
& ~hdu2exu_dbg_halted_i
|
979 |
|
|
`endif // SCR1_DBG_EN
|
980 |
|
|
;
|
981 |
|
|
assign exu2csr_mret_update_o = exu2csr_mret_instr_o & csr_access_init;
|
982 |
|
|
|
983 |
|
|
`ifdef SCR1_TDU_EN
|
984 |
|
|
//------------------------------------------------------------------------------
|
985 |
|
|
// EXU <-> TDU interface
|
986 |
|
|
//------------------------------------------------------------------------------
|
987 |
|
|
|
988 |
|
|
// Instruction monitor
|
989 |
|
|
assign exu2tdu_imon_o.vd = exu_queue_vd;
|
990 |
|
|
assign exu2tdu_imon_o.req = exu2pipe_instret_o;
|
991 |
|
|
assign exu2tdu_imon_o.addr = pc_curr_ff;
|
992 |
|
|
|
993 |
|
|
always_comb begin
|
994 |
|
|
exu2tdu_ibrkpt_ret_o = '0;
|
995 |
|
|
if (exu_queue_vd) begin
|
996 |
|
|
exu2tdu_ibrkpt_ret_o = tdu2exu_ibrkpt_match_i;
|
997 |
|
|
if (lsu_req) begin
|
998 |
|
|
exu2tdu_ibrkpt_ret_o[SCR1_TDU_MTRIG_NUM-1:0] |= tdu2lsu_dbrkpt_match_i;
|
999 |
|
|
end
|
1000 |
|
|
end
|
1001 |
|
|
end
|
1002 |
|
|
`endif // SCR1_TDU_EN
|
1003 |
|
|
|
1004 |
|
|
|
1005 |
|
|
`ifdef SCR1_TRGT_SIMULATION
|
1006 |
|
|
//------------------------------------------------------------------------------
|
1007 |
|
|
// Tracelog signals
|
1008 |
|
|
//------------------------------------------------------------------------------
|
1009 |
|
|
|
1010 |
|
|
logic [`SCR1_XLEN-1:0] update_pc;
|
1011 |
|
|
logic update_pc_en;
|
1012 |
|
|
|
1013 |
|
|
assign update_pc_en = (init_pc | exu2pipe_instret_o | exu2csr_take_irq_o)
|
1014 |
|
|
`ifdef SCR1_DBG_EN
|
1015 |
|
|
& ~hdu2exu_pc_advmt_dsbl_i & ~hdu2exu_no_commit_i
|
1016 |
|
|
`endif // SCR1_DBG_EN
|
1017 |
|
|
;
|
1018 |
|
|
assign update_pc = exu2ifu_pc_new_req_o ? exu2ifu_pc_new_o : inc_pc;
|
1019 |
|
|
|
1020 |
|
|
|
1021 |
|
|
//------------------------------------------------------------------------------
|
1022 |
|
|
// Assertion
|
1023 |
|
|
//------------------------------------------------------------------------------
|
1024 |
|
|
|
1025 |
|
|
// X checks
|
1026 |
|
|
|
1027 |
|
|
SCR1_SVA_EXU_XCHECK_CTRL : assert property (
|
1028 |
|
|
@(negedge clk) disable iff (~rst_n)
|
1029 |
|
|
!$isunknown({idu2exu_req_i, csr2exu_irq_i, csr2exu_ip_ie_i, lsu_req, lsu_rdy, exu_exc_req})
|
1030 |
|
|
) else $error("EXU Error: unknown control values");
|
1031 |
|
|
|
1032 |
|
|
SCR1_SVA_EXU_XCHECK_QUEUE : assert property (
|
1033 |
|
|
@(negedge clk) disable iff (~rst_n)
|
1034 |
|
|
idu2exu_req_i |-> !$isunknown(idu2exu_cmd_i)
|
1035 |
|
|
) else $error("EXU Error: unknown values in queue");
|
1036 |
|
|
|
1037 |
|
|
SCR1_SVA_EXU_XCHECK_CSR_RDATA : assert property (
|
1038 |
|
|
@(negedge clk) disable iff (~rst_n)
|
1039 |
|
|
exu2csr_r_req_o |-> !$isunknown({csr2exu_r_data_i, csr2exu_rw_exc_i})
|
1040 |
|
|
) else $error("EXU Error: unknown values from CSR");
|
1041 |
|
|
|
1042 |
|
|
// Behavior checks
|
1043 |
|
|
|
1044 |
|
|
SCR1_SVA_EXU_ONEHOT : assert property (
|
1045 |
|
|
@(negedge clk) disable iff (~rst_n)
|
1046 |
|
|
$onehot0({exu_queue.jump_req, exu_queue.branch_req, lsu_req})
|
1047 |
|
|
) else $error("EXU Error: illegal combination of control signals");
|
1048 |
|
|
|
1049 |
|
|
SCR1_SVA_EXU_ONEHOT_EXC : assert property (
|
1050 |
|
|
@(negedge clk) disable iff (~rst_n)
|
1051 |
|
|
exu_queue_vd |->
|
1052 |
|
|
$onehot0({exu_queue.exc_req, lsu_exc_req, csr2exu_rw_exc_i
|
1053 |
|
|
`ifndef SCR1_RVC_EXT
|
1054 |
|
|
, jb_misalign
|
1055 |
|
|
`endif
|
1056 |
|
|
})
|
1057 |
|
|
) else $error("EXU Error: exceptions $onehot0 failed");
|
1058 |
|
|
|
1059 |
|
|
`endif // SCR1_TRGT_SIMULATION
|
1060 |
|
|
|
1061 |
|
|
endmodule : scr1_pipe_exu
|