1 |
16 |
csantifort |
//////////////////////////////////////////////////////////////////
|
2 |
|
|
// //
|
3 |
|
|
// Decode stage of Amber 25 Core //
|
4 |
|
|
// //
|
5 |
|
|
// This file is part of the Amber project //
|
6 |
|
|
// http://www.opencores.org/project,amber //
|
7 |
|
|
// //
|
8 |
|
|
// Description //
|
9 |
|
|
// This module is the most complex part of the Amber core //
|
10 |
|
|
// It decodes and sequences all instructions and handles all //
|
11 |
|
|
// interrupts //
|
12 |
|
|
// //
|
13 |
|
|
// Author(s): //
|
14 |
|
|
// - Conor Santifort, csantifort.amber@gmail.com //
|
15 |
|
|
// //
|
16 |
|
|
//////////////////////////////////////////////////////////////////
|
17 |
|
|
// //
|
18 |
|
|
// Copyright (C) 2011 Authors and OPENCORES.ORG //
|
19 |
|
|
// //
|
20 |
|
|
// This source file may be used and distributed without //
|
21 |
|
|
// restriction provided that this copyright statement is not //
|
22 |
|
|
// removed from the file and that any derivative work contains //
|
23 |
|
|
// the original copyright notice and the associated disclaimer. //
|
24 |
|
|
// //
|
25 |
|
|
// This source file is free software; you can redistribute it //
|
26 |
|
|
// and/or modify it under the terms of the GNU Lesser General //
|
27 |
|
|
// Public License as published by the Free Software Foundation; //
|
28 |
|
|
// either version 2.1 of the License, or (at your option) any //
|
29 |
|
|
// later version. //
|
30 |
|
|
// //
|
31 |
|
|
// This source is distributed in the hope that it will be //
|
32 |
|
|
// useful, but WITHOUT ANY WARRANTY; without even the implied //
|
33 |
|
|
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //
|
34 |
|
|
// PURPOSE. See the GNU Lesser General Public License for more //
|
35 |
|
|
// details. //
|
36 |
|
|
// //
|
37 |
|
|
// You should have received a copy of the GNU Lesser General //
|
38 |
|
|
// Public License along with this source; if not, download it //
|
39 |
|
|
// from http://www.opencores.org/lgpl.shtml //
|
40 |
|
|
// //
|
41 |
|
|
//////////////////////////////////////////////////////////////////
|
42 |
|
|
|
43 |
|
|
|
44 |
|
|
module a25_decode
|
45 |
|
|
(
|
46 |
|
|
input i_clk,
|
47 |
|
|
input [31:0] i_fetch_instruction,
|
48 |
|
|
input i_access_stall, // stall all stages of the cpu at the same time
|
49 |
|
|
input i_irq, // interrupt request
|
50 |
|
|
input i_firq, // Fast interrupt request
|
51 |
|
|
input i_dabt, // data abort interrupt request
|
52 |
|
|
input i_iabt, // instruction pre-fetch abort flag
|
53 |
|
|
input i_adex, // Address Exception
|
54 |
|
|
input [31:0] i_execute_iaddress, // Registered instruction address output by execute stage
|
55 |
|
|
input [31:0] i_execute_daddress, // Registered instruction address output by execute stage
|
56 |
|
|
input [7:0] i_abt_status, // Abort status
|
57 |
|
|
input [31:0] i_execute_status_bits, // current status bits values in execute stage
|
58 |
|
|
input i_multiply_done, // multiply unit is nearly done
|
59 |
|
|
|
60 |
|
|
|
61 |
|
|
// --------------------------------------------------
|
62 |
|
|
// Control signals to execute stage
|
63 |
|
|
// --------------------------------------------------
|
64 |
|
|
// output reg [4:0] o_read_data_alignment = 1'd0, // 2 LSBs of read address used for calculating shift in ldrb ops
|
65 |
|
|
|
66 |
|
|
output reg [31:0] o_imm32 = 'd0,
|
67 |
|
|
output reg [4:0] o_imm_shift_amount = 'd0,
|
68 |
|
|
output reg o_shift_imm_zero = 'd0,
|
69 |
|
|
output reg [3:0] o_condition = 4'he, // 4'he = al
|
70 |
|
|
output reg o_decode_exclusive = 'd0, // exclusive access request ( swap instruction )
|
71 |
|
|
output reg o_decode_iaccess = 1'd1, // Indicates an instruction access
|
72 |
|
|
output reg o_decode_daccess = 'd0, // Indicates a data access
|
73 |
|
|
output reg [1:0] o_status_bits_mode = 2'b11, // SVC
|
74 |
|
|
output reg o_status_bits_irq_mask = 1'd1,
|
75 |
|
|
output reg o_status_bits_firq_mask = 1'd1,
|
76 |
|
|
|
77 |
|
|
output reg [3:0] o_rm_sel = 'd0,
|
78 |
|
|
output reg [3:0] o_rs_sel = 'd0,
|
79 |
|
|
output reg [7:0] o_load_rd = 'd0, // [7] load flags with PC
|
80 |
|
|
// [6] load status bits with PC
|
81 |
|
|
// [5] Write into User Mode register
|
82 |
|
|
// [4] zero-extend load
|
83 |
|
|
// [3:0] destination register, Rd
|
84 |
|
|
output reg [3:0] o_rn_sel = 'd0,
|
85 |
|
|
output reg [1:0] o_barrel_shift_amount_sel = 'd0,
|
86 |
|
|
output reg [1:0] o_barrel_shift_data_sel = 'd0,
|
87 |
|
|
output reg [1:0] o_barrel_shift_function = 'd0,
|
88 |
|
|
output reg [8:0] o_alu_function = 'd0,
|
89 |
|
|
output reg [1:0] o_multiply_function = 'd0,
|
90 |
|
|
output reg [2:0] o_interrupt_vector_sel = 'd0,
|
91 |
|
|
output reg [3:0] o_iaddress_sel = 4'd2,
|
92 |
|
|
output reg [3:0] o_daddress_sel = 4'd2,
|
93 |
|
|
output reg [2:0] o_pc_sel = 3'd2,
|
94 |
|
|
output reg [1:0] o_byte_enable_sel = 'd0, // byte, halfword or word write
|
95 |
|
|
output reg [2:0] o_status_bits_sel = 'd0,
|
96 |
|
|
output reg [2:0] o_reg_write_sel,
|
97 |
|
|
output reg o_user_mode_regs_store_nxt,
|
98 |
|
|
output reg o_firq_not_user_mode,
|
99 |
|
|
|
100 |
|
|
output reg o_write_data_wen = 'd0,
|
101 |
|
|
output reg o_base_address_wen = 'd0, // save ldm base address register
|
102 |
|
|
// in case of data abort
|
103 |
|
|
output reg o_pc_wen = 1'd1,
|
104 |
|
|
output reg [14:0] o_reg_bank_wen = 'd0,
|
105 |
|
|
output reg o_status_bits_flags_wen = 'd0,
|
106 |
|
|
output reg o_status_bits_mode_wen = 'd0,
|
107 |
|
|
output reg o_status_bits_irq_mask_wen = 'd0,
|
108 |
|
|
output reg o_status_bits_firq_mask_wen = 'd0,
|
109 |
|
|
|
110 |
|
|
// --------------------------------------------------
|
111 |
|
|
// Co-Processor interface
|
112 |
|
|
// --------------------------------------------------
|
113 |
|
|
output reg [2:0] o_copro_opcode1 = 'd0,
|
114 |
|
|
output reg [2:0] o_copro_opcode2 = 'd0,
|
115 |
|
|
output reg [3:0] o_copro_crn = 'd0,
|
116 |
|
|
output reg [3:0] o_copro_crm = 'd0,
|
117 |
|
|
output reg [3:0] o_copro_num = 'd0,
|
118 |
|
|
output reg [1:0] o_copro_operation = 'd0, // 0 = no operation,
|
119 |
|
|
// 1 = Move to Amber Core Register from Coprocessor
|
120 |
|
|
// 2 = Move to Coprocessor from Amber Core Register
|
121 |
|
|
output reg o_copro_write_data_wen = 'd0,
|
122 |
|
|
output o_iabt_trigger,
|
123 |
|
|
output [31:0] o_iabt_address,
|
124 |
|
|
output [7:0] o_iabt_status,
|
125 |
|
|
output o_dabt_trigger,
|
126 |
|
|
output [31:0] o_dabt_address,
|
127 |
|
|
output [7:0] o_dabt_status,
|
128 |
20 |
csantifort |
output o_conflict,
|
129 |
|
|
output reg o_rn_use_read,
|
130 |
|
|
output reg o_rm_use_read,
|
131 |
|
|
output reg o_rs_use_read,
|
132 |
|
|
output reg o_rd_use_read
|
133 |
16 |
csantifort |
|
134 |
|
|
);
|
135 |
|
|
|
136 |
|
|
`include "a25_localparams.v"
|
137 |
|
|
`include "a25_functions.v"
|
138 |
|
|
|
139 |
|
|
localparam [4:0] RST_WAIT1 = 5'd0,
|
140 |
|
|
RST_WAIT2 = 5'd1,
|
141 |
|
|
INT_WAIT1 = 5'd2,
|
142 |
|
|
INT_WAIT2 = 5'd3,
|
143 |
|
|
EXECUTE = 5'd4,
|
144 |
|
|
PRE_FETCH_EXEC = 5'd5, // Execute the Pre-Fetched Instruction
|
145 |
|
|
MEM_WAIT1 = 5'd6, // conditionally decode current instruction, in case
|
146 |
|
|
// previous instruction does not execute in S2
|
147 |
|
|
MEM_WAIT2 = 5'd7,
|
148 |
|
|
PC_STALL1 = 5'd8, // Program Counter altered
|
149 |
|
|
// conditionally decude current instruction, in case
|
150 |
|
|
// previous instruction does not execute in S2
|
151 |
|
|
PC_STALL2 = 5'd9,
|
152 |
|
|
MTRANS_EXEC1 = 5'd10,
|
153 |
|
|
MTRANS_EXEC2 = 5'd11,
|
154 |
|
|
MTRANS_ABORT = 5'd12,
|
155 |
|
|
MULT_PROC1 = 5'd13, // first cycle, save pre fetch instruction
|
156 |
|
|
MULT_PROC2 = 5'd14, // do multiplication
|
157 |
|
|
MULT_STORE = 5'd15, // save RdLo
|
158 |
|
|
MULT_ACCUMU = 5'd16, // Accumulate add lower 32 bits
|
159 |
|
|
SWAP_WRITE = 5'd17,
|
160 |
|
|
SWAP_WAIT1 = 5'd18,
|
161 |
|
|
SWAP_WAIT2 = 5'd19,
|
162 |
|
|
COPRO_WAIT = 5'd20;
|
163 |
|
|
|
164 |
|
|
|
165 |
|
|
// ========================================================
|
166 |
|
|
// Internal signals
|
167 |
|
|
// ========================================================
|
168 |
|
|
wire [31:0] instruction;
|
169 |
|
|
wire instruction_iabt; // abort flag, follows the instruction
|
170 |
|
|
wire instruction_adex; // address exception flag, follows the instruction
|
171 |
|
|
wire [31:0] instruction_address; // instruction virtual address, follows
|
172 |
|
|
// the instruction
|
173 |
|
|
wire [7:0] instruction_iabt_status; // abort status, follows the instruction
|
174 |
|
|
wire [1:0] instruction_sel;
|
175 |
|
|
reg [3:0] type;
|
176 |
|
|
wire [3:0] opcode;
|
177 |
|
|
wire [7:0] imm8;
|
178 |
|
|
wire [31:0] offset12;
|
179 |
|
|
wire [31:0] offset24;
|
180 |
|
|
wire [4:0] shift_imm;
|
181 |
|
|
|
182 |
|
|
wire opcode_compare;
|
183 |
|
|
wire mem_op;
|
184 |
|
|
wire load_op;
|
185 |
|
|
wire store_op;
|
186 |
|
|
wire write_pc;
|
187 |
|
|
wire current_write_pc;
|
188 |
|
|
reg load_pc_nxt;
|
189 |
|
|
reg load_pc_r = 'd0;
|
190 |
|
|
wire immediate_shift_op;
|
191 |
|
|
wire rds_use_rs;
|
192 |
|
|
wire branch;
|
193 |
|
|
wire mem_op_pre_indexed;
|
194 |
|
|
wire mem_op_post_indexed;
|
195 |
|
|
|
196 |
|
|
// Flop inputs
|
197 |
|
|
wire [31:0] imm32_nxt;
|
198 |
|
|
wire [4:0] imm_shift_amount_nxt;
|
199 |
|
|
wire shift_imm_zero_nxt;
|
200 |
|
|
wire [3:0] condition_nxt;
|
201 |
|
|
reg decode_exclusive_nxt;
|
202 |
|
|
reg decode_iaccess_nxt;
|
203 |
|
|
reg decode_daccess_nxt;
|
204 |
|
|
|
205 |
|
|
reg [1:0] barrel_shift_function_nxt;
|
206 |
|
|
wire [8:0] alu_function_nxt;
|
207 |
|
|
reg [1:0] multiply_function_nxt;
|
208 |
|
|
reg [1:0] status_bits_mode_nxt;
|
209 |
|
|
reg status_bits_irq_mask_nxt;
|
210 |
|
|
reg status_bits_firq_mask_nxt;
|
211 |
|
|
|
212 |
|
|
wire [3:0] rm_sel_nxt;
|
213 |
|
|
wire [3:0] rs_sel_nxt;
|
214 |
|
|
|
215 |
|
|
wire [3:0] rn_sel_nxt;
|
216 |
|
|
reg [1:0] barrel_shift_amount_sel_nxt;
|
217 |
|
|
reg [1:0] barrel_shift_data_sel_nxt;
|
218 |
|
|
reg [3:0] iaddress_sel_nxt;
|
219 |
|
|
reg [3:0] daddress_sel_nxt;
|
220 |
|
|
reg [2:0] pc_sel_nxt;
|
221 |
|
|
reg [1:0] byte_enable_sel_nxt;
|
222 |
|
|
reg [2:0] status_bits_sel_nxt;
|
223 |
|
|
reg [2:0] reg_write_sel_nxt;
|
224 |
|
|
wire firq_not_user_mode_nxt;
|
225 |
|
|
|
226 |
|
|
// ALU Function signals
|
227 |
|
|
reg alu_swap_sel_nxt;
|
228 |
|
|
reg alu_not_sel_nxt;
|
229 |
|
|
reg [1:0] alu_cin_sel_nxt;
|
230 |
|
|
reg alu_cout_sel_nxt;
|
231 |
|
|
reg [3:0] alu_out_sel_nxt;
|
232 |
|
|
|
233 |
|
|
reg write_data_wen_nxt;
|
234 |
|
|
reg copro_write_data_wen_nxt;
|
235 |
|
|
reg base_address_wen_nxt;
|
236 |
|
|
reg pc_wen_nxt;
|
237 |
|
|
reg [14:0] reg_bank_wen_nxt;
|
238 |
|
|
reg status_bits_flags_wen_nxt;
|
239 |
|
|
reg status_bits_mode_wen_nxt;
|
240 |
|
|
reg status_bits_irq_mask_wen_nxt;
|
241 |
|
|
reg status_bits_firq_mask_wen_nxt;
|
242 |
|
|
|
243 |
|
|
reg saved_current_instruction_wen; // saved load instruction
|
244 |
|
|
reg pre_fetch_instruction_wen; // pre-fetch instruction
|
245 |
|
|
|
246 |
|
|
reg [4:0] control_state = RST_WAIT1;
|
247 |
|
|
reg [4:0] control_state_nxt;
|
248 |
|
|
|
249 |
|
|
|
250 |
|
|
wire dabt;
|
251 |
|
|
reg dabt_reg = 'd0;
|
252 |
|
|
reg dabt_reg_d1;
|
253 |
|
|
reg iabt_reg = 'd0;
|
254 |
|
|
reg adex_reg = 'd0;
|
255 |
|
|
reg [31:0] fetch_address_r = 'd0;
|
256 |
|
|
reg [7:0] abt_status_reg = 'd0;
|
257 |
|
|
reg [31:0] fetch_instruction_r = 'd0;
|
258 |
|
|
reg [31:0] saved_current_instruction = 'd0;
|
259 |
|
|
reg saved_current_instruction_iabt = 'd0; // access abort flag
|
260 |
|
|
reg saved_current_instruction_adex = 'd0; // address exception
|
261 |
|
|
reg [31:0] saved_current_instruction_address = 'd0; // virtual address of abort instruction
|
262 |
|
|
reg [7:0] saved_current_instruction_iabt_status = 'd0; // status of abort instruction
|
263 |
|
|
reg [31:0] pre_fetch_instruction = 'd0;
|
264 |
|
|
reg pre_fetch_instruction_iabt = 'd0; // access abort flag
|
265 |
|
|
reg pre_fetch_instruction_adex = 'd0; // address exception
|
266 |
|
|
reg [31:0] pre_fetch_instruction_address = 'd0; // virtual address of abort instruction
|
267 |
|
|
reg [7:0] pre_fetch_instruction_iabt_status = 'd0; // status of abort instruction
|
268 |
|
|
reg [31:0] hold_instruction = 'd0;
|
269 |
|
|
reg hold_instruction_iabt = 'd0; // access abort flag
|
270 |
|
|
reg hold_instruction_adex = 'd0; // address exception
|
271 |
|
|
reg [31:0] hold_instruction_address = 'd0; // virtual address of abort instruction
|
272 |
|
|
reg [7:0] hold_instruction_iabt_status = 'd0; // status of abort instruction
|
273 |
|
|
|
274 |
|
|
wire instruction_valid;
|
275 |
|
|
wire instruction_execute;
|
276 |
20 |
csantifort |
reg instruction_execute_r = 'd0;
|
277 |
16 |
csantifort |
|
278 |
|
|
reg [3:0] mtrans_reg1; // the current register being accessed as part of stm/ldm
|
279 |
|
|
reg [3:0] mtrans_reg2; // the next register being accessed as part of stm/ldm
|
280 |
|
|
reg [31:0] mtrans_instruction_nxt;
|
281 |
|
|
wire [15:0] mtrans_reg2_mask;
|
282 |
|
|
|
283 |
|
|
wire [31:0] mtrans_base_reg_change;
|
284 |
|
|
wire [4:0] mtrans_num_registers;
|
285 |
|
|
wire use_saved_current_instruction;
|
286 |
|
|
wire use_hold_instruction;
|
287 |
|
|
wire use_pre_fetch_instruction;
|
288 |
|
|
wire interrupt;
|
289 |
|
|
wire [1:0] interrupt_mode;
|
290 |
|
|
wire [2:0] next_interrupt;
|
291 |
|
|
reg irq = 'd0;
|
292 |
|
|
reg firq = 'd0;
|
293 |
|
|
wire firq_request;
|
294 |
|
|
wire irq_request;
|
295 |
|
|
wire swi_request;
|
296 |
|
|
wire und_request;
|
297 |
|
|
wire dabt_request;
|
298 |
|
|
reg [1:0] copro_operation_nxt;
|
299 |
|
|
reg mtrans_r15 = 'd0;
|
300 |
|
|
reg mtrans_r15_nxt;
|
301 |
|
|
reg restore_base_address = 'd0;
|
302 |
|
|
reg restore_base_address_nxt;
|
303 |
|
|
|
304 |
|
|
wire regop_set_flags;
|
305 |
|
|
|
306 |
|
|
wire [7:0] load_rd_nxt;
|
307 |
|
|
wire load_rd_byte;
|
308 |
|
|
wire ldm_user_mode;
|
309 |
|
|
wire ldm_status_bits;
|
310 |
|
|
wire ldm_flags;
|
311 |
|
|
wire [6:0] load_rd_d1_nxt;
|
312 |
|
|
reg [6:0] load_rd_d1 = 'd0; // MSB is the valid bit
|
313 |
|
|
wire rn_valid;
|
314 |
|
|
wire rm_valid;
|
315 |
|
|
wire rs_valid;
|
316 |
|
|
wire rd_valid;
|
317 |
|
|
wire stm_valid;
|
318 |
|
|
wire rn_conflict1;
|
319 |
|
|
wire rn_conflict2;
|
320 |
|
|
wire rm_conflict1;
|
321 |
|
|
wire rm_conflict2;
|
322 |
|
|
wire rs_conflict1;
|
323 |
|
|
wire rs_conflict2;
|
324 |
|
|
wire rd_conflict1;
|
325 |
|
|
wire rd_conflict2;
|
326 |
|
|
wire stm_conflict1a;
|
327 |
|
|
wire stm_conflict1b;
|
328 |
|
|
wire stm_conflict2a;
|
329 |
|
|
wire stm_conflict2b;
|
330 |
|
|
wire conflict1; // Register conflict1 with ldr operation
|
331 |
|
|
wire conflict2; // Register conflict1 with ldr operation
|
332 |
|
|
wire conflict; // Register conflict1 with ldr operation
|
333 |
|
|
reg conflict_r = 'd0;
|
334 |
20 |
csantifort |
reg rn_conflict1_r = 'd0;
|
335 |
|
|
reg rm_conflict1_r = 'd0;
|
336 |
|
|
reg rs_conflict1_r = 'd0;
|
337 |
|
|
reg rd_conflict1_r = 'd0;
|
338 |
16 |
csantifort |
|
339 |
|
|
|
340 |
|
|
// ========================================================
|
341 |
|
|
// Instruction Abort and Data Abort outputs
|
342 |
|
|
// ========================================================
|
343 |
|
|
|
344 |
|
|
assign o_iabt_trigger = instruction_iabt && o_status_bits_mode == SVC && control_state == INT_WAIT1;
|
345 |
|
|
assign o_iabt_address = instruction_address;
|
346 |
|
|
assign o_iabt_status = instruction_iabt_status;
|
347 |
|
|
|
348 |
|
|
assign o_dabt_trigger = dabt_reg && !dabt_reg_d1;
|
349 |
|
|
assign o_dabt_address = fetch_address_r;
|
350 |
|
|
assign o_dabt_status = abt_status_reg;
|
351 |
|
|
|
352 |
|
|
|
353 |
|
|
// ========================================================
|
354 |
|
|
// Instruction Decode
|
355 |
|
|
// ========================================================
|
356 |
|
|
|
357 |
|
|
// for instructions that take more than one cycle
|
358 |
|
|
// the instruction is saved in the 'saved_mem_instruction'
|
359 |
|
|
// register and then that register is used for the rest of
|
360 |
|
|
// the execution of the instruction.
|
361 |
|
|
// But if the instruction does not execute because of the
|
362 |
|
|
// condition, then need to select the next instruction to
|
363 |
|
|
// decode
|
364 |
|
|
assign use_saved_current_instruction = instruction_execute &&
|
365 |
|
|
( control_state == MEM_WAIT1 ||
|
366 |
|
|
control_state == MEM_WAIT2 ||
|
367 |
|
|
control_state == MTRANS_EXEC1 ||
|
368 |
|
|
control_state == MTRANS_EXEC2 ||
|
369 |
|
|
control_state == MTRANS_ABORT ||
|
370 |
|
|
control_state == MULT_PROC1 ||
|
371 |
|
|
control_state == MULT_PROC2 ||
|
372 |
|
|
control_state == MULT_ACCUMU ||
|
373 |
|
|
control_state == MULT_STORE ||
|
374 |
|
|
control_state == INT_WAIT1 ||
|
375 |
|
|
control_state == INT_WAIT2 ||
|
376 |
|
|
control_state == SWAP_WRITE ||
|
377 |
|
|
control_state == SWAP_WAIT1 ||
|
378 |
|
|
control_state == SWAP_WAIT2 ||
|
379 |
|
|
control_state == COPRO_WAIT );
|
380 |
|
|
|
381 |
|
|
assign use_hold_instruction = conflict_r;
|
382 |
|
|
|
383 |
|
|
assign use_pre_fetch_instruction = control_state == PRE_FETCH_EXEC;
|
384 |
|
|
|
385 |
|
|
|
386 |
|
|
assign instruction_sel = use_hold_instruction ? 2'd3 : // hold_instruction
|
387 |
|
|
use_saved_current_instruction ? 2'd1 : // saved_current_instruction
|
388 |
|
|
use_pre_fetch_instruction ? 2'd2 : // pre_fetch_instruction
|
389 |
|
|
2'd0 ; // fetch_instruction_r
|
390 |
|
|
|
391 |
|
|
assign instruction = instruction_sel == 2'd0 ? fetch_instruction_r :
|
392 |
|
|
instruction_sel == 2'd1 ? saved_current_instruction :
|
393 |
|
|
instruction_sel == 2'd3 ? hold_instruction :
|
394 |
|
|
pre_fetch_instruction ;
|
395 |
|
|
|
396 |
|
|
// abort flag
|
397 |
|
|
assign instruction_iabt = instruction_sel == 2'd0 ? iabt_reg :
|
398 |
|
|
instruction_sel == 2'd1 ? saved_current_instruction_iabt :
|
399 |
|
|
instruction_sel == 2'd3 ? hold_instruction_iabt :
|
400 |
|
|
pre_fetch_instruction_iabt ;
|
401 |
|
|
|
402 |
|
|
assign instruction_address = instruction_sel == 2'd0 ? fetch_address_r :
|
403 |
|
|
instruction_sel == 2'd1 ? saved_current_instruction_address :
|
404 |
|
|
instruction_sel == 2'd3 ? hold_instruction_address :
|
405 |
|
|
pre_fetch_instruction_address ;
|
406 |
|
|
|
407 |
|
|
assign instruction_iabt_status = instruction_sel == 2'd0 ? abt_status_reg :
|
408 |
|
|
instruction_sel == 2'd1 ? saved_current_instruction_iabt_status :
|
409 |
|
|
instruction_sel == 2'd3 ? hold_instruction_iabt_status :
|
410 |
|
|
pre_fetch_instruction_iabt_status ;
|
411 |
|
|
|
412 |
|
|
// instruction address exception
|
413 |
|
|
assign instruction_adex = instruction_sel == 2'd0 ? adex_reg :
|
414 |
|
|
instruction_sel == 2'd1 ? saved_current_instruction_adex :
|
415 |
|
|
instruction_sel == 2'd3 ? hold_instruction_adex :
|
416 |
|
|
pre_fetch_instruction_adex ;
|
417 |
|
|
|
418 |
|
|
// Instruction Decode - Order is important!
|
419 |
|
|
always @*
|
420 |
|
|
casez ({instruction[27:20], instruction[7:4]})
|
421 |
|
|
12'b00010?001001 : type = SWAP;
|
422 |
|
|
12'b000000??1001 : type = MULT;
|
423 |
|
|
12'b00?????????? : type = REGOP;
|
424 |
|
|
12'b01?????????? : type = TRANS;
|
425 |
|
|
12'b100????????? : type = MTRANS;
|
426 |
|
|
12'b101????????? : type = BRANCH;
|
427 |
|
|
12'b110????????? : type = CODTRANS;
|
428 |
|
|
12'b1110???????0 : type = COREGOP;
|
429 |
|
|
12'b1110???????1 : type = CORTRANS;
|
430 |
|
|
default: type = SWI;
|
431 |
|
|
endcase
|
432 |
|
|
|
433 |
|
|
|
434 |
|
|
// ========================================================
|
435 |
|
|
// Fixed fields within the instruction
|
436 |
|
|
// ========================================================
|
437 |
|
|
|
438 |
|
|
assign opcode = instruction[24:21];
|
439 |
|
|
assign condition_nxt = instruction[31:28];
|
440 |
|
|
|
441 |
|
|
assign rm_sel_nxt = instruction[3:0];
|
442 |
|
|
assign rn_sel_nxt = branch ? 4'd15 : instruction[19:16]; // Use PC to calculate branch destination
|
443 |
|
|
assign rs_sel_nxt = control_state == SWAP_WRITE ? instruction[3:0] : // Rm gets written out to memory
|
444 |
|
|
type == MTRANS ? mtrans_reg1 :
|
445 |
|
|
branch ? 4'd15 : // Update the PC
|
446 |
|
|
rds_use_rs ? instruction[11:8] :
|
447 |
|
|
instruction[15:12] ;
|
448 |
|
|
|
449 |
|
|
// Load from memory into registers
|
450 |
|
|
assign ldm_user_mode = type == MTRANS && {instruction[22:20],instruction[15]} == 4'b1010;
|
451 |
|
|
assign ldm_flags = type == MTRANS && rs_sel_nxt == 4'd15 && instruction[20] && instruction[22];
|
452 |
|
|
assign ldm_status_bits = type == MTRANS && rs_sel_nxt == 4'd15 && instruction[20] && instruction[22] && i_execute_status_bits[1:0] != USR;
|
453 |
|
|
assign load_rd_byte = (type == TRANS || type == SWAP) && instruction[22];
|
454 |
|
|
assign load_rd_nxt = {ldm_flags, ldm_status_bits, ldm_user_mode, load_rd_byte, rs_sel_nxt};
|
455 |
|
|
|
456 |
|
|
|
457 |
|
|
// MSB indicates valid dirty target register
|
458 |
|
|
assign load_rd_d1_nxt = {o_decode_daccess && !o_write_data_wen, o_load_rd[3:0]};
|
459 |
|
|
assign shift_imm = instruction[11:7];
|
460 |
|
|
assign offset12 = { 20'h0, instruction[11:0]};
|
461 |
|
|
assign offset24 = {{6{instruction[23]}}, instruction[23:0], 2'd0 }; // sign extend
|
462 |
|
|
assign imm8 = instruction[7:0];
|
463 |
|
|
|
464 |
|
|
assign immediate_shift_op = instruction[25];
|
465 |
|
|
assign rds_use_rs = (type == REGOP && !instruction[25] && instruction[4]) ||
|
466 |
|
|
(type == MULT &&
|
467 |
|
|
(control_state == MULT_PROC1 ||
|
468 |
|
|
control_state == MULT_PROC2 ||
|
469 |
|
|
instruction_valid && !interrupt )) ;
|
470 |
|
|
assign branch = type == BRANCH;
|
471 |
|
|
assign opcode_compare = opcode == CMP || opcode == CMN || opcode == TEQ || opcode == TST ;
|
472 |
|
|
assign mem_op = type == TRANS;
|
473 |
|
|
assign load_op = mem_op && instruction[20];
|
474 |
|
|
assign store_op = mem_op && !instruction[20];
|
475 |
|
|
assign write_pc = (pc_wen_nxt && pc_sel_nxt != 3'd0) || load_pc_r || load_pc_nxt;
|
476 |
|
|
assign current_write_pc = (pc_wen_nxt && pc_sel_nxt != 3'd0) || load_pc_nxt;
|
477 |
|
|
assign regop_set_flags = type == REGOP && instruction[20];
|
478 |
|
|
|
479 |
|
|
assign mem_op_pre_indexed = instruction[24] && instruction[21];
|
480 |
|
|
assign mem_op_post_indexed = !instruction[24];
|
481 |
|
|
|
482 |
|
|
assign imm32_nxt = // add 0 to Rm
|
483 |
|
|
type == MULT ? { 32'd0 } :
|
484 |
|
|
|
485 |
|
|
// 4 x number of registers
|
486 |
|
|
type == MTRANS ? { mtrans_base_reg_change } :
|
487 |
|
|
type == BRANCH ? { offset24 } :
|
488 |
|
|
type == TRANS ? { offset12 } :
|
489 |
|
|
instruction[11:8] == 4'h0 ? { 24'h0, imm8[7:0] } :
|
490 |
|
|
instruction[11:8] == 4'h1 ? { imm8[1:0], 24'h0, imm8[7:2] } :
|
491 |
|
|
instruction[11:8] == 4'h2 ? { imm8[3:0], 24'h0, imm8[7:4] } :
|
492 |
|
|
instruction[11:8] == 4'h3 ? { imm8[5:0], 24'h0, imm8[7:6] } :
|
493 |
|
|
instruction[11:8] == 4'h4 ? { imm8[7:0], 24'h0 } :
|
494 |
|
|
instruction[11:8] == 4'h5 ? { 2'h0, imm8[7:0], 22'h0 } :
|
495 |
|
|
instruction[11:8] == 4'h6 ? { 4'h0, imm8[7:0], 20'h0 } :
|
496 |
|
|
instruction[11:8] == 4'h7 ? { 6'h0, imm8[7:0], 18'h0 } :
|
497 |
|
|
instruction[11:8] == 4'h8 ? { 8'h0, imm8[7:0], 16'h0 } :
|
498 |
|
|
instruction[11:8] == 4'h9 ? { 10'h0, imm8[7:0], 14'h0 } :
|
499 |
|
|
instruction[11:8] == 4'ha ? { 12'h0, imm8[7:0], 12'h0 } :
|
500 |
|
|
instruction[11:8] == 4'hb ? { 14'h0, imm8[7:0], 10'h0 } :
|
501 |
|
|
instruction[11:8] == 4'hc ? { 16'h0, imm8[7:0], 8'h0 } :
|
502 |
|
|
instruction[11:8] == 4'hd ? { 18'h0, imm8[7:0], 6'h0 } :
|
503 |
|
|
instruction[11:8] == 4'he ? { 20'h0, imm8[7:0], 4'h0 } :
|
504 |
|
|
{ 22'h0, imm8[7:0], 2'h0 } ;
|
505 |
|
|
|
506 |
|
|
|
507 |
|
|
assign imm_shift_amount_nxt = shift_imm ;
|
508 |
|
|
|
509 |
|
|
// This signal is encoded in the decode stage because
|
510 |
|
|
// it is on the critical path in the execute stage
|
511 |
|
|
assign shift_imm_zero_nxt = imm_shift_amount_nxt == 5'd0 && // immediate amount = 0
|
512 |
|
|
barrel_shift_amount_sel_nxt == 2'd2; // shift immediate amount
|
513 |
|
|
|
514 |
|
|
assign alu_function_nxt = { alu_swap_sel_nxt,
|
515 |
|
|
alu_not_sel_nxt,
|
516 |
|
|
alu_cin_sel_nxt,
|
517 |
|
|
alu_cout_sel_nxt,
|
518 |
|
|
alu_out_sel_nxt };
|
519 |
|
|
|
520 |
|
|
// ========================================================
|
521 |
|
|
// Register Conflict Detection
|
522 |
|
|
// ========================================================
|
523 |
20 |
csantifort |
assign rn_valid = type == REGOP || type == MULT || type == SWAP || type == TRANS || type == MTRANS || type == CODTRANS;
|
524 |
|
|
assign rm_valid = type == REGOP || type == MULT || type == SWAP || (type == TRANS && immediate_shift_op);
|
525 |
|
|
assign rs_valid = rds_use_rs;
|
526 |
|
|
assign rd_valid = (type == TRANS && store_op) || (type == REGOP || type == SWAP);
|
527 |
|
|
assign stm_valid = type == MTRANS && !instruction[20]; // stm instruction
|
528 |
|
|
|
529 |
|
|
|
530 |
|
|
assign rn_conflict1 = instruction_execute && rn_valid && ( load_rd_d1_nxt[4] && rn_sel_nxt == load_rd_d1_nxt[3:0] );
|
531 |
|
|
assign rn_conflict2 = instruction_execute_r && rn_valid && ( load_rd_d1 [4] && rn_sel_nxt == load_rd_d1 [3:0] );
|
532 |
|
|
assign rm_conflict1 = instruction_execute && rm_valid && ( load_rd_d1_nxt[4] && rm_sel_nxt == load_rd_d1_nxt[3:0] );
|
533 |
|
|
assign rm_conflict2 = instruction_execute_r && rm_valid && ( load_rd_d1 [4] && rm_sel_nxt == load_rd_d1 [3:0] );
|
534 |
|
|
assign rs_conflict1 = instruction_execute && rs_valid && ( load_rd_d1_nxt[4] && rs_sel_nxt == load_rd_d1_nxt[3:0] );
|
535 |
|
|
assign rs_conflict2 = instruction_execute_r && rs_valid && ( load_rd_d1 [4] && rs_sel_nxt == load_rd_d1 [3:0] );
|
536 |
|
|
assign rd_conflict1 = instruction_execute && rd_valid && ( load_rd_d1_nxt[4] && instruction[15:12] == load_rd_d1_nxt[3:0] );
|
537 |
|
|
assign rd_conflict2 = instruction_execute_r && rd_valid && ( load_rd_d1 [4] && instruction[15:12] == load_rd_d1 [3:0] );
|
538 |
|
|
|
539 |
|
|
assign stm_conflict1a = instruction_execute && stm_valid && ( load_rd_d1_nxt[4] && mtrans_reg1 == load_rd_d1_nxt[3:0] );
|
540 |
|
|
assign stm_conflict1b = instruction_execute && stm_valid && ( load_rd_d1_nxt[4] && mtrans_reg2 == load_rd_d1_nxt[3:0] );
|
541 |
|
|
assign stm_conflict2a = instruction_execute_r && stm_valid && ( load_rd_d1 [4] && mtrans_reg1 == load_rd_d1 [3:0] );
|
542 |
|
|
assign stm_conflict2b = instruction_execute_r && stm_valid && ( load_rd_d1 [4] && mtrans_reg2 == load_rd_d1 [3:0] );
|
543 |
16 |
csantifort |
|
544 |
|
|
assign conflict1 = instruction_valid &&
|
545 |
|
|
(rn_conflict1 || rm_conflict1 || rs_conflict1 || rd_conflict1 ||
|
546 |
|
|
stm_conflict1a || stm_conflict1b);
|
547 |
|
|
|
548 |
20 |
csantifort |
assign conflict2 = instruction_valid && (stm_conflict2a || stm_conflict2b);
|
549 |
16 |
csantifort |
|
550 |
|
|
assign conflict = conflict1 || conflict2;
|
551 |
|
|
|
552 |
|
|
|
553 |
|
|
always @( posedge i_clk )
|
554 |
|
|
if ( !i_access_stall )
|
555 |
|
|
begin
|
556 |
20 |
csantifort |
conflict_r <= conflict;
|
557 |
|
|
instruction_execute_r <= instruction_execute;
|
558 |
|
|
rn_conflict1_r <= rn_conflict1 && instruction_execute;
|
559 |
|
|
rm_conflict1_r <= rm_conflict1 && instruction_execute;
|
560 |
|
|
rs_conflict1_r <= rs_conflict1 && instruction_execute;
|
561 |
|
|
rd_conflict1_r <= rd_conflict1 && instruction_execute;
|
562 |
|
|
o_rn_use_read <= instruction_valid && ( rn_conflict1_r || rn_conflict2 );
|
563 |
|
|
o_rm_use_read <= instruction_valid && ( rm_conflict1_r || rm_conflict2 );
|
564 |
|
|
o_rs_use_read <= instruction_valid && ( rs_conflict1_r || rs_conflict2 );
|
565 |
|
|
o_rd_use_read <= instruction_valid && ( rd_conflict1_r || rd_conflict2 );
|
566 |
16 |
csantifort |
end
|
567 |
|
|
|
568 |
|
|
assign o_conflict = conflict;
|
569 |
|
|
|
570 |
|
|
|
571 |
|
|
// ========================================================
|
572 |
|
|
// MTRANS Operations
|
573 |
|
|
// ========================================================
|
574 |
|
|
|
575 |
|
|
// Bit 15 = r15
|
576 |
|
|
// Bit 0 = r0
|
577 |
|
|
// In ldm and stm instructions r0 is loaded or stored first
|
578 |
|
|
always @*
|
579 |
|
|
casez ( instruction[15:0] )
|
580 |
|
|
16'b???????????????1 : mtrans_reg1 = 4'h0 ;
|
581 |
|
|
16'b??????????????10 : mtrans_reg1 = 4'h1 ;
|
582 |
|
|
16'b?????????????100 : mtrans_reg1 = 4'h2 ;
|
583 |
|
|
16'b????????????1000 : mtrans_reg1 = 4'h3 ;
|
584 |
|
|
16'b???????????10000 : mtrans_reg1 = 4'h4 ;
|
585 |
|
|
16'b??????????100000 : mtrans_reg1 = 4'h5 ;
|
586 |
|
|
16'b?????????1000000 : mtrans_reg1 = 4'h6 ;
|
587 |
|
|
16'b????????10000000 : mtrans_reg1 = 4'h7 ;
|
588 |
|
|
16'b???????100000000 : mtrans_reg1 = 4'h8 ;
|
589 |
|
|
16'b??????1000000000 : mtrans_reg1 = 4'h9 ;
|
590 |
|
|
16'b?????10000000000 : mtrans_reg1 = 4'ha ;
|
591 |
|
|
16'b????100000000000 : mtrans_reg1 = 4'hb ;
|
592 |
|
|
16'b???1000000000000 : mtrans_reg1 = 4'hc ;
|
593 |
|
|
16'b??10000000000000 : mtrans_reg1 = 4'hd ;
|
594 |
|
|
16'b?100000000000000 : mtrans_reg1 = 4'he ;
|
595 |
|
|
default : mtrans_reg1 = 4'hf ;
|
596 |
|
|
endcase
|
597 |
|
|
|
598 |
|
|
|
599 |
|
|
assign mtrans_reg2_mask = 1'd1<<mtrans_reg1;
|
600 |
|
|
|
601 |
|
|
always @*
|
602 |
|
|
casez ( instruction[15:0] & ~mtrans_reg2_mask )
|
603 |
|
|
16'b???????????????1 : mtrans_reg2 = 4'h0 ;
|
604 |
|
|
16'b??????????????10 : mtrans_reg2 = 4'h1 ;
|
605 |
|
|
16'b?????????????100 : mtrans_reg2 = 4'h2 ;
|
606 |
|
|
16'b????????????1000 : mtrans_reg2 = 4'h3 ;
|
607 |
|
|
16'b???????????10000 : mtrans_reg2 = 4'h4 ;
|
608 |
|
|
16'b??????????100000 : mtrans_reg2 = 4'h5 ;
|
609 |
|
|
16'b?????????1000000 : mtrans_reg2 = 4'h6 ;
|
610 |
|
|
16'b????????10000000 : mtrans_reg2 = 4'h7 ;
|
611 |
|
|
16'b???????100000000 : mtrans_reg2 = 4'h8 ;
|
612 |
|
|
16'b??????1000000000 : mtrans_reg2 = 4'h9 ;
|
613 |
|
|
16'b?????10000000000 : mtrans_reg2 = 4'ha ;
|
614 |
|
|
16'b????100000000000 : mtrans_reg2 = 4'hb ;
|
615 |
|
|
16'b???1000000000000 : mtrans_reg2 = 4'hc ;
|
616 |
|
|
16'b??10000000000000 : mtrans_reg2 = 4'hd ;
|
617 |
|
|
16'b?100000000000000 : mtrans_reg2 = 4'he ;
|
618 |
|
|
default : mtrans_reg2 = 4'hf ;
|
619 |
|
|
endcase
|
620 |
|
|
|
621 |
|
|
always @*
|
622 |
|
|
casez (instruction[15:0])
|
623 |
|
|
16'b???????????????1 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 1], 1'd0};
|
624 |
|
|
16'b??????????????10 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 2], 2'd0};
|
625 |
|
|
16'b?????????????100 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 3], 3'd0};
|
626 |
|
|
16'b????????????1000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 4], 4'd0};
|
627 |
|
|
16'b???????????10000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 5], 5'd0};
|
628 |
|
|
16'b??????????100000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 6], 6'd0};
|
629 |
|
|
16'b?????????1000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 7], 7'd0};
|
630 |
|
|
16'b????????10000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 8], 8'd0};
|
631 |
|
|
16'b???????100000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 9], 9'd0};
|
632 |
|
|
16'b??????1000000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15:10], 10'd0};
|
633 |
|
|
16'b?????10000000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15:11], 11'd0};
|
634 |
|
|
16'b????100000000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15:12], 12'd0};
|
635 |
|
|
16'b???1000000000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15:13], 13'd0};
|
636 |
|
|
16'b??10000000000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15:14], 14'd0};
|
637 |
|
|
16'b?100000000000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15 ], 15'd0};
|
638 |
|
|
default : mtrans_instruction_nxt = {instruction[31:16], 16'd0};
|
639 |
|
|
endcase
|
640 |
|
|
|
641 |
|
|
|
642 |
|
|
// number of registers to be stored
|
643 |
|
|
assign mtrans_num_registers = {4'd0, instruction[15]} +
|
644 |
|
|
{4'd0, instruction[14]} +
|
645 |
|
|
{4'd0, instruction[13]} +
|
646 |
|
|
{4'd0, instruction[12]} +
|
647 |
|
|
{4'd0, instruction[11]} +
|
648 |
|
|
{4'd0, instruction[10]} +
|
649 |
|
|
{4'd0, instruction[ 9]} +
|
650 |
|
|
{4'd0, instruction[ 8]} +
|
651 |
|
|
{4'd0, instruction[ 7]} +
|
652 |
|
|
{4'd0, instruction[ 6]} +
|
653 |
|
|
{4'd0, instruction[ 5]} +
|
654 |
|
|
{4'd0, instruction[ 4]} +
|
655 |
|
|
{4'd0, instruction[ 3]} +
|
656 |
|
|
{4'd0, instruction[ 2]} +
|
657 |
|
|
{4'd0, instruction[ 1]} +
|
658 |
|
|
{4'd0, instruction[ 0]} ;
|
659 |
|
|
|
660 |
|
|
// 4 x number of registers to be stored
|
661 |
|
|
assign mtrans_base_reg_change = {25'd0, mtrans_num_registers, 2'd0};
|
662 |
|
|
|
663 |
|
|
// ========================================================
|
664 |
|
|
// Interrupts
|
665 |
|
|
// ========================================================
|
666 |
|
|
|
667 |
|
|
assign firq_request = firq && !i_execute_status_bits[26];
|
668 |
|
|
assign irq_request = irq && !i_execute_status_bits[27];
|
669 |
|
|
assign swi_request = type == SWI;
|
670 |
|
|
assign dabt_request = dabt_reg;
|
671 |
|
|
|
672 |
|
|
// copro15 and copro13 only supports reg trans opcodes
|
673 |
|
|
// all other opcodes involving co-processors cause an
|
674 |
|
|
// undefined instrution interrupt
|
675 |
|
|
assign und_request = type == CODTRANS ||
|
676 |
|
|
type == COREGOP ||
|
677 |
|
|
( type == CORTRANS && instruction[11:8] != 4'd15 );
|
678 |
|
|
|
679 |
|
|
|
680 |
|
|
// in order of priority !!
|
681 |
|
|
// Highest
|
682 |
|
|
// 1 Reset
|
683 |
|
|
// 2 Data Abort (including data TLB miss)
|
684 |
|
|
// 3 FIRQ
|
685 |
|
|
// 4 IRQ
|
686 |
|
|
// 5 Prefetch Abort (including prefetch TLB miss)
|
687 |
|
|
// 6 Undefined instruction, SWI
|
688 |
|
|
// Lowest
|
689 |
|
|
assign next_interrupt = dabt_request ? 3'd1 : // Data Abort
|
690 |
|
|
firq_request ? 3'd2 : // FIRQ
|
691 |
|
|
irq_request ? 3'd3 : // IRQ
|
692 |
|
|
instruction_adex ? 3'd4 : // Address Exception
|
693 |
|
|
instruction_iabt ? 3'd5 : // PreFetch Abort, only triggered
|
694 |
|
|
// if the instruction is used
|
695 |
|
|
und_request ? 3'd6 : // Undefined Instruction
|
696 |
|
|
swi_request ? 3'd7 : // SWI
|
697 |
|
|
3'd0 ; // none
|
698 |
|
|
|
699 |
|
|
// SWI and undefined instructions do not cause an interrupt in the decode
|
700 |
|
|
// stage. They only trigger interrupts if they arfe executed, so the
|
701 |
|
|
// interrupt is triggered if the execute condition is met in the execute stage
|
702 |
|
|
assign interrupt = next_interrupt != 3'd0 &&
|
703 |
|
|
next_interrupt != 3'd7 && // SWI
|
704 |
17 |
csantifort |
next_interrupt != 3'd6 && // undefined interrupt
|
705 |
|
|
!conflict ; // Wait for conflicts to resolve before
|
706 |
|
|
// triggering int
|
707 |
16 |
csantifort |
|
708 |
|
|
assign interrupt_mode = next_interrupt == 3'd2 ? FIRQ :
|
709 |
|
|
next_interrupt == 3'd3 ? IRQ :
|
710 |
|
|
next_interrupt == 3'd4 ? SVC :
|
711 |
|
|
next_interrupt == 3'd5 ? SVC :
|
712 |
|
|
next_interrupt == 3'd6 ? SVC :
|
713 |
|
|
next_interrupt == 3'd7 ? SVC :
|
714 |
|
|
next_interrupt == 3'd1 ? SVC :
|
715 |
|
|
USR ;
|
716 |
|
|
|
717 |
|
|
|
718 |
|
|
|
719 |
|
|
|
720 |
|
|
// ========================================================
|
721 |
|
|
// Generate control signals
|
722 |
|
|
// ========================================================
|
723 |
|
|
always @*
|
724 |
|
|
begin
|
725 |
|
|
// default mode
|
726 |
|
|
status_bits_mode_nxt = i_execute_status_bits[1:0]; // change to mode in execute stage get reflected
|
727 |
|
|
// back to this stage automatically
|
728 |
|
|
status_bits_irq_mask_nxt = o_status_bits_irq_mask;
|
729 |
|
|
status_bits_firq_mask_nxt = o_status_bits_firq_mask;
|
730 |
|
|
decode_exclusive_nxt = 1'd0;
|
731 |
|
|
decode_daccess_nxt = 1'd0;
|
732 |
|
|
decode_iaccess_nxt = 1'd1;
|
733 |
|
|
copro_operation_nxt = 'd0;
|
734 |
|
|
|
735 |
|
|
// Save an instruction to use later
|
736 |
|
|
saved_current_instruction_wen = 1'd0;
|
737 |
|
|
pre_fetch_instruction_wen = 1'd0;
|
738 |
|
|
mtrans_r15_nxt = mtrans_r15;
|
739 |
|
|
restore_base_address_nxt = restore_base_address;
|
740 |
|
|
|
741 |
|
|
// default Mux Select values
|
742 |
|
|
barrel_shift_amount_sel_nxt = 'd0; // don't shift the input
|
743 |
|
|
barrel_shift_data_sel_nxt = 'd0; // immediate value
|
744 |
|
|
barrel_shift_function_nxt = 'd0;
|
745 |
|
|
multiply_function_nxt = 'd0;
|
746 |
|
|
iaddress_sel_nxt = 'd0;
|
747 |
|
|
daddress_sel_nxt = 'd0;
|
748 |
|
|
pc_sel_nxt = 'd0;
|
749 |
|
|
load_pc_nxt = 'd0;
|
750 |
|
|
byte_enable_sel_nxt = 'd0;
|
751 |
|
|
status_bits_sel_nxt = 'd0;
|
752 |
|
|
reg_write_sel_nxt = 'd0;
|
753 |
|
|
o_user_mode_regs_store_nxt = 'd0;
|
754 |
|
|
|
755 |
|
|
// ALU Muxes
|
756 |
|
|
alu_swap_sel_nxt = 'd0;
|
757 |
|
|
alu_not_sel_nxt = 'd0;
|
758 |
|
|
alu_cin_sel_nxt = 'd0;
|
759 |
|
|
alu_cout_sel_nxt = 'd0;
|
760 |
|
|
alu_out_sel_nxt = 'd0;
|
761 |
|
|
|
762 |
|
|
// default Flop Write Enable values
|
763 |
|
|
write_data_wen_nxt = 'd0;
|
764 |
|
|
copro_write_data_wen_nxt = 'd0;
|
765 |
|
|
base_address_wen_nxt = 'd0;
|
766 |
|
|
pc_wen_nxt = 'd1;
|
767 |
|
|
reg_bank_wen_nxt = 'd0; // Don't select any
|
768 |
|
|
|
769 |
|
|
status_bits_flags_wen_nxt = 'd0;
|
770 |
|
|
status_bits_mode_wen_nxt = 'd0;
|
771 |
|
|
status_bits_irq_mask_wen_nxt = 'd0;
|
772 |
|
|
status_bits_firq_mask_wen_nxt = 'd0;
|
773 |
|
|
|
774 |
|
|
if ( instruction_valid && !interrupt && !conflict )
|
775 |
|
|
begin
|
776 |
|
|
if ( type == REGOP )
|
777 |
|
|
begin
|
778 |
|
|
if ( !opcode_compare )
|
779 |
|
|
begin
|
780 |
|
|
// Check is the load destination is the PC
|
781 |
|
|
if (instruction[15:12] == 4'd15)
|
782 |
|
|
begin
|
783 |
|
|
pc_sel_nxt = 3'd1; // alu_out
|
784 |
|
|
iaddress_sel_nxt = 4'd1; // alu_out
|
785 |
|
|
end
|
786 |
|
|
else
|
787 |
|
|
reg_bank_wen_nxt = decode (instruction[15:12]);
|
788 |
|
|
end
|
789 |
|
|
|
790 |
|
|
if ( !immediate_shift_op )
|
791 |
|
|
barrel_shift_function_nxt = instruction[6:5];
|
792 |
|
|
|
793 |
|
|
if ( !immediate_shift_op )
|
794 |
|
|
barrel_shift_data_sel_nxt = 2'd2; // Shift value from Rm register
|
795 |
|
|
|
796 |
|
|
if ( !immediate_shift_op && instruction[4] )
|
797 |
|
|
barrel_shift_amount_sel_nxt = 2'd1; // Shift amount from Rs registter
|
798 |
|
|
|
799 |
|
|
if ( !immediate_shift_op && !instruction[4] )
|
800 |
|
|
barrel_shift_amount_sel_nxt = 2'd2; // Shift immediate amount
|
801 |
|
|
|
802 |
|
|
if ( opcode == ADD || opcode == CMN ) // CMN is just like an ADD
|
803 |
|
|
begin
|
804 |
|
|
alu_out_sel_nxt = 4'd1; // Add
|
805 |
|
|
end
|
806 |
|
|
|
807 |
|
|
if ( opcode == ADC ) // Add with Carry
|
808 |
|
|
begin
|
809 |
|
|
alu_out_sel_nxt = 4'd1; // Add
|
810 |
|
|
alu_cin_sel_nxt = 2'd2; // carry in from status_bits
|
811 |
|
|
end
|
812 |
|
|
|
813 |
|
|
if ( opcode == SUB || opcode == CMP ) // Subtract
|
814 |
|
|
begin
|
815 |
|
|
alu_out_sel_nxt = 4'd1; // Add
|
816 |
|
|
alu_cin_sel_nxt = 2'd1; // cin = 1
|
817 |
|
|
alu_not_sel_nxt = 1'd1; // invert B
|
818 |
|
|
end
|
819 |
|
|
|
820 |
|
|
// SBC (Subtract with Carry) subtracts the value of its
|
821 |
|
|
// second operand and the value of NOT(Carry flag) from
|
822 |
|
|
// the value of its first operand.
|
823 |
|
|
// Rd = Rn - shifter_operand - NOT(C Flag)
|
824 |
|
|
if ( opcode == SBC ) // Subtract with Carry
|
825 |
|
|
begin
|
826 |
|
|
alu_out_sel_nxt = 4'd1; // Add
|
827 |
|
|
alu_cin_sel_nxt = 2'd2; // carry in from status_bits
|
828 |
|
|
alu_not_sel_nxt = 1'd1; // invert B
|
829 |
|
|
end
|
830 |
|
|
|
831 |
|
|
if ( opcode == RSB ) // Reverse Subtract
|
832 |
|
|
begin
|
833 |
|
|
alu_out_sel_nxt = 4'd1; // Add
|
834 |
|
|
alu_cin_sel_nxt = 2'd1; // cin = 1
|
835 |
|
|
alu_not_sel_nxt = 1'd1; // invert B
|
836 |
|
|
alu_swap_sel_nxt = 1'd1; // swap A and B
|
837 |
|
|
end
|
838 |
|
|
|
839 |
|
|
if ( opcode == RSC ) // Reverse Subtract with carry
|
840 |
|
|
begin
|
841 |
|
|
alu_out_sel_nxt = 4'd1; // Add
|
842 |
|
|
alu_cin_sel_nxt = 2'd2; // carry in from status_bits
|
843 |
|
|
alu_not_sel_nxt = 1'd1; // invert B
|
844 |
|
|
alu_swap_sel_nxt = 1'd1; // swap A and B
|
845 |
|
|
end
|
846 |
|
|
|
847 |
|
|
if ( opcode == AND || opcode == TST ) // Logical AND, Test (using AND operator)
|
848 |
|
|
begin
|
849 |
|
|
alu_out_sel_nxt = 4'd8; // AND
|
850 |
|
|
alu_cout_sel_nxt = 1'd1; // i_barrel_shift_carry
|
851 |
|
|
end
|
852 |
|
|
|
853 |
|
|
if ( opcode == EOR || opcode == TEQ ) // Logical Exclusive OR, Test Equivalence (using EOR operator)
|
854 |
|
|
begin
|
855 |
|
|
alu_out_sel_nxt = 4'd6; // XOR
|
856 |
|
|
alu_cout_sel_nxt = 1'd1; // i_barrel_shift_carry
|
857 |
|
|
end
|
858 |
|
|
|
859 |
|
|
if ( opcode == ORR )
|
860 |
|
|
begin
|
861 |
|
|
alu_out_sel_nxt = 4'd7; // OR
|
862 |
|
|
alu_cout_sel_nxt = 1'd1; // i_barrel_shift_carry
|
863 |
|
|
end
|
864 |
|
|
|
865 |
|
|
if ( opcode == BIC ) // Bit Clear (using AND & NOT operators)
|
866 |
|
|
begin
|
867 |
|
|
alu_out_sel_nxt = 4'd8; // AND
|
868 |
|
|
alu_not_sel_nxt = 1'd1; // invert B
|
869 |
|
|
alu_cout_sel_nxt = 1'd1; // i_barrel_shift_carry
|
870 |
|
|
end
|
871 |
|
|
|
872 |
|
|
if ( opcode == MOV ) // Move
|
873 |
|
|
begin
|
874 |
|
|
alu_cout_sel_nxt = 1'd1; // i_barrel_shift_carry
|
875 |
|
|
end
|
876 |
|
|
|
877 |
|
|
if ( opcode == MVN ) // Move NOT
|
878 |
|
|
begin
|
879 |
|
|
alu_not_sel_nxt = 1'd1; // invert B
|
880 |
|
|
alu_cout_sel_nxt = 1'd1; // i_barrel_shift_carry
|
881 |
|
|
end
|
882 |
|
|
end
|
883 |
|
|
|
884 |
|
|
// Load & Store instructions
|
885 |
|
|
if ( mem_op )
|
886 |
|
|
begin
|
887 |
|
|
if ( load_op && instruction[15:12] == 4'd15 ) // Write to PC
|
888 |
|
|
begin
|
889 |
|
|
saved_current_instruction_wen = 1'd1; // Save the memory access instruction to refer back to later
|
890 |
|
|
pc_wen_nxt = 1'd0; // hold current PC value rather than an instruction fetch
|
891 |
|
|
load_pc_nxt = 1'd1;
|
892 |
|
|
end
|
893 |
|
|
|
894 |
|
|
decode_daccess_nxt = 1'd1; // indicate a valid data access
|
895 |
|
|
alu_out_sel_nxt = 4'd1; // Add
|
896 |
|
|
|
897 |
|
|
if ( !instruction[23] ) // U: Subtract offset
|
898 |
|
|
begin
|
899 |
|
|
alu_cin_sel_nxt = 2'd1; // cin = 1
|
900 |
|
|
alu_not_sel_nxt = 1'd1; // invert B
|
901 |
|
|
end
|
902 |
|
|
|
903 |
|
|
if ( store_op )
|
904 |
|
|
begin
|
905 |
|
|
write_data_wen_nxt = 1'd1;
|
906 |
|
|
if ( type == TRANS && instruction[22] )
|
907 |
|
|
byte_enable_sel_nxt = 2'd1; // Save byte
|
908 |
|
|
end
|
909 |
|
|
|
910 |
|
|
// need to update the register holding the address ?
|
911 |
|
|
// This is Rn bits [19:16]
|
912 |
|
|
if ( mem_op_pre_indexed || mem_op_post_indexed )
|
913 |
|
|
begin
|
914 |
|
|
// Check is the load destination is the PC
|
915 |
|
|
if ( rn_sel_nxt == 4'd15 )
|
916 |
|
|
pc_sel_nxt = 3'd1;
|
917 |
|
|
else
|
918 |
|
|
reg_bank_wen_nxt = decode ( rn_sel_nxt );
|
919 |
|
|
end
|
920 |
|
|
|
921 |
|
|
// if post-indexed, then use Rn rather than ALU output, as address
|
922 |
|
|
if ( mem_op_post_indexed )
|
923 |
|
|
daddress_sel_nxt = 4'd4; // Rn
|
924 |
|
|
else
|
925 |
|
|
daddress_sel_nxt = 4'd1; // alu out
|
926 |
|
|
|
927 |
|
|
if ( instruction[25] && type == TRANS )
|
928 |
|
|
barrel_shift_data_sel_nxt = 2'd2; // Shift value from Rm register
|
929 |
|
|
|
930 |
|
|
if ( type == TRANS && instruction[25] && shift_imm != 5'd0 )
|
931 |
|
|
begin
|
932 |
|
|
barrel_shift_function_nxt = instruction[6:5];
|
933 |
|
|
barrel_shift_amount_sel_nxt = 2'd2; // imm_shift_amount
|
934 |
|
|
end
|
935 |
|
|
end
|
936 |
|
|
|
937 |
|
|
|
938 |
|
|
if ( type == BRANCH )
|
939 |
|
|
begin
|
940 |
|
|
pc_sel_nxt = 3'd1; // alu_out
|
941 |
|
|
iaddress_sel_nxt = 4'd1; // alu_out
|
942 |
|
|
alu_out_sel_nxt = 4'd1; // Add
|
943 |
|
|
|
944 |
|
|
if ( instruction[24] ) // Link
|
945 |
|
|
begin
|
946 |
|
|
reg_bank_wen_nxt = decode (4'd14); // Save PC to LR
|
947 |
|
|
reg_write_sel_nxt = 3'd1; // pc - 32'd4
|
948 |
|
|
end
|
949 |
|
|
end
|
950 |
|
|
|
951 |
|
|
|
952 |
|
|
if ( type == MTRANS )
|
953 |
|
|
begin
|
954 |
|
|
saved_current_instruction_wen = 1'd1; // Save the memory access instruction to refer back to later
|
955 |
|
|
decode_daccess_nxt = 1'd1; // valid data access
|
956 |
|
|
alu_out_sel_nxt = 4'd1; // Add
|
957 |
|
|
mtrans_r15_nxt = instruction[15]; // load or save r15 ?
|
958 |
|
|
base_address_wen_nxt = 1'd1; // Save the value of the register used for the base address,
|
959 |
|
|
// in case of a data abort, and need to restore the value
|
960 |
|
|
|
961 |
|
|
if ( mtrans_num_registers > 4'd1 )
|
962 |
|
|
begin
|
963 |
|
|
iaddress_sel_nxt = 4'd3; // pc (not pc + 4)
|
964 |
|
|
pc_wen_nxt = 1'd0; // hold current PC value rather than an instruction fetch
|
965 |
|
|
end
|
966 |
|
|
|
967 |
|
|
|
968 |
|
|
// The spec says -
|
969 |
|
|
// If the instruction would have overwritten the base with data
|
970 |
|
|
// (that is, it has the base in the transfer list), the overwriting is prevented.
|
971 |
|
|
// This is true even when the abort occurs after the base word gets loaded
|
972 |
|
|
restore_base_address_nxt = instruction[20] &&
|
973 |
|
|
(instruction[15:0] & (1'd1 << instruction[19:16]));
|
974 |
|
|
|
975 |
|
|
// Increment
|
976 |
|
|
if ( instruction[23] )
|
977 |
|
|
begin
|
978 |
|
|
if ( instruction[24] ) // increment before
|
979 |
|
|
daddress_sel_nxt = 4'd7; // Rn + 4
|
980 |
|
|
else
|
981 |
|
|
daddress_sel_nxt = 4'd4; // Rn
|
982 |
|
|
end
|
983 |
|
|
else
|
984 |
|
|
// Decrement
|
985 |
|
|
begin
|
986 |
|
|
alu_cin_sel_nxt = 2'd1; // cin = 1
|
987 |
|
|
alu_not_sel_nxt = 1'd1; // invert B
|
988 |
|
|
if ( !instruction[24] ) // decrement after
|
989 |
|
|
daddress_sel_nxt = 4'd6; // alu out + 4
|
990 |
|
|
else
|
991 |
|
|
daddress_sel_nxt = 4'd1; // alu out
|
992 |
|
|
end
|
993 |
|
|
|
994 |
|
|
// Load or store ?
|
995 |
|
|
if ( !instruction[20] ) // Store
|
996 |
|
|
write_data_wen_nxt = 1'd1;
|
997 |
|
|
|
998 |
|
|
// stm: store the user mode registers, when in priviledged mode
|
999 |
|
|
if ( {instruction[22:20]} == 3'b100 )
|
1000 |
|
|
o_user_mode_regs_store_nxt = 1'd1;
|
1001 |
|
|
|
1002 |
|
|
// update the base register ?
|
1003 |
|
|
if ( instruction[21] ) // the W bit
|
1004 |
|
|
reg_bank_wen_nxt = decode (rn_sel_nxt);
|
1005 |
|
|
|
1006 |
|
|
// write to the pc ?
|
1007 |
|
|
if ( instruction[20] && mtrans_reg1 == 4'd15 ) // Write to PC
|
1008 |
|
|
begin
|
1009 |
|
|
saved_current_instruction_wen = 1'd1; // Save the memory access instruction to refer back to later
|
1010 |
|
|
pc_wen_nxt = 1'd0; // hold current PC value rather than an instruction fetch
|
1011 |
|
|
load_pc_nxt = 1'd1;
|
1012 |
|
|
end
|
1013 |
|
|
end
|
1014 |
|
|
|
1015 |
|
|
|
1016 |
|
|
if ( type == MULT )
|
1017 |
|
|
begin
|
1018 |
|
|
multiply_function_nxt[0] = 1'd1; // set enable
|
1019 |
|
|
// some bits can be changed just below
|
1020 |
|
|
saved_current_instruction_wen = 1'd1; // Save the Multiply instruction to
|
1021 |
|
|
// refer back to later
|
1022 |
|
|
pc_wen_nxt = 1'd0; // hold current PC value
|
1023 |
|
|
|
1024 |
|
|
if ( instruction[21] )
|
1025 |
|
|
multiply_function_nxt[1] = 1'd1; // accumulate
|
1026 |
|
|
end
|
1027 |
|
|
|
1028 |
|
|
|
1029 |
|
|
// swp - do read part first
|
1030 |
|
|
if ( type == SWAP )
|
1031 |
|
|
begin
|
1032 |
|
|
saved_current_instruction_wen = 1'd1; // Save the memory access instruction to refer back to later
|
1033 |
|
|
pc_wen_nxt = 1'd0; // hold current PC value
|
1034 |
|
|
decode_iaccess_nxt = 1'd0; // skip the instruction fetch
|
1035 |
|
|
decode_daccess_nxt = 1'd1; // data access
|
1036 |
|
|
barrel_shift_data_sel_nxt = 2'd2; // Shift value from Rm register
|
1037 |
|
|
daddress_sel_nxt = 4'd4; // Rn
|
1038 |
|
|
decode_exclusive_nxt = 1'd1; // signal an exclusive access
|
1039 |
|
|
end
|
1040 |
|
|
|
1041 |
|
|
|
1042 |
|
|
// mcr & mrc - takes two cycles
|
1043 |
|
|
if ( type == CORTRANS && !und_request )
|
1044 |
|
|
begin
|
1045 |
|
|
saved_current_instruction_wen = 1'd1; // Save the memory access instruction to refer back to later
|
1046 |
|
|
pc_wen_nxt = 1'd0; // hold current PC value
|
1047 |
|
|
iaddress_sel_nxt = 4'd3; // pc (not pc + 4)
|
1048 |
|
|
|
1049 |
|
|
if ( instruction[20] ) // MRC
|
1050 |
|
|
copro_operation_nxt = 2'd1; // Register transfer from Co-Processor
|
1051 |
|
|
else // MCR
|
1052 |
|
|
begin
|
1053 |
|
|
// Don't enable operation to Co-Processor until next period
|
1054 |
|
|
// So it gets the Rd value from the execution stage at the same time
|
1055 |
|
|
copro_operation_nxt = 2'd0;
|
1056 |
|
|
copro_write_data_wen_nxt = 1'd1; // Rd register value to co-processor
|
1057 |
|
|
end
|
1058 |
|
|
end
|
1059 |
|
|
|
1060 |
|
|
|
1061 |
|
|
if ( type == SWI || und_request )
|
1062 |
|
|
begin
|
1063 |
|
|
// save address of next instruction to Supervisor Mode LR
|
1064 |
|
|
reg_write_sel_nxt = 3'd1; // pc -4
|
1065 |
|
|
reg_bank_wen_nxt = decode (4'd14); // LR
|
1066 |
|
|
|
1067 |
|
|
iaddress_sel_nxt = 4'd2; // interrupt_vector
|
1068 |
|
|
pc_sel_nxt = 3'd2; // interrupt_vector
|
1069 |
|
|
|
1070 |
|
|
status_bits_mode_nxt = interrupt_mode; // e.g. Supervisor mode
|
1071 |
|
|
status_bits_mode_wen_nxt = 1'd1;
|
1072 |
|
|
|
1073 |
|
|
// disable normal interrupts
|
1074 |
|
|
status_bits_irq_mask_nxt = 1'd1;
|
1075 |
|
|
status_bits_irq_mask_wen_nxt = 1'd1;
|
1076 |
|
|
end
|
1077 |
|
|
|
1078 |
|
|
|
1079 |
|
|
if ( regop_set_flags )
|
1080 |
|
|
begin
|
1081 |
|
|
status_bits_flags_wen_nxt = 1'd1;
|
1082 |
|
|
|
1083 |
|
|
// If <Rd> is r15, the ALU output is copied to the Status Bits.
|
1084 |
|
|
// Not allowed to use r15 for mul or lma instructions
|
1085 |
|
|
if ( instruction[15:12] == 4'd15 )
|
1086 |
|
|
begin
|
1087 |
|
|
status_bits_sel_nxt = 3'd1; // alu out
|
1088 |
|
|
|
1089 |
|
|
// Priviledged mode? Then also update the other status bits
|
1090 |
|
|
if ( i_execute_status_bits[1:0] != USR )
|
1091 |
|
|
begin
|
1092 |
|
|
status_bits_mode_wen_nxt = 1'd1;
|
1093 |
|
|
status_bits_irq_mask_wen_nxt = 1'd1;
|
1094 |
|
|
status_bits_firq_mask_wen_nxt = 1'd1;
|
1095 |
|
|
end
|
1096 |
|
|
end
|
1097 |
|
|
end
|
1098 |
|
|
|
1099 |
|
|
end
|
1100 |
|
|
|
1101 |
|
|
// Handle asynchronous interrupts.
|
1102 |
|
|
// interrupts are processed only during execution states
|
1103 |
|
|
// multicycle instructions must complete before the interrupt starts
|
1104 |
|
|
// SWI, Address Exception and Undefined Instruction interrupts are only executed if the
|
1105 |
|
|
// instruction that causes the interrupt is conditionally executed so
|
1106 |
|
|
// its not handled here
|
1107 |
|
|
if ( instruction_valid && interrupt && next_interrupt != 3'd6 )
|
1108 |
|
|
begin
|
1109 |
|
|
// Save the interrupt causing instruction to refer back to later
|
1110 |
|
|
// This also saves the instruction abort vma and status, in the case of an
|
1111 |
|
|
// instruction abort interrupt
|
1112 |
|
|
saved_current_instruction_wen = 1'd1;
|
1113 |
|
|
|
1114 |
|
|
// save address of next instruction to Supervisor Mode LR
|
1115 |
|
|
// Address Exception ?
|
1116 |
|
|
if ( next_interrupt == 3'd4 )
|
1117 |
|
|
reg_write_sel_nxt = 3'd7; // pc
|
1118 |
|
|
else
|
1119 |
|
|
reg_write_sel_nxt = 3'd1; // pc -4
|
1120 |
|
|
|
1121 |
|
|
reg_bank_wen_nxt = decode (4'd14); // LR
|
1122 |
|
|
|
1123 |
|
|
iaddress_sel_nxt = 4'd2; // interrupt_vector
|
1124 |
|
|
pc_sel_nxt = 3'd2; // interrupt_vector
|
1125 |
|
|
|
1126 |
|
|
status_bits_mode_nxt = interrupt_mode; // e.g. Supervisor mode
|
1127 |
|
|
status_bits_mode_wen_nxt = 1'd1;
|
1128 |
|
|
|
1129 |
|
|
// disable normal interrupts
|
1130 |
|
|
status_bits_irq_mask_nxt = 1'd1;
|
1131 |
|
|
status_bits_irq_mask_wen_nxt = 1'd1;
|
1132 |
|
|
|
1133 |
|
|
// disable fast interrupts
|
1134 |
|
|
if ( next_interrupt == 3'd2 ) // FIRQ
|
1135 |
|
|
begin
|
1136 |
|
|
status_bits_firq_mask_nxt = 1'd1;
|
1137 |
|
|
status_bits_firq_mask_wen_nxt = 1'd1;
|
1138 |
|
|
end
|
1139 |
|
|
end
|
1140 |
|
|
|
1141 |
|
|
|
1142 |
|
|
// previous instruction was ldr
|
1143 |
|
|
// if it is currently executing in the execute stage do the following
|
1144 |
|
|
if ( control_state == MEM_WAIT1 && !conflict )
|
1145 |
|
|
begin
|
1146 |
|
|
// Save the next instruction to execute later
|
1147 |
|
|
// Do this even if the ldr instruction does not execute because of Condition
|
1148 |
|
|
pre_fetch_instruction_wen = 1'd1;
|
1149 |
|
|
|
1150 |
|
|
if ( instruction_execute ) // conditional execution state
|
1151 |
|
|
begin
|
1152 |
|
|
iaddress_sel_nxt = 4'd3; // pc (not pc + 4)
|
1153 |
|
|
pc_wen_nxt = 1'd0; // hold current PC value
|
1154 |
|
|
load_pc_nxt = load_pc_r;
|
1155 |
|
|
end
|
1156 |
|
|
end
|
1157 |
|
|
|
1158 |
|
|
|
1159 |
|
|
// completion of ldr instruction
|
1160 |
|
|
if ( control_state == MEM_WAIT2 )
|
1161 |
|
|
begin
|
1162 |
|
|
if ( !dabt ) // dont load data there is an abort on the data read
|
1163 |
|
|
begin
|
1164 |
|
|
pc_wen_nxt = 1'd0; // hold current PC value
|
1165 |
|
|
|
1166 |
|
|
// Check if the load destination is the PC
|
1167 |
|
|
if (( type == TRANS && instruction[15:12] == 4'd15 ) ||
|
1168 |
|
|
( type == MTRANS && instruction[20] && mtrans_reg1 == 4'd15 ))
|
1169 |
|
|
begin
|
1170 |
|
|
pc_sel_nxt = 3'd3; // read_data_filtered
|
1171 |
|
|
iaddress_sel_nxt = 4'd3; // hold value after reading in from mem
|
1172 |
|
|
load_pc_nxt = load_pc_r;
|
1173 |
|
|
end
|
1174 |
|
|
end
|
1175 |
|
|
end
|
1176 |
|
|
|
1177 |
|
|
|
1178 |
|
|
// second cycle of multiple load or store
|
1179 |
|
|
if ( control_state == MTRANS_EXEC1 && !conflict )
|
1180 |
|
|
begin
|
1181 |
|
|
// Save the next instruction to execute later
|
1182 |
|
|
pre_fetch_instruction_wen = 1'd1;
|
1183 |
|
|
|
1184 |
|
|
if ( instruction_execute ) // conditional execution state
|
1185 |
|
|
begin
|
1186 |
|
|
daddress_sel_nxt = 4'd5; // o_address
|
1187 |
|
|
decode_daccess_nxt = 1'd1; // data access
|
1188 |
|
|
|
1189 |
|
|
if ( mtrans_num_registers > 4'd2 )
|
1190 |
|
|
decode_iaccess_nxt = 1'd0; // skip the instruction fetch
|
1191 |
|
|
|
1192 |
|
|
|
1193 |
|
|
if ( mtrans_num_registers != 4'd1 )
|
1194 |
|
|
begin
|
1195 |
|
|
pc_wen_nxt = 1'd0; // hold current PC value
|
1196 |
|
|
iaddress_sel_nxt = 4'd3; // pc (not pc + 4)
|
1197 |
|
|
end
|
1198 |
|
|
|
1199 |
|
|
|
1200 |
|
|
if ( !instruction[20] ) // Store
|
1201 |
|
|
write_data_wen_nxt = 1'd1;
|
1202 |
|
|
|
1203 |
|
|
// stm: store the user mode registers, when in priviledged mode
|
1204 |
|
|
if ( {instruction[22:20]} == 3'b100 )
|
1205 |
|
|
o_user_mode_regs_store_nxt = 1'd1;
|
1206 |
|
|
|
1207 |
|
|
// write to the pc ?
|
1208 |
|
|
if ( instruction[20] && mtrans_reg1 == 4'd15 ) // Write to PC
|
1209 |
|
|
begin
|
1210 |
|
|
saved_current_instruction_wen = 1'd1; // Save the memory access instruction to refer back to later
|
1211 |
|
|
pc_wen_nxt = 1'd0; // hold current PC value rather than an instruction fetch
|
1212 |
|
|
load_pc_nxt = 1'd1;
|
1213 |
|
|
end
|
1214 |
|
|
end
|
1215 |
|
|
end
|
1216 |
|
|
|
1217 |
|
|
|
1218 |
|
|
// third cycle of multiple load or store
|
1219 |
|
|
if ( control_state == MTRANS_EXEC2 )
|
1220 |
|
|
begin
|
1221 |
|
|
daddress_sel_nxt = 4'd5; // o_address
|
1222 |
|
|
decode_daccess_nxt = 1'd1; // data access
|
1223 |
|
|
|
1224 |
|
|
if ( mtrans_num_registers > 4'd2 )
|
1225 |
|
|
begin
|
1226 |
|
|
decode_iaccess_nxt = 1'd0; // skip the instruction fetch
|
1227 |
|
|
end
|
1228 |
|
|
|
1229 |
|
|
if ( mtrans_num_registers > 4'd1 )
|
1230 |
|
|
begin
|
1231 |
|
|
pc_wen_nxt = 1'd0; // hold current PC value
|
1232 |
|
|
iaddress_sel_nxt = 4'd3; // pc (not pc + 4)
|
1233 |
|
|
end
|
1234 |
|
|
|
1235 |
|
|
// Store
|
1236 |
|
|
if ( !instruction[20] )
|
1237 |
|
|
write_data_wen_nxt = 1'd1;
|
1238 |
|
|
|
1239 |
|
|
// stm: store the user mode registers, when in priviledged mode
|
1240 |
|
|
if ( {instruction[22:20]} == 3'b100 )
|
1241 |
|
|
o_user_mode_regs_store_nxt = 1'd1;
|
1242 |
|
|
|
1243 |
|
|
// write to the pc ?
|
1244 |
|
|
if ( instruction[20] && mtrans_reg1 == 4'd15 ) // Write to PC
|
1245 |
|
|
begin
|
1246 |
|
|
saved_current_instruction_wen = 1'd1; // Save the memory access instruction to refer back to later
|
1247 |
|
|
pc_wen_nxt = 1'd0; // hold current PC value rather than an instruction fetch
|
1248 |
|
|
load_pc_nxt = 1'd1;
|
1249 |
|
|
end
|
1250 |
|
|
end
|
1251 |
|
|
|
1252 |
|
|
|
1253 |
|
|
// state is for when a data abort interrupt is triggered during an ldm
|
1254 |
|
|
if ( control_state == MTRANS_ABORT )
|
1255 |
|
|
begin
|
1256 |
|
|
// Restore the Base Address, if the base register is included in the
|
1257 |
|
|
// list of registers being loaded
|
1258 |
|
|
if (restore_base_address) // ldm with base address in register list
|
1259 |
|
|
begin
|
1260 |
|
|
reg_write_sel_nxt = 3'd6; // write base_register
|
1261 |
|
|
reg_bank_wen_nxt = decode ( instruction[19:16] ); // to Rn
|
1262 |
|
|
end
|
1263 |
|
|
end
|
1264 |
|
|
|
1265 |
|
|
|
1266 |
|
|
// Multiply or Multiply-Accumulate
|
1267 |
|
|
if ( control_state == MULT_PROC1 && instruction_execute && !conflict )
|
1268 |
|
|
begin
|
1269 |
|
|
// Save the next instruction to execute later
|
1270 |
|
|
// Do this even if this instruction does not execute because of Condition
|
1271 |
|
|
pre_fetch_instruction_wen = 1'd1;
|
1272 |
|
|
pc_wen_nxt = 1'd0; // hold current PC value
|
1273 |
|
|
multiply_function_nxt = o_multiply_function;
|
1274 |
|
|
end
|
1275 |
|
|
|
1276 |
|
|
|
1277 |
|
|
// Multiply or Multiply-Accumulate
|
1278 |
|
|
// Do multiplication
|
1279 |
|
|
// Wait for done or accumulate signal
|
1280 |
|
|
if ( control_state == MULT_PROC2 )
|
1281 |
|
|
begin
|
1282 |
|
|
// Save the next instruction to execute later
|
1283 |
|
|
// Do this even if this instruction does not execute because of Condition
|
1284 |
|
|
pc_wen_nxt = 1'd0; // hold current PC value
|
1285 |
|
|
iaddress_sel_nxt = 4'd3; // pc (not pc + 4)
|
1286 |
|
|
multiply_function_nxt = o_multiply_function;
|
1287 |
|
|
end
|
1288 |
|
|
|
1289 |
|
|
|
1290 |
|
|
// Save RdLo
|
1291 |
|
|
// always last cycle of all multiply or multiply accumulate operations
|
1292 |
|
|
if ( control_state == MULT_STORE )
|
1293 |
|
|
begin
|
1294 |
|
|
reg_write_sel_nxt = 3'd2; // multiply_out
|
1295 |
|
|
multiply_function_nxt = o_multiply_function;
|
1296 |
|
|
|
1297 |
|
|
if ( type == MULT ) // 32-bit
|
1298 |
|
|
reg_bank_wen_nxt = decode (instruction[19:16]); // Rd
|
1299 |
|
|
else // 64-bit / Long
|
1300 |
|
|
reg_bank_wen_nxt = decode (instruction[15:12]); // RdLo
|
1301 |
|
|
|
1302 |
|
|
if ( instruction[20] ) // the 'S' bit
|
1303 |
|
|
begin
|
1304 |
|
|
status_bits_sel_nxt = 3'd4; // { multiply_flags, status_bits_flags[1:0] }
|
1305 |
|
|
status_bits_flags_wen_nxt = 1'd1;
|
1306 |
|
|
end
|
1307 |
|
|
end
|
1308 |
|
|
|
1309 |
|
|
|
1310 |
|
|
// Add lower 32 bits to multiplication product
|
1311 |
|
|
if ( control_state == MULT_ACCUMU )
|
1312 |
|
|
begin
|
1313 |
|
|
multiply_function_nxt = o_multiply_function;
|
1314 |
|
|
pc_wen_nxt = 1'd0; // hold current PC value
|
1315 |
|
|
iaddress_sel_nxt = 4'd3; // pc (not pc + 4)
|
1316 |
|
|
end
|
1317 |
|
|
|
1318 |
|
|
|
1319 |
|
|
// swp - do write request in 2nd cycle
|
1320 |
|
|
if ( control_state == SWAP_WRITE && instruction_execute && !conflict )
|
1321 |
|
|
begin
|
1322 |
|
|
barrel_shift_data_sel_nxt = 2'd2; // Shift value from Rm register
|
1323 |
|
|
daddress_sel_nxt = 4'd4; // Rn
|
1324 |
|
|
write_data_wen_nxt = 1'd1;
|
1325 |
|
|
decode_iaccess_nxt = 1'd0; // skip the instruction fetch
|
1326 |
|
|
decode_daccess_nxt = 1'd1; // data access
|
1327 |
|
|
|
1328 |
|
|
if ( instruction[22] )
|
1329 |
|
|
byte_enable_sel_nxt = 2'd1; // Save byte
|
1330 |
|
|
|
1331 |
|
|
if ( instruction_execute ) // conditional execution state
|
1332 |
|
|
pc_wen_nxt = 1'd0; // hold current PC value
|
1333 |
|
|
|
1334 |
|
|
// Save the next instruction to execute later
|
1335 |
|
|
// Do this even if this instruction does not execute because of Condition
|
1336 |
|
|
pre_fetch_instruction_wen = 1'd1;
|
1337 |
|
|
|
1338 |
|
|
load_pc_nxt = load_pc_r;
|
1339 |
|
|
end
|
1340 |
|
|
|
1341 |
|
|
|
1342 |
|
|
// swp - receive read response in 3rd cycle
|
1343 |
|
|
if ( control_state == SWAP_WAIT1 )
|
1344 |
|
|
begin
|
1345 |
|
|
|
1346 |
|
|
if ( instruction_execute ) // conditional execution state
|
1347 |
|
|
begin
|
1348 |
|
|
iaddress_sel_nxt = 4'd3; // pc (not pc + 4)
|
1349 |
|
|
pc_wen_nxt = 1'd0; // hold current PC value
|
1350 |
|
|
end
|
1351 |
|
|
|
1352 |
|
|
if ( !dabt )
|
1353 |
|
|
begin
|
1354 |
|
|
// Check is the load destination is the PC
|
1355 |
|
|
if ( instruction[15:12] == 4'd15 )
|
1356 |
|
|
begin
|
1357 |
|
|
pc_sel_nxt = 3'd3; // read_data_filtered
|
1358 |
|
|
iaddress_sel_nxt = 4'd3; // hold value after reading in from mem
|
1359 |
|
|
load_pc_nxt = load_pc_r;
|
1360 |
|
|
end
|
1361 |
|
|
end
|
1362 |
|
|
end
|
1363 |
|
|
|
1364 |
|
|
|
1365 |
|
|
// 1 cycle delay for Co-Processor Register access
|
1366 |
|
|
if ( control_state == COPRO_WAIT && instruction_execute && !conflict )
|
1367 |
|
|
begin
|
1368 |
|
|
pre_fetch_instruction_wen = 1'd1;
|
1369 |
|
|
|
1370 |
|
|
if ( instruction[20] ) // mrc instruction
|
1371 |
|
|
begin
|
1372 |
|
|
// Check is the load destination is the PC
|
1373 |
|
|
if ( instruction[15:12] == 4'd15 )
|
1374 |
|
|
begin
|
1375 |
|
|
// If r15 is specified for <Rd>, the condition code flags are
|
1376 |
|
|
// updated instead of a general-purpose register.
|
1377 |
|
|
status_bits_sel_nxt = 3'd3; // i_copro_data
|
1378 |
|
|
status_bits_flags_wen_nxt = 1'd1;
|
1379 |
|
|
|
1380 |
|
|
// Can't change these in USR mode
|
1381 |
|
|
if ( i_execute_status_bits[1:0] != USR )
|
1382 |
|
|
begin
|
1383 |
|
|
status_bits_mode_wen_nxt = 1'd1;
|
1384 |
|
|
status_bits_irq_mask_wen_nxt = 1'd1;
|
1385 |
|
|
status_bits_firq_mask_wen_nxt = 1'd1;
|
1386 |
|
|
end
|
1387 |
|
|
end
|
1388 |
|
|
else
|
1389 |
|
|
reg_bank_wen_nxt = decode (instruction[15:12]);
|
1390 |
|
|
|
1391 |
|
|
reg_write_sel_nxt = 3'd5; // i_copro_data
|
1392 |
|
|
end
|
1393 |
|
|
else // mcr instruction
|
1394 |
|
|
begin
|
1395 |
|
|
copro_operation_nxt = 2'd2; // Register transfer to Co-Processor
|
1396 |
|
|
end
|
1397 |
|
|
end
|
1398 |
|
|
|
1399 |
|
|
|
1400 |
|
|
// Have just changed the status_bits mode but this
|
1401 |
|
|
// creates a 1 cycle gap with the old mode
|
1402 |
|
|
// coming back from execute into instruction_decode
|
1403 |
|
|
// So squash that old mode value during this
|
1404 |
|
|
// cycle of the interrupt transition
|
1405 |
|
|
if ( control_state == INT_WAIT1 )
|
1406 |
|
|
status_bits_mode_nxt = o_status_bits_mode; // Supervisor mode
|
1407 |
|
|
|
1408 |
|
|
end
|
1409 |
|
|
|
1410 |
|
|
|
1411 |
|
|
// Speed up the long path from u_decode/fetch_instruction_r to u_register_bank/r8_firq
|
1412 |
|
|
// This pre-encodes the firq_s3 signal thats used in u_register_bank
|
1413 |
|
|
// assign firq_not_user_mode_nxt = !user_mode_regs_load_nxt && status_bits_mode_nxt == FIRQ;
|
1414 |
|
|
assign firq_not_user_mode_nxt = status_bits_mode_nxt == FIRQ;
|
1415 |
|
|
|
1416 |
|
|
|
1417 |
|
|
// ========================================================
|
1418 |
|
|
// Next State Logic
|
1419 |
|
|
// ========================================================
|
1420 |
|
|
|
1421 |
|
|
// this replicates the current value of the execute signal in the execute stage
|
1422 |
|
|
assign instruction_execute = conditional_execute ( o_condition, i_execute_status_bits[31:28] );
|
1423 |
|
|
|
1424 |
|
|
|
1425 |
|
|
// First state of executing a new instruction
|
1426 |
|
|
// Its complex because of conditional execution of multi-cycle instructions
|
1427 |
|
|
assign instruction_valid = ((control_state == EXECUTE || control_state == PRE_FETCH_EXEC) ||
|
1428 |
|
|
// when last instruction was multi-cycle instruction but did not execute
|
1429 |
|
|
// because condition was false then act like you're in the execute state
|
1430 |
|
|
(!instruction_execute && (control_state == PC_STALL1 ||
|
1431 |
|
|
control_state == MEM_WAIT1 ||
|
1432 |
|
|
control_state == COPRO_WAIT ||
|
1433 |
|
|
control_state == SWAP_WRITE ||
|
1434 |
|
|
control_state == MULT_PROC1 ||
|
1435 |
|
|
control_state == MTRANS_EXEC1 ) ));
|
1436 |
|
|
|
1437 |
|
|
|
1438 |
|
|
always @*
|
1439 |
|
|
begin
|
1440 |
|
|
// default is to hold the current state
|
1441 |
|
|
control_state_nxt = control_state;
|
1442 |
|
|
|
1443 |
|
|
// Note: The order is important here
|
1444 |
|
|
if ( control_state == RST_WAIT1 ) control_state_nxt = RST_WAIT2;
|
1445 |
|
|
if ( control_state == RST_WAIT2 ) control_state_nxt = EXECUTE;
|
1446 |
|
|
if ( control_state == INT_WAIT1 ) control_state_nxt = INT_WAIT2;
|
1447 |
|
|
if ( control_state == INT_WAIT2 ) control_state_nxt = EXECUTE;
|
1448 |
|
|
if ( control_state == COPRO_WAIT ) control_state_nxt = PRE_FETCH_EXEC;
|
1449 |
|
|
if ( control_state == PC_STALL1 ) control_state_nxt = PC_STALL2;
|
1450 |
|
|
if ( control_state == PC_STALL2 ) control_state_nxt = EXECUTE;
|
1451 |
|
|
if ( control_state == SWAP_WRITE ) control_state_nxt = SWAP_WAIT1;
|
1452 |
|
|
if ( control_state == SWAP_WAIT1 ) control_state_nxt = SWAP_WAIT2;
|
1453 |
|
|
if ( control_state == MULT_STORE ) control_state_nxt = PRE_FETCH_EXEC;
|
1454 |
|
|
if ( control_state == MTRANS_ABORT ) control_state_nxt = PRE_FETCH_EXEC;
|
1455 |
|
|
|
1456 |
|
|
if ( control_state == MEM_WAIT1 )
|
1457 |
|
|
control_state_nxt = MEM_WAIT2;
|
1458 |
|
|
|
1459 |
|
|
if ( control_state == MEM_WAIT2 ||
|
1460 |
|
|
control_state == SWAP_WAIT2 )
|
1461 |
|
|
begin
|
1462 |
|
|
if ( write_pc ) // writing to the PC!!
|
1463 |
|
|
control_state_nxt = PC_STALL1;
|
1464 |
|
|
else
|
1465 |
|
|
control_state_nxt = PRE_FETCH_EXEC;
|
1466 |
|
|
end
|
1467 |
|
|
|
1468 |
|
|
if ( control_state == MTRANS_EXEC1 )
|
1469 |
|
|
begin
|
1470 |
|
|
if ( mtrans_instruction_nxt[15:0] != 16'd0 )
|
1471 |
|
|
control_state_nxt = MTRANS_EXEC2;
|
1472 |
|
|
else // if the register list holds a single register
|
1473 |
|
|
begin
|
1474 |
|
|
if ( dabt ) // data abort
|
1475 |
|
|
control_state_nxt = MTRANS_ABORT;
|
1476 |
|
|
else if ( write_pc ) // writing to the PC!!
|
1477 |
|
|
control_state_nxt = MEM_WAIT1;
|
1478 |
|
|
else
|
1479 |
|
|
control_state_nxt = PRE_FETCH_EXEC;
|
1480 |
|
|
end
|
1481 |
|
|
end
|
1482 |
|
|
|
1483 |
|
|
// Stay in State MTRANS_EXEC2 until the full list of registers to
|
1484 |
|
|
// load or store has been processed
|
1485 |
|
|
if ( control_state == MTRANS_EXEC2 && mtrans_num_registers == 5'd1 )
|
1486 |
|
|
begin
|
1487 |
|
|
if ( dabt ) // data abort
|
1488 |
|
|
control_state_nxt = MTRANS_ABORT;
|
1489 |
|
|
else if ( write_pc ) // writing to the PC!!
|
1490 |
|
|
control_state_nxt = MEM_WAIT1;
|
1491 |
|
|
else
|
1492 |
|
|
control_state_nxt = PRE_FETCH_EXEC;
|
1493 |
|
|
end
|
1494 |
|
|
|
1495 |
|
|
|
1496 |
|
|
if ( control_state == MULT_PROC1 )
|
1497 |
|
|
begin
|
1498 |
|
|
if (!instruction_execute)
|
1499 |
|
|
control_state_nxt = PRE_FETCH_EXEC;
|
1500 |
|
|
else
|
1501 |
|
|
control_state_nxt = MULT_PROC2;
|
1502 |
|
|
end
|
1503 |
|
|
|
1504 |
|
|
if ( control_state == MULT_PROC2 )
|
1505 |
|
|
begin
|
1506 |
|
|
if ( i_multiply_done )
|
1507 |
|
|
if ( o_multiply_function[1] ) // Accumulate ?
|
1508 |
|
|
control_state_nxt = MULT_ACCUMU;
|
1509 |
|
|
else
|
1510 |
|
|
control_state_nxt = MULT_STORE;
|
1511 |
|
|
end
|
1512 |
|
|
|
1513 |
|
|
|
1514 |
|
|
if ( control_state == MULT_ACCUMU )
|
1515 |
|
|
begin
|
1516 |
|
|
control_state_nxt = MULT_STORE;
|
1517 |
|
|
end
|
1518 |
|
|
|
1519 |
|
|
|
1520 |
|
|
// This should come at the end, so that conditional execution works
|
1521 |
|
|
// correctly
|
1522 |
|
|
if ( instruction_valid )
|
1523 |
|
|
begin
|
1524 |
|
|
// default is to stay in execute state, or to move into this
|
1525 |
|
|
// state from a conditional execute state
|
1526 |
|
|
control_state_nxt = EXECUTE;
|
1527 |
|
|
|
1528 |
|
|
if ( current_write_pc )
|
1529 |
|
|
control_state_nxt = PC_STALL1;
|
1530 |
|
|
|
1531 |
|
|
if ( load_op && instruction[15:12] == 4'd15 ) // load new PC value
|
1532 |
|
|
control_state_nxt = MEM_WAIT1;
|
1533 |
|
|
|
1534 |
|
|
// ldm rx, {pc}
|
1535 |
|
|
if ( type == MTRANS && instruction[20] && mtrans_reg1 == 4'd15 ) // Write to PC
|
1536 |
|
|
control_state_nxt = MEM_WAIT1;
|
1537 |
|
|
|
1538 |
|
|
if ( type == MTRANS && !conflict && mtrans_num_registers != 5'd0 && mtrans_num_registers != 5'd1 )
|
1539 |
|
|
control_state_nxt = MTRANS_EXEC1;
|
1540 |
|
|
|
1541 |
|
|
if ( type == MULT && !conflict )
|
1542 |
|
|
control_state_nxt = MULT_PROC1;
|
1543 |
|
|
|
1544 |
|
|
if ( type == SWAP && !conflict )
|
1545 |
|
|
control_state_nxt = SWAP_WRITE;
|
1546 |
|
|
|
1547 |
|
|
if ( type == CORTRANS && !und_request && !conflict )
|
1548 |
|
|
control_state_nxt = COPRO_WAIT;
|
1549 |
|
|
|
1550 |
|
|
// interrupt overrides everything else so its last
|
1551 |
|
|
if ( interrupt && !conflict )
|
1552 |
|
|
control_state_nxt = INT_WAIT1;
|
1553 |
|
|
end
|
1554 |
|
|
|
1555 |
|
|
end
|
1556 |
|
|
|
1557 |
|
|
|
1558 |
|
|
// ========================================================
|
1559 |
|
|
// Register Update
|
1560 |
|
|
// ========================================================
|
1561 |
|
|
always @ ( posedge i_clk )
|
1562 |
|
|
if ( !i_access_stall )
|
1563 |
|
|
begin
|
1564 |
|
|
if (!conflict)
|
1565 |
|
|
begin
|
1566 |
|
|
fetch_instruction_r <= i_fetch_instruction;
|
1567 |
|
|
fetch_address_r <= i_execute_iaddress;
|
1568 |
|
|
iabt_reg <= i_iabt;
|
1569 |
|
|
adex_reg <= i_adex;
|
1570 |
|
|
abt_status_reg <= i_abt_status;
|
1571 |
|
|
end
|
1572 |
|
|
|
1573 |
|
|
o_status_bits_mode <= status_bits_mode_nxt;
|
1574 |
|
|
o_status_bits_irq_mask <= status_bits_irq_mask_nxt;
|
1575 |
|
|
o_status_bits_firq_mask <= status_bits_firq_mask_nxt;
|
1576 |
|
|
o_imm32 <= imm32_nxt;
|
1577 |
|
|
o_imm_shift_amount <= imm_shift_amount_nxt;
|
1578 |
|
|
o_shift_imm_zero <= shift_imm_zero_nxt;
|
1579 |
|
|
|
1580 |
|
|
// when have an interrupt, execute the interrupt operation
|
1581 |
|
|
// unconditionally in the execute stage
|
1582 |
|
|
// ensures that status_bits register gets updated correctly
|
1583 |
|
|
// Likewise when in middle of multi-cycle instructions
|
1584 |
|
|
// execute them unconditionally
|
1585 |
|
|
o_condition <= instruction_valid && !interrupt ? condition_nxt : AL;
|
1586 |
|
|
o_decode_exclusive <= decode_exclusive_nxt;
|
1587 |
|
|
o_decode_iaccess <= decode_iaccess_nxt;
|
1588 |
|
|
o_decode_daccess <= decode_daccess_nxt;
|
1589 |
|
|
|
1590 |
|
|
o_rm_sel <= rm_sel_nxt;
|
1591 |
|
|
o_rs_sel <= rs_sel_nxt;
|
1592 |
|
|
o_load_rd <= load_rd_nxt;
|
1593 |
|
|
load_rd_d1 <= load_rd_d1_nxt;
|
1594 |
|
|
load_pc_r <= load_pc_nxt;
|
1595 |
|
|
o_rn_sel <= rn_sel_nxt;
|
1596 |
|
|
o_barrel_shift_amount_sel <= barrel_shift_amount_sel_nxt;
|
1597 |
|
|
o_barrel_shift_data_sel <= barrel_shift_data_sel_nxt;
|
1598 |
|
|
o_barrel_shift_function <= barrel_shift_function_nxt;
|
1599 |
|
|
o_alu_function <= alu_function_nxt;
|
1600 |
|
|
o_multiply_function <= multiply_function_nxt;
|
1601 |
|
|
o_interrupt_vector_sel <= next_interrupt;
|
1602 |
|
|
o_iaddress_sel <= iaddress_sel_nxt;
|
1603 |
|
|
o_daddress_sel <= daddress_sel_nxt;
|
1604 |
|
|
o_pc_sel <= pc_sel_nxt;
|
1605 |
|
|
o_byte_enable_sel <= byte_enable_sel_nxt;
|
1606 |
|
|
o_status_bits_sel <= status_bits_sel_nxt;
|
1607 |
|
|
o_reg_write_sel <= reg_write_sel_nxt;
|
1608 |
|
|
o_firq_not_user_mode <= firq_not_user_mode_nxt;
|
1609 |
|
|
o_write_data_wen <= write_data_wen_nxt;
|
1610 |
|
|
o_base_address_wen <= base_address_wen_nxt;
|
1611 |
|
|
o_pc_wen <= pc_wen_nxt;
|
1612 |
|
|
o_reg_bank_wen <= reg_bank_wen_nxt;
|
1613 |
|
|
o_status_bits_flags_wen <= status_bits_flags_wen_nxt;
|
1614 |
|
|
o_status_bits_mode_wen <= status_bits_mode_wen_nxt;
|
1615 |
|
|
o_status_bits_irq_mask_wen <= status_bits_irq_mask_wen_nxt;
|
1616 |
|
|
o_status_bits_firq_mask_wen <= status_bits_firq_mask_wen_nxt;
|
1617 |
|
|
|
1618 |
|
|
o_copro_opcode1 <= instruction[23:21];
|
1619 |
|
|
o_copro_opcode2 <= instruction[7:5];
|
1620 |
|
|
o_copro_crn <= instruction[19:16];
|
1621 |
|
|
o_copro_crm <= instruction[3:0];
|
1622 |
|
|
o_copro_num <= instruction[11:8];
|
1623 |
|
|
o_copro_operation <= copro_operation_nxt;
|
1624 |
|
|
o_copro_write_data_wen <= copro_write_data_wen_nxt;
|
1625 |
|
|
mtrans_r15 <= mtrans_r15_nxt;
|
1626 |
|
|
restore_base_address <= restore_base_address_nxt;
|
1627 |
|
|
control_state <= control_state_nxt;
|
1628 |
|
|
end
|
1629 |
|
|
|
1630 |
|
|
|
1631 |
|
|
|
1632 |
|
|
always @ ( posedge i_clk )
|
1633 |
|
|
if ( !i_access_stall )
|
1634 |
|
|
begin
|
1635 |
|
|
// sometimes this is a pre-fetch instruction
|
1636 |
|
|
// e.g. two ldr instructions in a row. The second ldr will be saved
|
1637 |
|
|
// to the pre-fetch instruction register
|
1638 |
|
|
// then when its decoded, a copy is saved to the saved_current_instruction
|
1639 |
|
|
// register
|
1640 |
|
|
if ( type == MTRANS )
|
1641 |
|
|
begin
|
1642 |
|
|
saved_current_instruction <= mtrans_instruction_nxt;
|
1643 |
|
|
saved_current_instruction_iabt <= instruction_iabt;
|
1644 |
|
|
saved_current_instruction_adex <= instruction_adex;
|
1645 |
|
|
saved_current_instruction_address <= instruction_address;
|
1646 |
|
|
saved_current_instruction_iabt_status <= instruction_iabt_status;
|
1647 |
|
|
end
|
1648 |
|
|
else if ( saved_current_instruction_wen )
|
1649 |
|
|
begin
|
1650 |
|
|
saved_current_instruction <= instruction;
|
1651 |
|
|
saved_current_instruction_iabt <= instruction_iabt;
|
1652 |
|
|
saved_current_instruction_adex <= instruction_adex;
|
1653 |
|
|
saved_current_instruction_address <= instruction_address;
|
1654 |
|
|
saved_current_instruction_iabt_status <= instruction_iabt_status;
|
1655 |
|
|
end
|
1656 |
|
|
|
1657 |
|
|
if ( pre_fetch_instruction_wen )
|
1658 |
|
|
begin
|
1659 |
|
|
pre_fetch_instruction <= fetch_instruction_r;
|
1660 |
|
|
pre_fetch_instruction_iabt <= iabt_reg;
|
1661 |
|
|
pre_fetch_instruction_adex <= adex_reg;
|
1662 |
|
|
pre_fetch_instruction_address <= fetch_address_r;
|
1663 |
|
|
pre_fetch_instruction_iabt_status <= abt_status_reg;
|
1664 |
|
|
end
|
1665 |
|
|
|
1666 |
|
|
hold_instruction <= instruction;
|
1667 |
|
|
hold_instruction_iabt <= instruction_iabt;
|
1668 |
|
|
hold_instruction_adex <= instruction_adex;
|
1669 |
|
|
hold_instruction_address <= instruction_address;
|
1670 |
|
|
hold_instruction_iabt_status <= instruction_iabt_status;
|
1671 |
|
|
end
|
1672 |
|
|
|
1673 |
|
|
|
1674 |
|
|
|
1675 |
|
|
always @ ( posedge i_clk )
|
1676 |
|
|
if ( !i_access_stall )
|
1677 |
|
|
begin
|
1678 |
|
|
irq <= i_irq;
|
1679 |
|
|
firq <= i_firq;
|
1680 |
|
|
|
1681 |
|
|
if ( control_state == INT_WAIT1 && o_status_bits_mode == SVC )
|
1682 |
|
|
begin
|
1683 |
|
|
dabt_reg <= 1'd0;
|
1684 |
|
|
end
|
1685 |
|
|
else
|
1686 |
|
|
begin
|
1687 |
|
|
dabt_reg <= dabt_reg || i_dabt;
|
1688 |
|
|
end
|
1689 |
|
|
|
1690 |
|
|
dabt_reg_d1 <= dabt_reg;
|
1691 |
|
|
end
|
1692 |
|
|
|
1693 |
|
|
assign dabt = dabt_reg || i_dabt;
|
1694 |
|
|
|
1695 |
|
|
|
1696 |
|
|
// ========================================================
|
1697 |
|
|
// Decompiler for debugging core - not synthesizable
|
1698 |
|
|
// ========================================================
|
1699 |
|
|
//synopsys translate_off
|
1700 |
|
|
|
1701 |
|
|
`include "debug_functions.v"
|
1702 |
|
|
|
1703 |
|
|
a25_decompile u_decompile (
|
1704 |
|
|
.i_clk ( i_clk ),
|
1705 |
|
|
.i_access_stall ( i_access_stall ),
|
1706 |
|
|
.i_instruction ( instruction ),
|
1707 |
|
|
.i_instruction_valid ( instruction_valid &&!conflict ),
|
1708 |
|
|
.i_instruction_execute ( instruction_execute ),
|
1709 |
|
|
.i_instruction_address ( instruction_address ),
|
1710 |
|
|
.i_interrupt ( {3{interrupt}} & next_interrupt ),
|
1711 |
|
|
.i_interrupt_state ( control_state == INT_WAIT2 ),
|
1712 |
|
|
.i_instruction_undefined ( und_request ),
|
1713 |
|
|
.i_pc_sel ( o_pc_sel ),
|
1714 |
|
|
.i_pc_wen ( o_pc_wen )
|
1715 |
|
|
);
|
1716 |
|
|
|
1717 |
|
|
|
1718 |
|
|
wire [(15*8)-1:0] xCONTROL_STATE;
|
1719 |
|
|
wire [(15*8)-1:0] xMODE;
|
1720 |
|
|
wire [( 8*8)-1:0] xTYPE;
|
1721 |
|
|
|
1722 |
|
|
assign xCONTROL_STATE =
|
1723 |
|
|
control_state == RST_WAIT1 ? "RST_WAIT1" :
|
1724 |
|
|
control_state == RST_WAIT2 ? "RST_WAIT2" :
|
1725 |
|
|
|
1726 |
|
|
|
1727 |
|
|
control_state == INT_WAIT1 ? "INT_WAIT1" :
|
1728 |
|
|
control_state == INT_WAIT2 ? "INT_WAIT2" :
|
1729 |
|
|
control_state == EXECUTE ? "EXECUTE" :
|
1730 |
|
|
control_state == PRE_FETCH_EXEC ? "PRE_FETCH_EXEC" :
|
1731 |
|
|
control_state == MEM_WAIT1 ? "MEM_WAIT1" :
|
1732 |
|
|
control_state == MEM_WAIT2 ? "MEM_WAIT2" :
|
1733 |
|
|
control_state == PC_STALL1 ? "PC_STALL1" :
|
1734 |
|
|
control_state == PC_STALL2 ? "PC_STALL2" :
|
1735 |
|
|
control_state == MTRANS_EXEC1 ? "MTRANS_EXEC1" :
|
1736 |
|
|
control_state == MTRANS_EXEC2 ? "MTRANS_EXEC2" :
|
1737 |
|
|
control_state == MTRANS_ABORT ? "MTRANS_ABORT" :
|
1738 |
|
|
control_state == MULT_PROC1 ? "MULT_PROC1" :
|
1739 |
|
|
control_state == MULT_PROC2 ? "MULT_PROC2" :
|
1740 |
|
|
control_state == MULT_STORE ? "MULT_STORE" :
|
1741 |
|
|
control_state == MULT_ACCUMU ? "MULT_ACCUMU" :
|
1742 |
|
|
control_state == SWAP_WRITE ? "SWAP_WRITE" :
|
1743 |
|
|
control_state == SWAP_WAIT1 ? "SWAP_WAIT1" :
|
1744 |
|
|
control_state == SWAP_WAIT2 ? "SWAP_WAIT2" :
|
1745 |
|
|
control_state == COPRO_WAIT ? "COPRO_WAIT" :
|
1746 |
|
|
"UNKNOWN " ;
|
1747 |
|
|
|
1748 |
|
|
assign xMODE = mode_name ( o_status_bits_mode );
|
1749 |
|
|
|
1750 |
|
|
assign xTYPE =
|
1751 |
|
|
type == REGOP ? "REGOP" :
|
1752 |
|
|
type == MULT ? "MULT" :
|
1753 |
|
|
type == SWAP ? "SWAP" :
|
1754 |
|
|
type == TRANS ? "TRANS" :
|
1755 |
|
|
type == MTRANS ? "MTRANS" :
|
1756 |
|
|
type == BRANCH ? "BRANCH" :
|
1757 |
|
|
type == CODTRANS ? "CODTRANS" :
|
1758 |
|
|
type == COREGOP ? "COREGOP" :
|
1759 |
|
|
type == CORTRANS ? "CORTRANS" :
|
1760 |
|
|
type == SWI ? "SWI" :
|
1761 |
|
|
"UNKNOWN" ;
|
1762 |
|
|
|
1763 |
|
|
|
1764 |
|
|
always @( posedge i_clk )
|
1765 |
|
|
if (control_state == EXECUTE && ((instruction[0] === 1'bx) || (instruction[31] === 1'bx)))
|
1766 |
|
|
begin
|
1767 |
|
|
`TB_ERROR_MESSAGE
|
1768 |
|
|
$display("Instruction with x's =%08h", instruction);
|
1769 |
|
|
end
|
1770 |
|
|
//synopsys translate_on
|
1771 |
|
|
|
1772 |
|
|
endmodule
|
1773 |
|
|
|
1774 |
|
|
|