blob: f691743a3d6560727e90dbd19b015446181a1c3b [file] [log] [blame]
Philipp Wagner31441082020-07-14 11:17:21 +01001// Copyright lowRISC contributors.
2// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3// SPDX-License-Identifier: Apache-2.0
4
5`include "prim_assert.sv"
6
7/**
8 * OTBN Controller
9 */
10module otbn_controller
11 import otbn_pkg::*;
12#(
13 // Size of the instruction memory, in bytes
14 parameter int ImemSizeByte = 4096,
15 // Size of the data memory, in bytes
16 parameter int DmemSizeByte = 4096,
17
18 localparam int ImemAddrWidth = prim_util_pkg::vbits(ImemSizeByte),
19 localparam int DmemAddrWidth = prim_util_pkg::vbits(DmemSizeByte)
20) (
21 input logic clk_i,
22 input logic rst_ni,
23
Rupert Swarbrick2fb857a2021-09-03 17:14:50 +010024 input logic start_i, // start the processing at address zero
Greg Chadwickd3154ec2020-09-24 12:03:23 +010025 output logic done_o, // processing done, signaled by ECALL or error occurring
Greg Chadwick79738062021-09-15 18:09:14 +010026 output logic locked_o, // OTBN in locked state and must be reset to perform any further actions
Greg Chadwickd3154ec2020-09-24 12:03:23 +010027
Greg Chadwick5ce1cb72021-01-13 14:20:48 +000028 output err_bits_t err_bits_o, // valid when done_o is asserted
Greg Chadwickd3154ec2020-09-24 12:03:23 +010029
Philipp Wagner31441082020-07-14 11:17:21 +010030 // Next instruction selection (to instruction fetch)
31 output logic insn_fetch_req_valid_o,
32 output logic [ImemAddrWidth-1:0] insn_fetch_req_addr_o,
Greg Chadwickd3154ec2020-09-24 12:03:23 +010033 // Error from fetch requested last cycle
34 input logic insn_fetch_err_i,
Philipp Wagner31441082020-07-14 11:17:21 +010035
36 // Fetched/decoded instruction
37 input logic insn_valid_i,
Greg Chadwickd3154ec2020-09-24 12:03:23 +010038 input logic insn_illegal_i,
Philipp Wagner31441082020-07-14 11:17:21 +010039 input logic [ImemAddrWidth-1:0] insn_addr_i,
Philipp Wagner31441082020-07-14 11:17:21 +010040
Philipp Wagner56a64bd2021-05-08 14:31:24 +010041 // Decoded instruction data
Philipp Wagner31441082020-07-14 11:17:21 +010042 input insn_dec_base_t insn_dec_base_i,
Greg Chadwickf7863442020-09-14 18:11:33 +010043 input insn_dec_bignum_t insn_dec_bignum_i,
44 input insn_dec_shared_t insn_dec_shared_i,
Philipp Wagner31441082020-07-14 11:17:21 +010045
46 // Base register file
Greg Chadwickee060bd2021-05-15 17:33:22 +010047 output logic [4:0] rf_base_wr_addr_o,
48 output logic rf_base_wr_en_o,
49 output logic rf_base_wr_commit_o,
50 output logic [31:0] rf_base_wr_data_no_intg_o,
51 output logic [BaseIntgWidth-1:0] rf_base_wr_data_intg_o,
52 output logic rf_base_wr_data_intg_sel_o,
Philipp Wagner31441082020-07-14 11:17:21 +010053
Greg Chadwick009d9ee2021-04-26 16:25:51 +010054 output logic [4:0] rf_base_rd_addr_a_o,
55 output logic rf_base_rd_en_a_o,
56 input logic [BaseIntgWidth-1:0] rf_base_rd_data_a_intg_i,
57 output logic [4:0] rf_base_rd_addr_b_o,
58 output logic rf_base_rd_en_b_o,
59 input logic [BaseIntgWidth-1:0] rf_base_rd_data_b_intg_i,
60 output logic rf_base_rd_commit_o,
Philipp Wagner31441082020-07-14 11:17:21 +010061
Greg Chadwickd3154ec2020-09-24 12:03:23 +010062 input logic rf_base_call_stack_err_i,
Greg Chadwick009d9ee2021-04-26 16:25:51 +010063 input logic rf_base_rd_data_err_i,
Greg Chadwickd3154ec2020-09-24 12:03:23 +010064
Greg Chadwickf7863442020-09-14 18:11:33 +010065 // Bignum register file (WDRs)
Greg Chadwick009d9ee2021-04-26 16:25:51 +010066 output logic [4:0] rf_bignum_wr_addr_o,
67 output logic [1:0] rf_bignum_wr_en_o,
68 output logic [WLEN-1:0] rf_bignum_wr_data_no_intg_o,
69 output logic [ExtWLEN-1:0] rf_bignum_wr_data_intg_o,
70 output logic rf_bignum_wr_data_intg_sel_o,
Greg Chadwickf7863442020-09-14 18:11:33 +010071
Greg Chadwick009d9ee2021-04-26 16:25:51 +010072 output logic [4:0] rf_bignum_rd_addr_a_o,
73 output logic rf_bignum_rd_en_a_o,
74 input logic [ExtWLEN-1:0] rf_bignum_rd_data_a_intg_i,
Greg Chadwickf7863442020-09-14 18:11:33 +010075
Greg Chadwick009d9ee2021-04-26 16:25:51 +010076 output logic [4:0] rf_bignum_rd_addr_b_o,
77 output logic rf_bignum_rd_en_b_o,
78 input logic [ExtWLEN-1:0] rf_bignum_rd_data_b_intg_i,
79
80 input logic rf_bignum_rd_data_err_i,
Greg Chadwickf7863442020-09-14 18:11:33 +010081
Philipp Wagner31441082020-07-14 11:17:21 +010082 // Execution units
Greg Chadwickf7863442020-09-14 18:11:33 +010083
84 // Base ALU
Greg Chadwick9791eed2020-07-22 18:08:28 +010085 output alu_base_operation_t alu_base_operation_o,
86 output alu_base_comparison_t alu_base_comparison_o,
87 input logic [31:0] alu_base_operation_result_i,
Greg Chadwickc8cd4352020-08-14 16:45:23 +010088 input logic alu_base_comparison_result_i,
89
Greg Chadwickf7863442020-09-14 18:11:33 +010090 // Bignum ALU
91 output alu_bignum_operation_t alu_bignum_operation_o,
92 input logic [WLEN-1:0] alu_bignum_operation_result_i,
Greg Chadwick009d9ee2021-04-26 16:25:51 +010093 input logic alu_bignum_selection_flag_i,
Greg Chadwickf7863442020-09-14 18:11:33 +010094
Greg Chadwick94786452020-10-28 18:19:51 +000095 // Bignum MAC
96 output mac_bignum_operation_t mac_bignum_operation_o,
97 input logic [WLEN-1:0] mac_bignum_operation_result_i,
98 output logic mac_bignum_en_o,
99
Greg Chadwickf7863442020-09-14 18:11:33 +0100100 // LSU
Greg Chadwickc8cd4352020-08-14 16:45:23 +0100101 output logic lsu_load_req_o,
102 output logic lsu_store_req_o,
103 output insn_subset_e lsu_req_subset_o,
104 output logic [DmemAddrWidth-1:0] lsu_addr_o,
105
Greg Chadwickee060bd2021-05-15 17:33:22 +0100106 output logic [BaseIntgWidth-1:0] lsu_base_wdata_o,
107 output logic [ExtWLEN-1:0] lsu_bignum_wdata_o,
Greg Chadwickc8cd4352020-08-14 16:45:23 +0100108
Greg Chadwickee060bd2021-05-15 17:33:22 +0100109 input logic [BaseIntgWidth-1:0] lsu_base_rdata_i,
110 input logic [ExtWLEN-1:0] lsu_bignum_rdata_i,
Rupert Swarbrick40cd9142020-12-02 11:02:17 +0000111 input logic lsu_rdata_err_i,
Greg Chadwickf7863442020-09-14 18:11:33 +0100112
113 // Internal Special-Purpose Registers (ISPRs)
114 output ispr_e ispr_addr_o,
115 output logic [31:0] ispr_base_wdata_o,
116 output logic [BaseWordsPerWLEN-1:0] ispr_base_wr_en_o,
117 output logic [WLEN-1:0] ispr_bignum_wdata_o,
118 output logic ispr_bignum_wr_en_o,
Greg Chadwickb168ae92021-04-14 16:04:03 +0100119 input logic [WLEN-1:0] ispr_rdata_i,
120
121 output logic rnd_req_o,
122 output logic rnd_prefetch_req_o,
Vladimir Rozicb8db07a2021-05-24 14:15:04 +0100123 input logic rnd_valid_i,
124
Rupert Swarbrick13d50082021-07-13 14:14:03 +0100125 input logic state_reset_i,
Greg Chadwickf0a30192021-08-19 09:33:25 +0100126 output logic [31:0] insn_cnt_o,
Philipp Wagnerb1589332021-09-20 15:50:19 +0100127 input logic bus_intg_violation_i,
Philipp Wagnerc74ba0a2021-08-23 12:56:11 +0200128 input logic illegal_bus_access_i,
129 input logic lifecycle_escalation_i
Philipp Wagner31441082020-07-14 11:17:21 +0100130);
Greg Chadwickd3154ec2020-09-24 12:03:23 +0100131 otbn_state_e state_q, state_d, state_raw;
132
133 logic err;
Greg Chadwick79738062021-09-15 18:09:14 +0100134 logic fatal_err;
Greg Chadwickd3154ec2020-09-24 12:03:23 +0100135 logic done_complete;
Rupert Swarbrick692db552021-09-24 16:26:31 +0100136 logic executing;
Greg Chadwickd3154ec2020-09-24 12:03:23 +0100137
138 logic insn_fetch_req_valid_raw;
Greg Chadwick28836af2020-07-23 14:35:52 +0100139
Greg Chadwickc8cd4352020-08-14 16:45:23 +0100140 logic stall;
Greg Chadwickb168ae92021-04-14 16:04:03 +0100141 logic ispr_stall;
Greg Chadwickc8cd4352020-08-14 16:45:23 +0100142 logic mem_stall;
Rupert Swarbrickb2b784d2021-08-03 14:21:51 +0100143 logic jump_or_branch;
Greg Chadwick51f36232020-09-02 15:37:23 +0100144 logic branch_taken;
Greg Chadwick42a9f3b2021-01-28 13:54:14 +0000145 logic insn_executing;
Greg Chadwick51f36232020-09-02 15:37:23 +0100146 logic [ImemAddrWidth-1:0] branch_target;
Greg Chadwickd3154ec2020-09-24 12:03:23 +0100147 logic branch_target_overflow;
Rupert Swarbricke9ff47f2021-01-04 13:20:36 +0000148 logic [ImemAddrWidth:0] next_insn_addr_wide;
Greg Chadwick51f36232020-09-02 15:37:23 +0100149 logic [ImemAddrWidth-1:0] next_insn_addr;
Greg Chadwickc8cd4352020-08-14 16:45:23 +0100150
Greg Chadwickf7863442020-09-14 18:11:33 +0100151 csr_e csr_addr;
Philipp Wagner711d2262021-01-21 18:17:42 +0000152 logic [$clog2(BaseWordsPerWLEN)-1:0] csr_sub_addr;
Greg Chadwickdbd655a2020-11-24 16:42:06 +0000153 logic [31:0] csr_rdata_raw;
Greg Chadwickf7863442020-09-14 18:11:33 +0100154 logic [31:0] csr_rdata;
155 logic [BaseWordsPerWLEN-1:0] csr_rdata_mux [32];
Greg Chadwickdbd655a2020-11-24 16:42:06 +0000156 logic [31:0] csr_wdata_raw;
Greg Chadwickf7863442020-09-14 18:11:33 +0100157 logic [31:0] csr_wdata;
158
159 wsr_e wsr_addr;
160 logic [WLEN-1:0] wsr_wdata;
161
162 ispr_e ispr_addr_base;
163 logic [$clog2(BaseWordsPerWLEN)-1:0] ispr_word_addr_base;
164 logic [BaseWordsPerWLEN-1:0] ispr_word_sel_base;
165
166 ispr_e ispr_addr_bignum;
167
Greg Chadwickb168ae92021-04-14 16:04:03 +0100168 logic ispr_wr_insn, ispr_rd_insn;
Rupert Swarbrick514348e2021-02-03 09:04:59 +0000169 logic ispr_wr_base_insn;
170 logic ispr_wr_bignum_insn;
Greg Chadwickf7863442020-09-14 18:11:33 +0100171
Greg Chadwick42a9f3b2021-01-28 13:54:14 +0000172 logic lsu_load_req_raw;
173 logic lsu_store_req_raw;
174
Greg Chadwick009d9ee2021-04-26 16:25:51 +0100175 // Register read data with integrity stripped off
176 logic [31:0] rf_base_rd_data_a_no_intg;
177 logic [31:0] rf_base_rd_data_b_no_intg;
178 logic [WLEN-1:0] rf_bignum_rd_data_a_no_intg;
179 logic [WLEN-1:0] rf_bignum_rd_data_b_no_intg;
180
181 logic [ExtWLEN-1:0] selection_result;
182
Greg Chadwickae8e6452020-10-02 12:04:15 +0100183 // Computed increments for indirect register index and memory address in BN.LID/BN.SID/BN.MOVR
184 // instructions.
Greg Chadwick496fd342021-03-05 18:08:39 +0000185 logic [5:0] rf_base_rd_data_a_inc;
186 logic [5:0] rf_base_rd_data_b_inc;
Rupert Swarbrick9a4f47b2021-01-04 15:48:24 +0000187 logic [26:0] rf_base_rd_data_a_wlen_word_inc;
Greg Chadwickae8e6452020-10-02 12:04:15 +0100188
Greg Chadwick1a1c0112021-09-14 16:27:31 +0100189 // Read/Write enables for base register file before illegal instruction encoding are factored in
190 logic rf_base_rd_en_a_raw, rf_base_rd_en_b_raw, rf_base_wr_en_raw;
191
Greg Chadwickae8e6452020-10-02 12:04:15 +0100192 // Output of mux taking the above increments as inputs and choosing one to write back to base
193 // register file with appropriate zero extension and padding to give a 32-bit result.
194 logic [31:0] increment_out;
195
Greg Chadwick53c95862020-10-14 17:58:38 +0100196 // Loop control, used to start a new loop
Greg Chadwick42a9f3b2021-01-28 13:54:14 +0000197 logic loop_start_req;
198 logic loop_start_commit;
Greg Chadwick53c95862020-10-14 17:58:38 +0100199 logic [11:0] loop_bodysize;
200 logic [31:0] loop_iterations;
201
202 // Loop generated jumps. The loop controller asks to jump when execution reaches the end of a loop
203 // body that hasn't completed all of its iterations.
204 logic loop_jump;
205 logic [ImemAddrWidth-1:0] loop_jump_addr;
206
Greg Chadwick94786452020-10-28 18:19:51 +0000207 logic [WLEN-1:0] mac_bignum_rf_wr_data;
208
Greg Chadwickd3154ec2020-09-24 12:03:23 +0100209 logic csr_illegal_addr, wsr_illegal_addr, ispr_illegal_addr;
210 logic imem_addr_err, loop_err, ispr_err;
211 logic dmem_addr_err, dmem_addr_unaligned_base, dmem_addr_unaligned_bignum, dmem_addr_overflow;
Greg Chadwick1a1c0112021-09-14 16:27:31 +0100212 logic illegal_insn_static;
Greg Chadwickd3154ec2020-09-24 12:03:23 +0100213
Greg Chadwick496fd342021-03-05 18:08:39 +0000214 logic rf_a_indirect_err, rf_b_indirect_err, rf_d_indirect_err, rf_indirect_err;
215
Vladimir Rozicb8db07a2021-05-24 14:15:04 +0100216 logic insn_cnt_en;
217 logic [31:0] insn_cnt_d, insn_cnt_q;
218
Greg Chadwick9a6fc462021-08-10 15:42:16 +0100219 logic [4:0] ld_insn_bignum_wr_addr_q;
220
Greg Chadwickc8cd4352020-08-14 16:45:23 +0100221 // Stall a cycle on loads to allow load data writeback to happen the following cycle. Stall not
222 // required on stores as there is no response to deal with.
223 // TODO: Possibility of error response on store? Probably still don't need to stall in that case
224 // just ensure incoming store error stops anything else happening.
Greg Chadwick42a9f3b2021-01-28 13:54:14 +0000225 assign mem_stall = lsu_load_req_raw;
Greg Chadwickc8cd4352020-08-14 16:45:23 +0100226
Greg Chadwickb168ae92021-04-14 16:04:03 +0100227 // Reads to RND must stall until data is available
228 assign ispr_stall = rnd_req_o & ~rnd_valid_i;
229
230 assign stall = mem_stall | ispr_stall;
Greg Chadwickd3154ec2020-09-24 12:03:23 +0100231
Rupert Swarbrick692db552021-09-24 16:26:31 +0100232 // OTBN is done when it was executing something (in state OtbnStateUrndRefresh, OtbnStateRun or
233 // OtbnStateStall) and either it executes an ecall or an error occurs. A pulse on the done signal
234 // raises the 'done' interrupt and also tells the top-level to update its err_bits status
235 // register.
236 //
237 // The calculation that ecall triggered done is factored out as `done_complete` to avoid logic
238 // loops in the error handling logic.
Greg Chadwickd3154ec2020-09-24 12:03:23 +0100239 assign done_complete = (insn_valid_i && insn_dec_shared_i.ecall_insn);
Rupert Swarbrick692db552021-09-24 16:26:31 +0100240 assign executing = (state_q == OtbnStateUrndRefresh) ||
241 (state_q == OtbnStateRun) ||
242 (state_q == OtbnStateStall);
243 assign done_o = executing & (done_complete | err);
Greg Chadwick79738062021-09-15 18:09:14 +0100244 assign locked_o = state_q == OtbnStateLocked;
Philipp Wagner31441082020-07-14 11:17:21 +0100245
Rupert Swarbrickb2b784d2021-08-03 14:21:51 +0100246 assign jump_or_branch = (insn_valid_i &
247 (insn_dec_shared_i.branch_insn | insn_dec_shared_i.jump_insn));
248
Greg Chadwick51f36232020-09-02 15:37:23 +0100249 // Branch taken when there is a valid branch instruction and comparison passes or a valid jump
250 // instruction (which is always taken)
Philipp Wagnerdc946522020-12-03 10:52:58 +0000251 assign branch_taken = insn_valid_i &
252 ((insn_dec_shared_i.branch_insn & alu_base_comparison_result_i) |
253 insn_dec_shared_i.jump_insn);
Greg Chadwick51f36232020-09-02 15:37:23 +0100254 // Branch target computed by base ALU (PC + imm)
Greg Chadwick51f36232020-09-02 15:37:23 +0100255 assign branch_target = alu_base_operation_result_i[ImemAddrWidth-1:0];
Greg Chadwickd3154ec2020-09-24 12:03:23 +0100256 assign branch_target_overflow = |alu_base_operation_result_i[31:ImemAddrWidth];
Greg Chadwick51f36232020-09-02 15:37:23 +0100257
Rupert Swarbricke9ff47f2021-01-04 13:20:36 +0000258 assign next_insn_addr_wide = {1'b0, insn_addr_i} + 'd4;
259 assign next_insn_addr = next_insn_addr_wide[ImemAddrWidth-1:0];
Greg Chadwick51f36232020-09-02 15:37:23 +0100260
Philipp Wagner31441082020-07-14 11:17:21 +0100261 always_comb begin
Greg Chadwickd3154ec2020-09-24 12:03:23 +0100262 // `state_raw` and `insn_fetch_req_valid_raw` are the values of `state_d` and
263 // `insn_fetch_req_valid_o` before any errors are considered.
264 state_raw = state_q;
265 insn_fetch_req_valid_raw = 1'b0;
Rupert Swarbrick2fb857a2021-09-03 17:14:50 +0100266 insn_fetch_req_addr_o = '0;
Greg Chadwick28836af2020-07-23 14:35:52 +0100267
Greg Chadwickc8cd4352020-08-14 16:45:23 +0100268 // TODO: Harden state machine
Philipp Wagner31441082020-07-14 11:17:21 +0100269 // TODO: Jumps/branches
Greg Chadwickc8cd4352020-08-14 16:45:23 +0100270 unique case (state_q)
271 OtbnStateHalt: begin
272 if (start_i) begin
Greg Chadwickd3154ec2020-09-24 12:03:23 +0100273 state_raw = OtbnStateRun;
Greg Chadwickb5b86862021-04-09 15:49:43 +0100274
Rupert Swarbrick2fb857a2021-09-03 17:14:50 +0100275 insn_fetch_req_addr_o = '0;
Greg Chadwickd3154ec2020-09-24 12:03:23 +0100276 insn_fetch_req_valid_raw = 1'b1;
Greg Chadwickc8cd4352020-08-14 16:45:23 +0100277 end
278 end
279 OtbnStateRun: begin
Greg Chadwickd3154ec2020-09-24 12:03:23 +0100280 insn_fetch_req_valid_raw = 1'b1;
Greg Chadwickc8cd4352020-08-14 16:45:23 +0100281
Greg Chadwickd3154ec2020-09-24 12:03:23 +0100282 if (done_complete) begin
283 state_raw = OtbnStateHalt;
284 insn_fetch_req_valid_raw = 1'b0;
Greg Chadwickc8cd4352020-08-14 16:45:23 +0100285 end else begin
286 // When stalling refetch the same instruction to keep decode inputs constant
287 if (stall) begin
Greg Chadwickd3154ec2020-09-24 12:03:23 +0100288 state_raw = OtbnStateStall;
Greg Chadwickc8cd4352020-08-14 16:45:23 +0100289 insn_fetch_req_addr_o = insn_addr_i;
290 end else begin
Greg Chadwick51f36232020-09-02 15:37:23 +0100291 if (branch_taken) begin
292 insn_fetch_req_addr_o = branch_target;
Greg Chadwick53c95862020-10-14 17:58:38 +0100293 end else if (loop_jump) begin
294 insn_fetch_req_addr_o = loop_jump_addr;
Greg Chadwick51f36232020-09-02 15:37:23 +0100295 end else begin
296 insn_fetch_req_addr_o = next_insn_addr;
297 end
Greg Chadwickc8cd4352020-08-14 16:45:23 +0100298 end
299 end
300 end
301 OtbnStateStall: begin
Greg Chadwickd3154ec2020-09-24 12:03:23 +0100302 insn_fetch_req_valid_raw = 1'b1;
Greg Chadwick9aef1c92021-01-25 18:24:58 +0000303
Greg Chadwicke6e8f152021-03-05 13:35:36 +0000304 // When stalling refetch the same instruction to keep decode inputs constant
305 if (stall) begin
306 state_raw = OtbnStateStall;
307 insn_fetch_req_addr_o = insn_addr_i;
Greg Chadwick9aef1c92021-01-25 18:24:58 +0000308 end else begin
Greg Chadwicke6e8f152021-03-05 13:35:36 +0000309 if (loop_jump) begin
310 insn_fetch_req_addr_o = loop_jump_addr;
311 end else begin
312 insn_fetch_req_addr_o = next_insn_addr;
313 end
Greg Chadwick9aef1c92021-01-25 18:24:58 +0000314
Greg Chadwicke6e8f152021-03-05 13:35:36 +0000315 state_raw = OtbnStateRun;
316 end
Greg Chadwickc8cd4352020-08-14 16:45:23 +0100317 end
Greg Chadwick79738062021-09-15 18:09:14 +0100318 OtbnStateLocked: begin
319 insn_fetch_req_valid_raw = 1'b0;
320 state_raw = OtbnStateLocked;
321 end
Greg Chadwickc8cd4352020-08-14 16:45:23 +0100322 default: ;
323 endcase
Philipp Wagner31441082020-07-14 11:17:21 +0100324 end
325
Greg Chadwick9aef1c92021-01-25 18:24:58 +0000326 // Anything that moves us or keeps us in the stall state should cause `stall` to be asserted
Philipp Wagnerefa09012021-01-27 14:42:16 +0000327 `ASSERT(StallIfNextStateStall, insn_valid_i & (state_d == OtbnStateStall) |-> stall)
Greg Chadwick9aef1c92021-01-25 18:24:58 +0000328
Greg Chadwickd3154ec2020-09-24 12:03:23 +0100329 // On any error immediately halt and suppress any Imem request.
Greg Chadwick79738062021-09-15 18:09:14 +0100330 assign state_d = fatal_err ? OtbnStateLocked :
331 err ? OtbnStateHalt :
332 state_raw;
333
Greg Chadwickd3154ec2020-09-24 12:03:23 +0100334 assign insn_fetch_req_valid_o = err ? 1'b0 : insn_fetch_req_valid_raw;
335
336 // Determine if there are any errors related to the Imem fetch address.
337 always_comb begin
338 imem_addr_err = 1'b0;
339
340 if (insn_fetch_req_valid_raw) begin
341 if (|insn_fetch_req_addr_o[1:0]) begin
342 // Imem address is unaligned
343 imem_addr_err = 1'b1;
344 end else if (branch_taken) begin
345 imem_addr_err = branch_target_overflow;
346 end else begin
Rupert Swarbricke9ff47f2021-01-04 13:20:36 +0000347 imem_addr_err = next_insn_addr_wide[ImemAddrWidth];
Greg Chadwickd3154ec2020-09-24 12:03:23 +0100348 end
349 end
350 end
351
Greg Chadwick1a1c0112021-09-14 16:27:31 +0100352 // Instruction is illegal based on the static properties of the instruction bits (illegal encoding
353 // or illegal WSR/CSR referenced).
354 assign illegal_insn_static = insn_illegal_i | ispr_err;
355
Philipp Wagner75f76902021-09-17 14:55:35 +0100356 assign err_bits_o.lifecycle_escalation = lifecycle_escalation_i;
357 assign err_bits_o.illegal_bus_access = illegal_bus_access_i;
Philipp Wagnerb1589332021-09-20 15:50:19 +0100358 assign err_bits_o.bus_intg_violation = bus_intg_violation_i;
Philipp Wagner75f76902021-09-17 14:55:35 +0100359 assign err_bits_o.reg_intg_violation = rf_base_rd_data_err_i | rf_bignum_rd_data_err_i;
Philipp Wagner75f76902021-09-17 14:55:35 +0100360 assign err_bits_o.dmem_intg_violation = lsu_rdata_err_i;
Philipp Wagnerb1589332021-09-20 15:50:19 +0100361 assign err_bits_o.imem_intg_violation = insn_fetch_err_i;
Philipp Wagner75f76902021-09-17 14:55:35 +0100362 assign err_bits_o.illegal_insn = illegal_insn_static | rf_indirect_err;
363 assign err_bits_o.bad_data_addr = dmem_addr_err;
364 assign err_bits_o.loop = loop_err;
365 assign err_bits_o.call_stack = rf_base_call_stack_err_i;
366 assign err_bits_o.bad_insn_addr = imem_addr_err;
Greg Chadwickd3154ec2020-09-24 12:03:23 +0100367
Greg Chadwick3bb4f0b2021-02-19 15:07:00 +0000368 assign err = |err_bits_o;
Greg Chadwick79738062021-09-15 18:09:14 +0100369 assign fatal_err = |{err_bits_o.lifecycle_escalation,
370 err_bits_o.illegal_bus_access,
371 err_bits_o.bus_intg_violation,
372 err_bits_o.reg_intg_violation,
373 err_bits_o.dmem_intg_violation,
374 err_bits_o.imem_intg_violation};
Greg Chadwickd3154ec2020-09-24 12:03:23 +0100375
Greg Chadwick42a9f3b2021-01-28 13:54:14 +0000376 // Instructions must not execute if there is an error
377 assign insn_executing = insn_valid_i & ~err;
378
Greg Chadwick5ce1cb72021-01-13 14:20:48 +0000379 `ASSERT(ErrBitSetOnErr, err |-> |err_bits_o)
Greg Chadwick79738062021-09-15 18:09:14 +0100380 `ASSERT(ErrSetOnFatalErr, fatal_err |-> err)
Greg Chadwickd3154ec2020-09-24 12:03:23 +0100381
Greg Chadwickb168ae92021-04-14 16:04:03 +0100382 `ASSERT(ControllerStateValid, state_q inside {OtbnStateHalt, OtbnStateRun,
Rupert Swarbrick3cb910b2021-09-24 16:25:48 +0100383 OtbnStateStall, OtbnStateLocked})
Greg Chadwick51f36232020-09-02 15:37:23 +0100384 // Branch only takes effect in OtbnStateRun so must not go into stall state for branch
385 // instructions.
Philipp Wagnerdc946522020-12-03 10:52:58 +0000386 `ASSERT(NoStallOnBranch,
387 insn_valid_i & insn_dec_shared_i.branch_insn |-> state_q != OtbnStateStall)
Greg Chadwickc8cd4352020-08-14 16:45:23 +0100388
Greg Chadwick28836af2020-07-23 14:35:52 +0100389 always_ff @(posedge clk_i or negedge rst_ni) begin
390 if (!rst_ni) begin
Greg Chadwickc8cd4352020-08-14 16:45:23 +0100391 state_q <= OtbnStateHalt;
Greg Chadwick28836af2020-07-23 14:35:52 +0100392 end else begin
Greg Chadwickc8cd4352020-08-14 16:45:23 +0100393 state_q <= state_d;
Greg Chadwick28836af2020-07-23 14:35:52 +0100394 end
395 end
396
Rupert Swarbrick13d50082021-07-13 14:14:03 +0100397 assign insn_cnt_d = state_reset_i ? 32'd0 : (insn_cnt_q + 32'd1);
398 assign insn_cnt_en = (insn_executing & ~stall & (insn_cnt_q != 32'hffffffff)) | state_reset_i;
Vladimir Rozicb8db07a2021-05-24 14:15:04 +0100399 assign insn_cnt_o = insn_cnt_q;
400
401 always_ff @(posedge clk_i or negedge rst_ni) begin
402 if (!rst_ni) begin
403 insn_cnt_q <= 32'd0;
404 end else if (insn_cnt_en) begin
405 insn_cnt_q <= insn_cnt_d;
406 end
407 end
408
Greg Chadwick53c95862020-10-14 17:58:38 +0100409 otbn_loop_controller #(
410 .ImemAddrWidth(ImemAddrWidth)
411 ) u_otbn_loop_controller (
412 .clk_i,
413 .rst_ni,
414
Rupert Swarbrick13d50082021-07-13 14:14:03 +0100415 .state_reset_i,
416
Greg Chadwickb5163fd2020-11-26 16:48:55 +0000417 .insn_valid_i,
Greg Chadwick53c95862020-10-14 17:58:38 +0100418 .insn_addr_i,
Greg Chadwick42a9f3b2021-01-28 13:54:14 +0000419 .next_insn_addr_i (next_insn_addr),
Greg Chadwick53c95862020-10-14 17:58:38 +0100420
Greg Chadwick42a9f3b2021-01-28 13:54:14 +0000421 .loop_start_req_i (loop_start_req),
422 .loop_start_commit_i (loop_start_commit),
423 .loop_bodysize_i (loop_bodysize),
424 .loop_iterations_i (loop_iterations),
Greg Chadwick53c95862020-10-14 17:58:38 +0100425
Greg Chadwick42a9f3b2021-01-28 13:54:14 +0000426 .loop_jump_o (loop_jump),
427 .loop_jump_addr_o (loop_jump_addr),
428 .loop_err_o (loop_err),
Greg Chadwickb5163fd2020-11-26 16:48:55 +0000429
Rupert Swarbrickb2b784d2021-08-03 14:21:51 +0100430 .jump_or_branch_i (jump_or_branch),
Greg Chadwick42a9f3b2021-01-28 13:54:14 +0000431 .otbn_stall_i (stall)
Greg Chadwick53c95862020-10-14 17:58:38 +0100432 );
433
Greg Chadwick42a9f3b2021-01-28 13:54:14 +0000434 // loop_start_req indicates the instruction wishes to start a loop, loop_start_commit confirms it
435 // should occur.
436 assign loop_start_req = insn_valid_i & insn_dec_shared_i.loop_insn;
437 assign loop_start_commit = insn_executing;
438 assign loop_bodysize = insn_dec_base_i.loop_bodysize;
Rupert Swarbrick514348e2021-02-03 09:04:59 +0000439 assign loop_iterations = insn_dec_base_i.loop_immediate ? insn_dec_base_i.i :
Greg Chadwick009d9ee2021-04-26 16:25:51 +0100440 rf_base_rd_data_a_no_intg;
Greg Chadwick53c95862020-10-14 17:58:38 +0100441
Greg Chadwickae8e6452020-10-02 12:04:15 +0100442 // Compute increments which can be optionally applied to indirect register accesses and memory
443 // addresses in BN.LID/BN.SID/BN.MOVR instructions.
Greg Chadwick009d9ee2021-04-26 16:25:51 +0100444 assign rf_base_rd_data_a_inc = rf_base_rd_data_a_no_intg[4:0] + 1'b1;
445 assign rf_base_rd_data_b_inc = rf_base_rd_data_b_no_intg[4:0] + 1'b1;
Rupert Swarbrick9a4f47b2021-01-04 15:48:24 +0000446 // We can avoid a full 32-bit adder here because the offset is 32-bit aligned, so we know the
Greg Chadwick009d9ee2021-04-26 16:25:51 +0100447 // load/store address will only be valid if rf_base_rd_data_a_no_intg[4:0] is zero.
448 assign rf_base_rd_data_a_wlen_word_inc = rf_base_rd_data_a_no_intg[31:5] + 27'h1;
Greg Chadwickae8e6452020-10-02 12:04:15 +0100449
450 // Choose increment to write back to base register file, only one increment can be written as
451 // there is only one write port. Note that where an instruction is incrementing the indirect
452 // reference to its destination register (insn_dec_bignum_i.d_inc) that reference is read on the
453 // B read port so the B increment is written back.
454 always_comb begin
455 unique case (1'b1)
456 insn_dec_bignum_i.a_inc: begin
Greg Chadwick496fd342021-03-05 18:08:39 +0000457 increment_out = {26'b0, rf_base_rd_data_a_inc};
Greg Chadwickae8e6452020-10-02 12:04:15 +0100458 end
459 insn_dec_bignum_i.b_inc: begin
Greg Chadwick496fd342021-03-05 18:08:39 +0000460 increment_out = {26'b0, rf_base_rd_data_b_inc};
Greg Chadwickae8e6452020-10-02 12:04:15 +0100461 end
462 insn_dec_bignum_i.d_inc: begin
Greg Chadwick496fd342021-03-05 18:08:39 +0000463 increment_out = {26'b0, rf_base_rd_data_b_inc};
Greg Chadwickae8e6452020-10-02 12:04:15 +0100464 end
465 insn_dec_bignum_i.a_wlen_word_inc: begin
Rupert Swarbrick9a4f47b2021-01-04 15:48:24 +0000466 increment_out = {rf_base_rd_data_a_wlen_word_inc, 5'b0};
Greg Chadwickae8e6452020-10-02 12:04:15 +0100467 end
Pirmin Vogele97cac02020-11-02 12:28:50 +0100468 default: begin
469 // Whenever increment_out is written back to the register file, exactly one of the
470 // increment selector signals is high. To prevent the automatic inference of latches in
471 // case nothing is written back (rf_wdata_sel != RfWdSelIncr) and to save logic, we choose
472 // a valid output as default.
Greg Chadwick496fd342021-03-05 18:08:39 +0000473 increment_out = {26'b0, rf_base_rd_data_a_inc};
Pirmin Vogele97cac02020-11-02 12:28:50 +0100474 end
Greg Chadwickae8e6452020-10-02 12:04:15 +0100475 endcase
476 end
477
Greg Chadwick5c8579c2021-08-04 14:38:33 +0100478 // Base RF read/write address, enable and commit control
Greg Chadwickae8e6452020-10-02 12:04:15 +0100479 always_comb begin
480 rf_base_rd_addr_a_o = insn_dec_base_i.a;
481 rf_base_rd_addr_b_o = insn_dec_base_i.b;
482 rf_base_wr_addr_o = insn_dec_base_i.d;
Greg Chadwicke6e8f152021-03-05 13:35:36 +0000483
Greg Chadwick5c8579c2021-08-04 14:38:33 +0100484 // Only commit read or write if the instruction is executing (in particular a read commit pops
485 // the call stack so must not occur where a valid instruction sees an error and doesn't
486 // execute).
487 rf_base_rd_commit_o = insn_executing;
488 rf_base_wr_commit_o = insn_executing;
Greg Chadwick9f5b6382021-05-10 17:53:46 +0100489
Greg Chadwick1a1c0112021-09-14 16:27:31 +0100490 rf_base_rd_en_a_raw = 1'b0;
491 rf_base_rd_en_b_raw = 1'b0;
492 rf_base_wr_en_raw = 1'b0;
Greg Chadwick9f5b6382021-05-10 17:53:46 +0100493
494 if (insn_valid_i) begin
Rupert Swarbrick46e11ba2021-07-13 12:11:43 +0100495 if (insn_dec_shared_i.st_insn) begin
496 // For stores, both base reads happen in the same cycle as the request because they give the
497 // address and data, which make up the request.
Greg Chadwick1a1c0112021-09-14 16:27:31 +0100498 rf_base_rd_en_a_raw = insn_dec_base_i.rf_ren_a & lsu_store_req_raw;
499 rf_base_rd_en_b_raw = insn_dec_base_i.rf_ren_b & lsu_store_req_raw;
Greg Chadwick5c8579c2021-08-04 14:38:33 +0100500
501 // Bignum stores can update the base register file where an increment is used.
Greg Chadwick1a1c0112021-09-14 16:27:31 +0100502 rf_base_wr_en_raw = (insn_dec_shared_i.subset == InsnSubsetBignum) &
Greg Chadwick5c8579c2021-08-04 14:38:33 +0100503 insn_dec_base_i.rf_we &
504 lsu_store_req_raw;
Rupert Swarbrick46e11ba2021-07-13 12:11:43 +0100505 end else if (insn_dec_shared_i.ld_insn) begin
Greg Chadwick9a6fc462021-08-10 15:42:16 +0100506 // For loads, both base reads happen in the same cycle as the request. The address is
507 // required for the request and the indirect destination register (only used for Bignum
508 // loads) is flopped in ld_insn_bignum_wr_addr_q to correctly deal with the case where it's
509 // updated by an increment.
Greg Chadwick1a1c0112021-09-14 16:27:31 +0100510 rf_base_rd_en_a_raw = insn_dec_base_i.rf_ren_a & lsu_load_req_raw;
511 rf_base_rd_en_b_raw = insn_dec_base_i.rf_ren_b & lsu_load_req_raw;
Greg Chadwick5c8579c2021-08-04 14:38:33 +0100512
513 if (insn_dec_shared_i.subset == InsnSubsetBignum) begin
Greg Chadwick9a6fc462021-08-10 15:42:16 +0100514 // Bignum loads can update the base register file where an increment is used. This must
515 // always happen in the same cycle as the request as this is where both registers are
516 // read.
Greg Chadwick1a1c0112021-09-14 16:27:31 +0100517 rf_base_wr_en_raw = insn_dec_base_i.rf_we & lsu_load_req_raw;
Greg Chadwick5c8579c2021-08-04 14:38:33 +0100518 end else begin
519 // For Base loads write the base register file when the instruction is unstalled (meaning
520 // the load data is available).
Greg Chadwick1a1c0112021-09-14 16:27:31 +0100521 rf_base_wr_en_raw = insn_dec_base_i.rf_we & ~stall;
Greg Chadwick5c8579c2021-08-04 14:38:33 +0100522 end
Greg Chadwick9f5b6382021-05-10 17:53:46 +0100523 end else begin
Greg Chadwick5c8579c2021-08-04 14:38:33 +0100524 // For all other instructions the read and write happen when the instruction is unstalled.
Greg Chadwick1a1c0112021-09-14 16:27:31 +0100525 rf_base_rd_en_a_raw = insn_dec_base_i.rf_ren_a & ~stall;
526 rf_base_rd_en_b_raw = insn_dec_base_i.rf_ren_b & ~stall;
527 rf_base_wr_en_raw = insn_dec_base_i.rf_we & ~stall;
Greg Chadwick9f5b6382021-05-10 17:53:46 +0100528 end
Greg Chadwicke6e8f152021-03-05 13:35:36 +0000529 end
Greg Chadwickae8e6452020-10-02 12:04:15 +0100530
531 if (insn_dec_shared_i.subset == InsnSubsetBignum) begin
532 unique case (1'b1)
533 insn_dec_bignum_i.a_inc,
534 insn_dec_bignum_i.a_wlen_word_inc: begin
535 rf_base_wr_addr_o = insn_dec_base_i.a;
536 end
537
538 insn_dec_bignum_i.b_inc,
539 insn_dec_bignum_i.d_inc: begin
540 rf_base_wr_addr_o = insn_dec_base_i.b;
541 end
542 default: ;
543 endcase
544 end
Greg Chadwick1a1c0112021-09-14 16:27:31 +0100545
546 rf_base_rd_en_a_o = rf_base_rd_en_a_raw & ~illegal_insn_static;
547 rf_base_rd_en_b_o = rf_base_rd_en_b_raw & ~illegal_insn_static;
548 rf_base_wr_en_o = rf_base_wr_en_raw & ~illegal_insn_static;
Greg Chadwickae8e6452020-10-02 12:04:15 +0100549 end
Philipp Wagner31441082020-07-14 11:17:21 +0100550
551 // Base ALU Operand A MUX
552 always_comb begin
Greg Chadwickcf048242020-10-02 15:28:42 +0100553 unique case (insn_dec_base_i.op_a_sel)
Greg Chadwick009d9ee2021-04-26 16:25:51 +0100554 OpASelRegister: alu_base_operation_o.operand_a = rf_base_rd_data_a_no_intg;
Greg Chadwick9e858fb2020-10-12 17:39:16 +0100555 OpASelZero: alu_base_operation_o.operand_a = '0;
556 OpASelCurrPc: alu_base_operation_o.operand_a = {{(32 - ImemAddrWidth){1'b0}}, insn_addr_i};
Greg Chadwick009d9ee2021-04-26 16:25:51 +0100557 default: alu_base_operation_o.operand_a = rf_base_rd_data_a_no_intg;
Philipp Wagner31441082020-07-14 11:17:21 +0100558 endcase
559 end
560
561 // Base ALU Operand B MUX
562 always_comb begin
Greg Chadwickcf048242020-10-02 15:28:42 +0100563 unique case (insn_dec_base_i.op_b_sel)
Greg Chadwick009d9ee2021-04-26 16:25:51 +0100564 OpBSelRegister: alu_base_operation_o.operand_b = rf_base_rd_data_b_no_intg;
Greg Chadwick9e858fb2020-10-12 17:39:16 +0100565 OpBSelImmediate: alu_base_operation_o.operand_b = insn_dec_base_i.i;
Greg Chadwick009d9ee2021-04-26 16:25:51 +0100566 default: alu_base_operation_o.operand_b = rf_base_rd_data_b_no_intg;
Philipp Wagner31441082020-07-14 11:17:21 +0100567 endcase
568 end
569
Greg Chadwicke177f172020-09-09 14:46:03 +0100570 assign alu_base_operation_o.op = insn_dec_base_i.alu_op;
Philipp Wagner31441082020-07-14 11:17:21 +0100571
Greg Chadwick009d9ee2021-04-26 16:25:51 +0100572 assign alu_base_comparison_o.operand_a = rf_base_rd_data_a_no_intg;
573 assign alu_base_comparison_o.operand_b = rf_base_rd_data_b_no_intg;
Greg Chadwicke177f172020-09-09 14:46:03 +0100574 assign alu_base_comparison_o.op = insn_dec_base_i.comparison_op;
Greg Chadwick9791eed2020-07-22 18:08:28 +0100575
Greg Chadwick009d9ee2021-04-26 16:25:51 +0100576 assign rf_base_rd_data_a_no_intg = rf_base_rd_data_a_intg_i[31:0];
577 assign rf_base_rd_data_b_no_intg = rf_base_rd_data_b_intg_i[31:0];
578
579 // TODO: For now integrity bits from RF base are ignored in the controller, remove this when end
580 // to end integrity features that use them are implemented
581 logic unused_rf_base_rd_a_intg_bits;
582 logic unused_rf_base_rd_b_intg_bits;
583
584 assign unused_rf_base_rd_a_intg_bits = |rf_base_rd_data_a_intg_i[38:32];
585 assign unused_rf_base_rd_b_intg_bits = |rf_base_rd_data_b_intg_i[38:32];
586
Philipp Wagner31441082020-07-14 11:17:21 +0100587 // Register file write MUX
Greg Chadwickc8cd4352020-08-14 16:45:23 +0100588 always_comb begin
Greg Chadwickee060bd2021-05-15 17:33:22 +0100589 // Write data mux for anything that needs integrity computing during register write
Greg Chadwickcf048242020-10-02 15:28:42 +0100590 unique case (insn_dec_base_i.rf_wdata_sel)
Greg Chadwick009d9ee2021-04-26 16:25:51 +0100591 RfWdSelEx: rf_base_wr_data_no_intg_o = alu_base_operation_result_i;
Greg Chadwick009d9ee2021-04-26 16:25:51 +0100592 RfWdSelNextPc: rf_base_wr_data_no_intg_o = {{(32-(ImemAddrWidth+1)){1'b0}},
593 next_insn_addr_wide};
594 RfWdSelIspr: rf_base_wr_data_no_intg_o = csr_rdata;
595 RfWdSelIncr: rf_base_wr_data_no_intg_o = increment_out;
596 default: rf_base_wr_data_no_intg_o = alu_base_operation_result_i;
Greg Chadwickc8cd4352020-08-14 16:45:23 +0100597 endcase
Greg Chadwickc8cd4352020-08-14 16:45:23 +0100598
Greg Chadwickee060bd2021-05-15 17:33:22 +0100599 // Write data mux for anything that provides its own integrity
600 unique case (insn_dec_base_i.rf_wdata_sel)
601 RfWdSelLsu: begin
602 rf_base_wr_data_intg_sel_o = 1'b1;
603 rf_base_wr_data_intg_o = lsu_base_rdata_i;
604 end
605 default: begin
606 rf_base_wr_data_intg_sel_o = 1'b0;
607 rf_base_wr_data_intg_o = '0;
608 end
609 endcase
610 end
Greg Chadwick009d9ee2021-04-26 16:25:51 +0100611
612 for (genvar i = 0; i < BaseWordsPerWLEN; ++i) begin : g_rf_bignum_rd_data
613 assign rf_bignum_rd_data_a_no_intg[i * 32 +: 32] = rf_bignum_rd_data_a_intg_i[i * 39 +: 32];
614 assign rf_bignum_rd_data_b_no_intg[i * 32 +: 32] = rf_bignum_rd_data_b_intg_i[i * 39 +: 32];
615 end
616
617 assign rf_bignum_rd_addr_a_o = insn_dec_bignum_i.rf_a_indirect ? rf_base_rd_data_a_no_intg[4:0] :
Greg Chadwickae8e6452020-10-02 12:04:15 +0100618 insn_dec_bignum_i.a;
Greg Chadwick009d9ee2021-04-26 16:25:51 +0100619 assign rf_bignum_rd_en_a_o = insn_dec_bignum_i.rf_ren_a & insn_valid_i;
Greg Chadwickae8e6452020-10-02 12:04:15 +0100620
Greg Chadwick009d9ee2021-04-26 16:25:51 +0100621 assign rf_bignum_rd_addr_b_o = insn_dec_bignum_i.rf_b_indirect ? rf_base_rd_data_b_no_intg[4:0] :
Greg Chadwickae8e6452020-10-02 12:04:15 +0100622 insn_dec_bignum_i.b;
Greg Chadwick009d9ee2021-04-26 16:25:51 +0100623 assign rf_bignum_rd_en_b_o = insn_dec_bignum_i.rf_ren_b & insn_valid_i;
Greg Chadwickf7863442020-09-14 18:11:33 +0100624
Greg Chadwick009d9ee2021-04-26 16:25:51 +0100625 assign alu_bignum_operation_o.operand_a = rf_bignum_rd_data_a_no_intg;
Greg Chadwickf7863442020-09-14 18:11:33 +0100626
627 // Base ALU Operand B MUX
628 always_comb begin
Greg Chadwick94786452020-10-28 18:19:51 +0000629 unique case (insn_dec_bignum_i.alu_op_b_sel)
Greg Chadwick009d9ee2021-04-26 16:25:51 +0100630 OpBSelRegister: alu_bignum_operation_o.operand_b = rf_bignum_rd_data_b_no_intg;
Greg Chadwick9e858fb2020-10-12 17:39:16 +0100631 OpBSelImmediate: alu_bignum_operation_o.operand_b = insn_dec_bignum_i.i;
Greg Chadwick009d9ee2021-04-26 16:25:51 +0100632 default: alu_bignum_operation_o.operand_b = rf_bignum_rd_data_b_no_intg;
Greg Chadwickf7863442020-09-14 18:11:33 +0100633 endcase
634 end
635
636 assign alu_bignum_operation_o.op = insn_dec_bignum_i.alu_op;
Greg Chadwick94786452020-10-28 18:19:51 +0000637 assign alu_bignum_operation_o.shift_right = insn_dec_bignum_i.alu_shift_right;
638 assign alu_bignum_operation_o.shift_amt = insn_dec_bignum_i.alu_shift_amt;
639 assign alu_bignum_operation_o.flag_group = insn_dec_bignum_i.alu_flag_group;
640 assign alu_bignum_operation_o.sel_flag = insn_dec_bignum_i.alu_sel_flag;
Greg Chadwick96fe7052021-03-18 15:15:05 +0000641 assign alu_bignum_operation_o.alu_flag_en = insn_dec_bignum_i.alu_flag_en & insn_executing;
642 assign alu_bignum_operation_o.mac_flag_en = insn_dec_bignum_i.mac_flag_en & insn_executing;
Greg Chadwickf7863442020-09-14 18:11:33 +0100643
Greg Chadwick009d9ee2021-04-26 16:25:51 +0100644 assign mac_bignum_operation_o.operand_a = rf_bignum_rd_data_a_no_intg;
645 assign mac_bignum_operation_o.operand_b = rf_bignum_rd_data_b_no_intg;
Greg Chadwick94786452020-10-28 18:19:51 +0000646 assign mac_bignum_operation_o.operand_a_qw_sel = insn_dec_bignum_i.mac_op_a_qw_sel;
647 assign mac_bignum_operation_o.operand_b_qw_sel = insn_dec_bignum_i.mac_op_b_qw_sel;
Rupert Swarbrick8e016022020-11-19 16:59:02 +0000648 assign mac_bignum_operation_o.wr_hw_sel_upper = insn_dec_bignum_i.mac_wr_hw_sel_upper;
Greg Chadwick94786452020-10-28 18:19:51 +0000649 assign mac_bignum_operation_o.pre_acc_shift_imm = insn_dec_bignum_i.mac_pre_acc_shift;
650 assign mac_bignum_operation_o.zero_acc = insn_dec_bignum_i.mac_zero_acc;
651 assign mac_bignum_operation_o.shift_acc = insn_dec_bignum_i.mac_shift_out;
652
Greg Chadwick42a9f3b2021-01-28 13:54:14 +0000653 assign mac_bignum_en_o = insn_executing & insn_dec_bignum_i.mac_en;
Greg Chadwick94786452020-10-28 18:19:51 +0000654
Greg Chadwick009d9ee2021-04-26 16:25:51 +0100655 // Move / Conditional Select. Only select B register data when a selection instruction is being
656 // executed and the selection flag isn't set.
657
658 `ASSERT(SelFlagValid, insn_valid_i & insn_dec_bignum_i.sel_insn |->
659 insn_dec_bignum_i.alu_sel_flag inside {FlagC, FlagL, FlagM, FlagZ})
660
661 assign selection_result =
662 ~insn_dec_bignum_i.sel_insn | alu_bignum_selection_flag_i ? rf_bignum_rd_data_a_intg_i :
663 rf_bignum_rd_data_b_intg_i;
Greg Chadwick94786452020-10-28 18:19:51 +0000664
665 // Bignum Register file write control
666
667 always_comb begin
668 // By default write nothing
669 rf_bignum_wr_en_o = 2'b00;
670
Greg Chadwicke6e8f152021-03-05 13:35:36 +0000671 // Only write if executing instruction wants a bignum rf write and it isn't stalled and there is
672 // no error
673 if (insn_executing && insn_dec_bignum_i.rf_we && !err && !stall) begin
Greg Chadwick94786452020-10-28 18:19:51 +0000674 if (insn_dec_bignum_i.mac_en && insn_dec_bignum_i.mac_shift_out) begin
675 // Special handling for BN.MULQACC.SO, only enable upper or lower half depending on
Rupert Swarbrick8e016022020-11-19 16:59:02 +0000676 // mac_wr_hw_sel_upper.
677 rf_bignum_wr_en_o = insn_dec_bignum_i.mac_wr_hw_sel_upper ? 2'b10 : 2'b01;
Greg Chadwick94786452020-10-28 18:19:51 +0000678 end else begin
679 // For everything else write both halves immediately.
680 rf_bignum_wr_en_o = 2'b11;
681 end
682 end
683 end
Greg Chadwickf7863442020-09-14 18:11:33 +0100684
Greg Chadwick9a6fc462021-08-10 15:42:16 +0100685 // For BN.LID sample the indirect destination register index in first cycle as an increment might
686 // change it for the second cycle where the load data is written to the bignum register file.
687 always_ff @(posedge clk_i) begin
688 if (insn_dec_bignum_i.rf_d_indirect & lsu_load_req_raw) begin
689 ld_insn_bignum_wr_addr_q <= rf_base_rd_data_b_no_intg[4:0];
690 end
691 end
Greg Chadwickf7863442020-09-14 18:11:33 +0100692
Greg Chadwick9a6fc462021-08-10 15:42:16 +0100693 always_comb begin
694 rf_bignum_wr_addr_o = insn_dec_bignum_i.d;
695
696 if (insn_dec_bignum_i.rf_d_indirect) begin
697 if (insn_dec_shared_i.ld_insn) begin
698 // Use sampled register index from first cycle of the load (in case the increment has
699 // changed the value in the mean-time).
700 rf_bignum_wr_addr_o = ld_insn_bignum_wr_addr_q;
701 end else begin
702 // Use read register index directly
703 rf_bignum_wr_addr_o = rf_base_rd_data_b_no_intg[4:0];
704 end
705 end
706 end
Greg Chadwick496fd342021-03-05 18:08:39 +0000707
Greg Chadwick94786452020-10-28 18:19:51 +0000708 // For the shift-out variant of BN.MULQACC the bottom half of the MAC result is written to one
Philipp Wagnerdc946522020-12-03 10:52:58 +0000709 // half of a desintation register specified by the instruction (mac_wr_hw_sel_upper). The bottom
710 // half of the MAC result must be placed in the appropriate half of the write data (the RF only
711 // accepts write data for the top half in the top half of the write data input). Otherwise
712 // (shift-out to bottom half and all other BN.MULQACC instructions) simply pass the MAC result
713 // through unchanged as write data.
Greg Chadwick94786452020-10-28 18:19:51 +0000714 assign mac_bignum_rf_wr_data[WLEN-1:WLEN/2] =
Philipp Wagnerdc946522020-12-03 10:52:58 +0000715 insn_dec_bignum_i.mac_wr_hw_sel_upper &&
716 insn_dec_bignum_i.mac_shift_out ? mac_bignum_operation_result_i[WLEN/2-1:0] :
717 mac_bignum_operation_result_i[WLEN-1:WLEN/2];
Greg Chadwick94786452020-10-28 18:19:51 +0000718
719 assign mac_bignum_rf_wr_data[WLEN/2-1:0] = mac_bignum_operation_result_i[WLEN/2-1:0];
720
Greg Chadwickf7863442020-09-14 18:11:33 +0100721 always_comb begin
Greg Chadwick009d9ee2021-04-26 16:25:51 +0100722 // Write data mux for anything that needs integrity computing during register write
Greg Chadwickee060bd2021-05-15 17:33:22 +0100723 // TODO: ISPR data will go via direct mux below once integrity has been implemented for
Greg Chadwick009d9ee2021-04-26 16:25:51 +0100724 // them.
Greg Chadwickcf048242020-10-02 15:28:42 +0100725 unique case (insn_dec_bignum_i.rf_wdata_sel)
Greg Chadwick009d9ee2021-04-26 16:25:51 +0100726 RfWdSelEx: rf_bignum_wr_data_no_intg_o = alu_bignum_operation_result_i;
Greg Chadwick009d9ee2021-04-26 16:25:51 +0100727 RfWdSelIspr: rf_bignum_wr_data_no_intg_o = ispr_rdata_i;
728 RfWdSelMac: rf_bignum_wr_data_no_intg_o = mac_bignum_rf_wr_data;
729 default: rf_bignum_wr_data_no_intg_o = alu_bignum_operation_result_i;
730 endcase
731
732 // Write data mux for anything that provides its own integrity
733 unique case (insn_dec_bignum_i.rf_wdata_sel)
734 RfWdSelMovSel: begin
735 rf_bignum_wr_data_intg_sel_o = 1'b1;
736 rf_bignum_wr_data_intg_o = selection_result;
737 end
Greg Chadwickee060bd2021-05-15 17:33:22 +0100738 RfWdSelLsu: begin
739 rf_bignum_wr_data_intg_sel_o = 1'b1;
740 rf_bignum_wr_data_intg_o = lsu_bignum_rdata_i;
741 end
Greg Chadwick009d9ee2021-04-26 16:25:51 +0100742 default: begin
743 rf_bignum_wr_data_intg_sel_o = 1'b0;
744 rf_bignum_wr_data_intg_o = '0;
745 end
Greg Chadwickf7863442020-09-14 18:11:33 +0100746 endcase
747 end
748
Greg Chadwick9a6fc462021-08-10 15:42:16 +0100749 assign rf_a_indirect_err = insn_dec_bignum_i.rf_a_indirect &
750 (|rf_base_rd_data_a_no_intg[31:5]) &
751 rf_base_rd_en_a_o;
752
753 assign rf_b_indirect_err = insn_dec_bignum_i.rf_b_indirect &
754 (|rf_base_rd_data_b_no_intg[31:5]) &
755 rf_base_rd_en_b_o;
756
757 assign rf_d_indirect_err = insn_dec_bignum_i.rf_d_indirect &
758 (|rf_base_rd_data_b_no_intg[31:5]) &
759 rf_base_rd_en_b_o;
Greg Chadwick496fd342021-03-05 18:08:39 +0000760
761 assign rf_indirect_err =
762 insn_valid_i & (rf_a_indirect_err | rf_b_indirect_err | rf_d_indirect_err);
763
Greg Chadwickf7863442020-09-14 18:11:33 +0100764 // CSR/WSR/ISPR handling
765 // ISPRs (Internal Special Purpose Registers) are the internal registers. CSRs and WSRs are the
766 // ISA visible versions of those registers in the base and bignum ISAs respectively.
767
Philipp Wagner711d2262021-01-21 18:17:42 +0000768 assign csr_addr = csr_e'(insn_dec_base_i.i[11:0]);
769 assign csr_sub_addr = insn_dec_base_i.i[$clog2(BaseWordsPerWLEN)-1:0];
Greg Chadwickf7863442020-09-14 18:11:33 +0100770
771 always_comb begin
772 ispr_addr_base = IsprMod;
773 ispr_word_addr_base = '0;
Greg Chadwickd3154ec2020-09-24 12:03:23 +0100774 csr_illegal_addr = 1'b0;
Greg Chadwickf7863442020-09-14 18:11:33 +0100775
776 unique case (csr_addr)
Greg Chadwickdbd655a2020-11-24 16:42:06 +0000777 CsrFlags, CsrFg0, CsrFg1 : begin
Greg Chadwickf7863442020-09-14 18:11:33 +0100778 ispr_addr_base = IsprFlags;
779 ispr_word_addr_base = '0;
780 end
Philipp Wagner711d2262021-01-21 18:17:42 +0000781 CsrMod0, CsrMod1, CsrMod2, CsrMod3, CsrMod4, CsrMod5, CsrMod6, CsrMod7: begin
Greg Chadwickf7863442020-09-14 18:11:33 +0100782 ispr_addr_base = IsprMod;
Philipp Wagner711d2262021-01-21 18:17:42 +0000783 ispr_word_addr_base = csr_sub_addr;
Greg Chadwickf7863442020-09-14 18:11:33 +0100784 end
Greg Chadwickb168ae92021-04-14 16:04:03 +0100785 CsrRndPrefetch: begin
786 // Reading from RND_PREFETCH results in 0, there is no ISPR to read so no address is set.
787 // The csr_rdata mux logic takes care of producing the 0.
788 end
Philipp Wagner93877522021-07-16 10:49:25 +0100789 CsrRnd: begin
790 ispr_addr_base = IsprRnd;
791 ispr_word_addr_base = '0;
792 end
Greg Chadwickb168ae92021-04-14 16:04:03 +0100793 CsrUrnd: begin
794 ispr_addr_base = IsprUrnd;
795 ispr_word_addr_base = '0;
796 end
Greg Chadwickd3154ec2020-09-24 12:03:23 +0100797 default: csr_illegal_addr = 1'b1;
Greg Chadwickf7863442020-09-14 18:11:33 +0100798 endcase
799 end
800
801 for (genvar i_word = 0; i_word < BaseWordsPerWLEN; i_word++) begin : g_ispr_word_sel_base
802 assign ispr_word_sel_base[i_word] = ispr_word_addr_base == i_word;
803 end
804
805 for (genvar i_bit = 0; i_bit < 32; i_bit++) begin : g_csr_rdata_mux
806 for (genvar i_word = 0; i_word < BaseWordsPerWLEN; i_word++) begin : g_csr_rdata_mux_inner
Philipp Wagnerdc946522020-12-03 10:52:58 +0000807 assign csr_rdata_mux[i_bit][i_word] =
808 ispr_rdata_i[i_word*32 + i_bit] & ispr_word_sel_base[i_word];
Greg Chadwickf7863442020-09-14 18:11:33 +0100809 end
810
Greg Chadwickdbd655a2020-11-24 16:42:06 +0000811 assign csr_rdata_raw[i_bit] = |csr_rdata_mux[i_bit];
Greg Chadwickf7863442020-09-14 18:11:33 +0100812 end
813
Greg Chadwickdbd655a2020-11-24 16:42:06 +0000814 // Specialised read data handling for CSR reads where raw read data needs modification.
815 always_comb begin
816 csr_rdata = csr_rdata_raw;
817
Greg Chadwickb168ae92021-04-14 16:04:03 +0100818 unique case (csr_addr)
Greg Chadwickdbd655a2020-11-24 16:42:06 +0000819 // For FG0/FG1 select out appropriate bits from FLAGS ISPR and pad the rest with zeros.
Greg Chadwickb168ae92021-04-14 16:04:03 +0100820 CsrFg0: csr_rdata = {28'b0, csr_rdata_raw[3:0]};
821 CsrFg1: csr_rdata = {28'b0, csr_rdata_raw[7:4]};
822 CsrRndPrefetch: csr_rdata = '0;
Greg Chadwickdbd655a2020-11-24 16:42:06 +0000823 default: ;
824 endcase
825 end
826
Greg Chadwick009d9ee2021-04-26 16:25:51 +0100827 assign csr_wdata_raw = insn_dec_shared_i.ispr_rs_insn ? csr_rdata | rf_base_rd_data_a_no_intg :
828 rf_base_rd_data_a_no_intg;
Greg Chadwickdbd655a2020-11-24 16:42:06 +0000829
830 // Specialised write data handling for CSR writes where raw write data needs modification.
831 always_comb begin
832 csr_wdata = csr_wdata_raw;
833
Greg Chadwickb168ae92021-04-14 16:04:03 +0100834 unique case (csr_addr)
Greg Chadwickdbd655a2020-11-24 16:42:06 +0000835 // For FG0/FG1 only modify relevant part of FLAGS ISPR.
836 CsrFg0: csr_wdata = {24'b0, csr_rdata_raw[7:4], csr_wdata_raw[3:0]};
837 CsrFg1: csr_wdata = {24'b0, csr_wdata_raw[3:0], csr_rdata_raw[3:0]};
838 default: ;
839 endcase
840 end
Greg Chadwickf7863442020-09-14 18:11:33 +0100841
Rupert Swarbricka2c05e72020-11-20 08:46:25 +0000842 // ISPR RS (read and set) must not be combined with ISPR RD or WR (read or write). ISPR RD and
843 // WR (read and write) is allowed.
844 `ASSERT(NoIsprRorWAndRs, insn_valid_i |-> ~(insn_dec_shared_i.ispr_rs_insn &
845 (insn_dec_shared_i.ispr_rd_insn |
846 insn_dec_shared_i.ispr_wr_insn)))
847
848
Greg Chadwickf7863442020-09-14 18:11:33 +0100849 assign wsr_addr = wsr_e'(insn_dec_bignum_i.i[WsrNumWidth-1:0]);
850
851 always_comb begin
852 ispr_addr_bignum = IsprMod;
Greg Chadwickd3154ec2020-09-24 12:03:23 +0100853 wsr_illegal_addr = 1'b0;
Greg Chadwickf7863442020-09-14 18:11:33 +0100854
855 unique case (wsr_addr)
Greg Chadwickb168ae92021-04-14 16:04:03 +0100856 WsrMod: ispr_addr_bignum = IsprMod;
857 WsrRnd: ispr_addr_bignum = IsprRnd;
Greg Chadwickb168ae92021-04-14 16:04:03 +0100858 WsrUrnd: ispr_addr_bignum = IsprUrnd;
Philipp Wagner19afa992021-07-16 10:56:23 +0100859 WsrAcc: ispr_addr_bignum = IsprAcc;
Greg Chadwickd3154ec2020-09-24 12:03:23 +0100860 default: wsr_illegal_addr = 1'b1;
Greg Chadwickf7863442020-09-14 18:11:33 +0100861 endcase
862 end
863
Greg Chadwick009d9ee2021-04-26 16:25:51 +0100864 assign wsr_wdata = insn_dec_shared_i.ispr_rs_insn ? ispr_rdata_i | rf_bignum_rd_data_a_no_intg :
865 rf_bignum_rd_data_a_no_intg;
Greg Chadwickf7863442020-09-14 18:11:33 +0100866
Philipp Wagner711d2262021-01-21 18:17:42 +0000867 assign ispr_illegal_addr = insn_dec_shared_i.subset == InsnSubsetBase ? csr_illegal_addr :
868 wsr_illegal_addr;
Greg Chadwickd3154ec2020-09-24 12:03:23 +0100869
870 assign ispr_err = ispr_illegal_addr & insn_valid_i & (insn_dec_shared_i.ispr_rd_insn |
871 insn_dec_shared_i.ispr_wr_insn |
872 insn_dec_shared_i.ispr_rs_insn);
873
Rupert Swarbricka2c05e72020-11-20 08:46:25 +0000874 assign ispr_wr_insn = insn_dec_shared_i.ispr_wr_insn | insn_dec_shared_i.ispr_rs_insn;
Greg Chadwickb168ae92021-04-14 16:04:03 +0100875 assign ispr_rd_insn = insn_dec_shared_i.ispr_rd_insn | insn_dec_shared_i.ispr_rs_insn;
876
877 // Write to RND_PREFETCH must not produce ISR write
878 assign ispr_wr_base_insn =
879 ispr_wr_insn & (insn_dec_shared_i.subset == InsnSubsetBase) & (csr_addr != CsrRndPrefetch);
880
Rupert Swarbrick514348e2021-02-03 09:04:59 +0000881 assign ispr_wr_bignum_insn = ispr_wr_insn & (insn_dec_shared_i.subset == InsnSubsetBignum);
Greg Chadwickf7863442020-09-14 18:11:33 +0100882
Philipp Wagnerdc946522020-12-03 10:52:58 +0000883 assign ispr_addr_o = insn_dec_shared_i.subset == InsnSubsetBase ? ispr_addr_base :
884 ispr_addr_bignum;
Greg Chadwickf7863442020-09-14 18:11:33 +0100885 assign ispr_base_wdata_o = csr_wdata;
Rupert Swarbrick514348e2021-02-03 09:04:59 +0000886 assign ispr_base_wr_en_o = {BaseWordsPerWLEN{ispr_wr_base_insn & insn_executing}} &
887 ispr_word_sel_base;
Greg Chadwickf6f35962020-11-02 17:32:08 +0000888
Greg Chadwickf7863442020-09-14 18:11:33 +0100889 assign ispr_bignum_wdata_o = wsr_wdata;
Rupert Swarbrick514348e2021-02-03 09:04:59 +0000890 assign ispr_bignum_wr_en_o = ispr_wr_bignum_insn & insn_executing;
Greg Chadwickf7863442020-09-14 18:11:33 +0100891
Greg Chadwick42a9f3b2021-01-28 13:54:14 +0000892 // lsu_load_req_raw/lsu_store_req_raw indicate an instruction wishes to perform a store or a load.
Rupert Swarbrick514348e2021-02-03 09:04:59 +0000893 // lsu_load_req_o/lsu_store_req_o factor in whether an instruction is actually executing (it may
894 // be suppressed due an error) and command the load or store to happen when asserted.
Greg Chadwick42a9f3b2021-01-28 13:54:14 +0000895 assign lsu_load_req_raw = insn_valid_i & insn_dec_shared_i.ld_insn & (state_q == OtbnStateRun);
896 assign lsu_load_req_o = insn_executing & lsu_load_req_raw;
897
898 assign lsu_store_req_raw = insn_valid_i & insn_dec_shared_i.st_insn & (state_q == OtbnStateRun);
899 assign lsu_store_req_o = insn_executing & lsu_store_req_raw;
900
Greg Chadwickf7863442020-09-14 18:11:33 +0100901 assign lsu_req_subset_o = insn_dec_shared_i.subset;
Greg Chadwickc8cd4352020-08-14 16:45:23 +0100902
Greg Chadwickae8e6452020-10-02 12:04:15 +0100903 assign lsu_addr_o = alu_base_operation_result_i[DmemAddrWidth-1:0];
Greg Chadwickee060bd2021-05-15 17:33:22 +0100904 assign lsu_base_wdata_o = rf_base_rd_data_b_intg_i;
905 assign lsu_bignum_wdata_o = rf_bignum_rd_data_b_intg_i;
Greg Chadwick6ab8d952020-10-30 12:13:34 +0000906
Philipp Wagner711d2262021-01-21 18:17:42 +0000907 assign dmem_addr_unaligned_bignum =
908 (lsu_req_subset_o == InsnSubsetBignum) & (|lsu_addr_o[$clog2(WLEN/8)-1:0]);
909 assign dmem_addr_unaligned_base =
910 (lsu_req_subset_o == InsnSubsetBase) & (|lsu_addr_o[1:0]);
Greg Chadwickd3154ec2020-09-24 12:03:23 +0100911 assign dmem_addr_overflow = |alu_base_operation_result_i[31:DmemAddrWidth];
912
Greg Chadwick42a9f3b2021-01-28 13:54:14 +0000913 assign dmem_addr_err =
914 insn_valid_i & (lsu_load_req_raw | lsu_store_req_raw) & (dmem_addr_overflow |
Greg Chadwickd3154ec2020-09-24 12:03:23 +0100915 dmem_addr_unaligned_bignum |
916 dmem_addr_unaligned_base);
917
Greg Chadwickb168ae92021-04-14 16:04:03 +0100918 assign rnd_req_o = insn_valid_i & ispr_rd_insn & (ispr_addr_o == IsprRnd);
919
920 assign rnd_prefetch_req_o = insn_valid_i & ispr_wr_insn &
921 (insn_dec_shared_i.subset == InsnSubsetBase) & (csr_addr == CsrRndPrefetch);
Philipp Wagner31441082020-07-14 11:17:21 +0100922endmodule