URL
https://opencores.org/ocsvn/amber/amber/trunk
Subversion Repositories amber
Compare Revisions
- This comparison shows the changes necessary to convert path
/amber/trunk/hw/vlog
- from Rev 88 to Rev 89
- ↔ Reverse comparison
Rev 88 → Rev 89
/amber23/a23_decode.v
52,7 → 52,7
input i_iabt, // instruction pre-fetch abort flag |
input i_adex, // Address Exception |
input [31:0] i_execute_address, // Registered address output by execute stage |
// 2 LSBs of read address used for calculating |
// 2 LSBs of read address used for calculating |
// shift in LDRB ops |
input [7:0] i_abt_status, // Abort status |
input [31:0] i_execute_status_bits, // current status bits values in execute stage |
68,13 → 68,13
output reg [31:0] o_imm32 = 'd0, |
output reg [4:0] o_imm_shift_amount = 'd0, |
output reg o_shift_imm_zero = 'd0, |
output reg [3:0] o_condition = 4'he, // 4'he = al |
output wire [3:0] o_condition, |
output reg o_exclusive_exec = 'd0, // exclusive access request ( swap instruction ) |
output reg o_data_access_exec = 'd0, // high means the memory access is a read |
output reg o_data_access_exec = 'd0, // high means the memory access is a read |
// read or write, low for instruction |
output reg [1:0] o_status_bits_mode = 2'b11, // SVC |
output reg o_status_bits_irq_mask = 1'd1, |
output reg o_status_bits_firq_mask = 1'd1, |
output wire [1:0] o_status_bits_mode, |
output wire o_status_bits_irq_mask, |
output wire o_status_bits_firq_mask, |
|
output reg [3:0] o_rm_sel = 'd0, |
output reg [3:0] o_rds_sel = 'd0, |
89,8 → 89,8
output reg o_use_carry_in = 'd0, |
output reg [1:0] o_multiply_function = 'd0, |
output reg [2:0] o_interrupt_vector_sel = 'd0, |
output reg [3:0] o_address_sel = 4'd2, |
output reg [1:0] o_pc_sel = 2'd2, |
output wire [3:0] o_address_sel, |
output wire [1:0] o_pc_sel, |
output reg [1:0] o_byte_enable_sel = 'd0, // byte, halfword or word write |
output reg [2:0] o_status_bits_sel = 'd0, |
output reg [2:0] o_reg_write_sel, |
101,7 → 101,7
output reg o_write_data_wen = 'd0, |
output reg o_base_address_wen = 'd0, // save LDM base address register |
// in case of data abort |
output reg o_pc_wen = 1'd1, |
output wire o_pc_wen, |
output reg [14:0] o_reg_bank_wen = 'd0, |
output reg [3:0] o_reg_bank_wsel = 'd0, |
output reg o_status_bits_flags_wen = 'd0, |
114,10 → 114,10
// -------------------------------------------------- |
output reg [2:0] o_copro_opcode1 = 'd0, |
output reg [2:0] o_copro_opcode2 = 'd0, |
output reg [3:0] o_copro_crn = 'd0, |
output reg [3:0] o_copro_crn = 'd0, |
output reg [3:0] o_copro_crm = 'd0, |
output reg [3:0] o_copro_num = 'd0, |
output reg [1:0] o_copro_operation = 'd0, // 0 = no operation, |
output reg [1:0] o_copro_operation = 'd0, // 0 = no operation, |
// 1 = Move to Amber Core Register from Coprocessor |
// 2 = Move to Coprocessor from Amber Core Register |
output reg o_copro_write_data_wen = 'd0, |
126,7 → 126,7
output [7:0] o_iabt_status, |
output o_dabt_trigger, |
output [31:0] o_dabt_address, |
output [7:0] o_dabt_status |
output [7:0] o_dabt_status |
|
|
); |
161,8 → 161,8
SWAP_WAIT1 = 5'd23, |
SWAP_WAIT2 = 5'd24, |
COPRO_WAIT = 5'd25; |
|
|
|
|
// ======================================================== |
// Internal signals |
// ======================================================== |
169,7 → 169,7
wire [31:0] instruction; |
wire instruction_iabt; // abort flag, follows the instruction |
wire instruction_adex; // address exception flag, follows the instruction |
wire [31:0] instruction_address; // instruction virtual address, follows |
wire [31:0] instruction_address; // instruction virtual address, follows |
// the instruction |
wire [7:0] instruction_iabt_status; // abort status, follows the instruction |
wire [1:0] instruction_sel; |
292,10 → 292,31
|
|
// ======================================================== |
// registers for output ports with non-zero initial values |
// ======================================================== |
reg [3:0] condition_r = 4'he; // 4'he = al |
reg [1:0] status_bits_mode_r = 2'b11; // SVC |
reg status_bits_irq_mask_r = 1'd1; |
reg status_bits_firq_mask_r = 1'd1; |
reg [3:0] address_sel_r = 4'd2; |
reg [1:0] pc_sel_r = 2'd2; |
reg pc_wen_r = 1'd1; |
|
assign o_condition = condition_r; |
assign o_status_bits_mode = status_bits_mode_r; |
assign o_status_bits_irq_mask = status_bits_irq_mask_r; |
assign o_status_bits_firq_mask = status_bits_firq_mask_r; |
assign o_address_sel = address_sel_r; |
assign o_pc_sel = pc_sel_r; |
assign o_pc_wen = pc_wen_r; |
|
|
|
// ======================================================== |
// Instruction Abort and Data Abort outputs |
// ======================================================== |
|
assign o_iabt_trigger = instruction_iabt && o_status_bits_mode == SVC && control_state == INT_WAIT1; |
assign o_iabt_trigger = instruction_iabt && status_bits_mode_r == SVC && control_state == INT_WAIT1; |
assign o_iabt_address = instruction_address; |
assign o_iabt_status = instruction_iabt_status; |
|
319,7 → 340,7
( control_state == MEM_WAIT1 || |
control_state == MEM_WAIT2 || |
control_state == MTRANS_EXEC1 || |
control_state == MTRANS_EXEC2 || |
control_state == MTRANS_EXEC2 || |
control_state == MTRANS_EXEC3 || |
control_state == MTRANS_EXEC3B || |
control_state == MTRANS_EXEC4 || |
338,9 → 359,9
assign use_pre_fetch_instruction = control_state == PRE_FETCH_EXEC; |
|
|
assign instruction_sel = use_saved_current_instruction ? 2'd1 : // saved_current_instruction |
use_pre_fetch_instruction ? 2'd2 : // pre_fetch_instruction |
2'd0 ; // o_read_data |
assign instruction_sel = use_saved_current_instruction ? 2'd1 : // saved_current_instruction |
use_pre_fetch_instruction ? 2'd2 : // pre_fetch_instruction |
2'd0 ; // o_read_data |
|
assign instruction = instruction_sel == 2'd0 ? o_read_data : |
instruction_sel == 2'd1 ? saved_current_instruction : |
350,7 → 371,7
assign instruction_iabt = instruction_sel == 2'd0 ? iabt_reg : |
instruction_sel == 2'd1 ? saved_current_instruction_iabt : |
pre_fetch_instruction_iabt ; |
|
|
assign instruction_address = instruction_sel == 2'd0 ? abt_address_reg : |
instruction_sel == 2'd1 ? saved_current_instruction_address : |
pre_fetch_instruction_address ; |
370,25 → 391,25
12'b00010?001001 : itype = SWAP; |
12'b000000??1001 : itype = MULT; |
12'b00?????????? : itype = REGOP; |
12'b01?????????? : itype = TRANS; |
12'b100????????? : itype = MTRANS; |
12'b101????????? : itype = BRANCH; |
12'b01?????????? : itype = TRANS; |
12'b100????????? : itype = MTRANS; |
12'b101????????? : itype = BRANCH; |
12'b110????????? : itype = CODTRANS; |
12'b1110???????0 : itype = COREGOP; |
12'b1110???????1 : itype = CORTRANS; |
12'b1110???????0 : itype = COREGOP; |
12'b1110???????1 : itype = CORTRANS; |
default: itype = SWI; |
endcase |
|
|
|
// ======================================================== |
// Fixed fields within the instruction |
// ======================================================== |
|
|
assign opcode = instruction[24:21]; |
assign condition_nxt = instruction[31:28]; |
|
assign o_rm_sel_nxt = instruction[3:0]; |
|
|
assign o_rn_sel_nxt = branch ? 4'd15 : // Use PC to calculate branch destination |
instruction[19:16] ; |
|
395,10 → 416,10
assign o_rds_sel_nxt = control_state == SWAP_WRITE ? instruction[3:0] : // Rm gets written out to memory |
itype == MTRANS ? mtrans_reg : |
branch ? 4'd15 : // Update the PC |
rds_use_rs ? instruction[11:8] : |
rds_use_rs ? instruction[11:8] : |
instruction[15:12] ; |
|
|
|
assign shift_imm = instruction[11:7]; |
|
// this is used for RRX |
410,23 → 431,23
|
assign immediate_shifter_operand = instruction[25]; |
assign rds_use_rs = (itype == REGOP && !instruction[25] && instruction[4]) || |
(itype == MULT && |
(control_state == MULT_PROC1 || |
(itype == MULT && |
(control_state == MULT_PROC1 || |
control_state == MULT_PROC2 || |
instruction_valid && !interrupt )) ; |
assign branch = itype == BRANCH; |
assign opcode_compare = |
opcode == CMP || |
opcode == CMN || |
opcode == TEQ || |
opcode == CMP || |
opcode == CMN || |
opcode == TEQ || |
opcode == TST ; |
|
|
|
|
assign mem_op = itype == TRANS; |
assign load_op = mem_op && instruction[20]; |
assign store_op = mem_op && !instruction[20]; |
assign write_pc = pc_wen_nxt && pc_sel_nxt != 2'd0; |
assign regop_set_flags = itype == REGOP && instruction[20]; |
assign regop_set_flags = itype == REGOP && instruction[20]; |
|
assign mem_op_pre_indexed = instruction[24] && instruction[21]; |
assign mem_op_post_indexed = !instruction[24]; |
433,7 → 454,7
|
assign imm32_nxt = // add 0 to Rm |
itype == MULT ? { 32'd0 } : |
|
|
// 4 x number of registers |
itype == MTRANS ? { mtrans_base_reg_change } : |
itype == BRANCH ? { offset24 } : |
458,25 → 479,25
|
assign imm_shift_amount_nxt = shift_imm ; |
|
// This signal is encoded in the decode stage because |
// This signal is encoded in the decode stage because |
// it is on the critical path in the execute stage |
assign shift_imm_zero_nxt = imm_shift_amount_nxt == 5'd0 && // immediate amount = 0 |
barrel_shift_amount_sel_nxt == 2'd2; // shift immediate amount |
|
assign alu_function_nxt = { alu_swap_sel_nxt, |
alu_not_sel_nxt, |
assign alu_function_nxt = { alu_swap_sel_nxt, |
alu_not_sel_nxt, |
alu_cin_sel_nxt, |
alu_cout_sel_nxt, |
alu_cout_sel_nxt, |
alu_out_sel_nxt }; |
|
|
|
|
// ======================================================== |
// MTRANS Operations |
// ======================================================== |
|
|
// Bit 15 = r15 |
// Bit 0 = R0 |
// In LDM and STM instructions R0 is loaded or stored first |
// In LDM and STM instructions R0 is loaded or stored first |
always @* |
casez (instruction[15:0]) |
16'b???????????????1 : mtrans_reg = 4'h0 ; |
501,28 → 522,28
always @* |
casez (instruction[15:0]) |
16'b???????????????1 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 1], 1'd0}; |
16'b??????????????10 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 2], 2'd0}; |
16'b?????????????100 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 3], 3'd0}; |
16'b????????????1000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 4], 4'd0}; |
16'b???????????10000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 5], 5'd0}; |
16'b??????????100000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 6], 6'd0}; |
16'b?????????1000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 7], 7'd0}; |
16'b????????10000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 8], 8'd0}; |
16'b???????100000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 9], 9'd0}; |
16'b??????1000000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15:10], 10'd0}; |
16'b?????10000000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15:11], 11'd0}; |
16'b????100000000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15:12], 12'd0}; |
16'b???1000000000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15:13], 13'd0}; |
16'b??10000000000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15:14], 14'd0}; |
16'b?100000000000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15 ], 15'd0}; |
default : mtrans_instruction_nxt = {instruction[31:16], 16'd0}; |
16'b??????????????10 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 2], 2'd0}; |
16'b?????????????100 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 3], 3'd0}; |
16'b????????????1000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 4], 4'd0}; |
16'b???????????10000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 5], 5'd0}; |
16'b??????????100000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 6], 6'd0}; |
16'b?????????1000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 7], 7'd0}; |
16'b????????10000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 8], 8'd0}; |
16'b???????100000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 9], 9'd0}; |
16'b??????1000000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15:10], 10'd0}; |
16'b?????10000000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15:11], 11'd0}; |
16'b????100000000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15:12], 12'd0}; |
16'b???1000000000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15:13], 13'd0}; |
16'b??10000000000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15:14], 14'd0}; |
16'b?100000000000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15 ], 15'd0}; |
default : mtrans_instruction_nxt = {instruction[31:16], 16'd0}; |
endcase |
|
|
// number of registers to be stored |
assign mtrans_num_registers = {4'd0, instruction[15]} + |
{4'd0, instruction[14]} + |
{4'd0, instruction[13]} + |
assign mtrans_num_registers = {4'd0, instruction[15]} + |
{4'd0, instruction[14]} + |
{4'd0, instruction[13]} + |
{4'd0, instruction[12]} + |
{4'd0, instruction[11]} + |
{4'd0, instruction[10]} + |
536,7 → 557,7
{4'd0, instruction[ 2]} + |
{4'd0, instruction[ 1]} + |
{4'd0, instruction[ 0]} ; |
|
|
// 4 x number of registers to be stored |
assign mtrans_base_reg_change = {25'd0, mtrans_num_registers, 2'd0}; |
|
550,15 → 571,15
assign dabt_request = dabt_reg; |
|
// copro15 and copro13 only supports reg trans opcodes |
// all other opcodes involving co-processors cause an |
// all other opcodes involving co-processors cause an |
// undefined instrution interrupt |
assign und_request = itype == CODTRANS || |
itype == COREGOP || |
assign und_request = itype == CODTRANS || |
itype == COREGOP || |
( itype == CORTRANS && instruction[11:8] != 4'd15 ); |
|
|
// in order of priority !! |
// Highest |
// in order of priority !! |
// Highest |
// 1 Reset |
// 2 Data Abort (including data TLB miss) |
// 3 FIRQ |
565,21 → 586,21
// 4 IRQ |
// 5 Prefetch Abort (including prefetch TLB miss) |
// 6 Undefined instruction, SWI |
// Lowest |
// Lowest |
assign next_interrupt = dabt_request ? 3'd1 : // Data Abort |
firq_request ? 3'd2 : // FIRQ |
irq_request ? 3'd3 : // IRQ |
instruction_adex ? 3'd4 : // Address Exception |
instruction_iabt ? 3'd5 : // PreFetch Abort, only triggered |
instruction_adex ? 3'd4 : // Address Exception |
instruction_iabt ? 3'd5 : // PreFetch Abort, only triggered |
// if the instruction is used |
und_request ? 3'd6 : // Undefined Instruction |
swi_request ? 3'd7 : // SWI |
3'd0 ; // none |
3'd0 ; // none |
|
// SWI and undefined instructions do not cause an interrupt in the decode |
// stage. They only trigger interrupts if they arfe executed, so the |
// interrupt is triggered if the execute condition is met in the execute stage |
assign interrupt = next_interrupt != 3'd0 && |
assign interrupt = next_interrupt != 3'd0 && |
next_interrupt != 3'd7 && // SWI |
next_interrupt != 3'd6 ; // undefined interrupt |
|
604,18 → 625,18
// default mode |
status_bits_mode_nxt = i_execute_status_bits[1:0]; // change to mode in execute stage get reflected |
// back to this stage automatically |
status_bits_irq_mask_nxt = o_status_bits_irq_mask; |
status_bits_firq_mask_nxt = o_status_bits_firq_mask; |
status_bits_irq_mask_nxt = status_bits_irq_mask_r; |
status_bits_firq_mask_nxt = status_bits_firq_mask_r; |
exclusive_exec_nxt = 1'd0; |
data_access_exec_nxt = 1'd0; |
copro_operation_nxt = 'd0; |
|
|
// Save an instruction to use later |
saved_current_instruction_wen = 1'd0; |
pre_fetch_instruction_wen = 1'd0; |
mtrans_r15_nxt = mtrans_r15; |
restore_base_address_nxt = restore_base_address; |
|
|
// default Mux Select values |
barrel_shift_amount_sel_nxt = 'd0; // don't shift the input |
barrel_shift_data_sel_nxt = 'd0; // immediate value |
622,21 → 643,21
barrel_shift_function_nxt = 'd0; |
use_carry_in_nxt = 'd0; |
multiply_function_nxt = 'd0; |
address_sel_nxt = 'd0; |
pc_sel_nxt = 'd0; |
byte_enable_sel_nxt = 'd0; |
status_bits_sel_nxt = 'd0; |
reg_write_sel_nxt = 'd0; |
address_sel_nxt = 'd0; |
pc_sel_nxt = 'd0; |
byte_enable_sel_nxt = 'd0; |
status_bits_sel_nxt = 'd0; |
reg_write_sel_nxt = 'd0; |
user_mode_regs_load_nxt = 'd0; |
o_user_mode_regs_store_nxt = 'd0; |
|
o_user_mode_regs_store_nxt = 'd0; |
|
// ALU Muxes |
alu_swap_sel_nxt = 'd0; |
alu_not_sel_nxt = 'd0; |
alu_cin_sel_nxt = 'd0; |
alu_cout_sel_nxt = 'd0; |
alu_out_sel_nxt = 'd0; |
|
alu_swap_sel_nxt = 'd0; |
alu_not_sel_nxt = 'd0; |
alu_cin_sel_nxt = 'd0; |
alu_cout_sel_nxt = 'd0; |
alu_out_sel_nxt = 'd0; |
|
// default Flop Write Enable values |
write_data_wen_nxt = 'd0; |
copro_write_data_wen_nxt = 'd0; |
647,7 → 668,7
status_bits_mode_wen_nxt = 'd0; |
status_bits_irq_mask_wen_nxt = 'd0; |
status_bits_firq_mask_wen_nxt = 'd0; |
|
|
if ( instruction_valid && !interrupt ) |
begin |
if ( itype == REGOP ) |
660,24 → 681,24
pc_sel_nxt = 2'd1; // alu_out |
address_sel_nxt = 4'd1; // alu_out |
end |
else |
else |
reg_bank_wsel_nxt = instruction[15:12]; |
end |
|
|
if ( !immediate_shifter_operand ) |
barrel_shift_function_nxt = instruction[6:5]; |
|
|
if ( !immediate_shifter_operand ) |
barrel_shift_data_sel_nxt = 2'd2; // Shift value from Rm register |
|
|
if ( !immediate_shifter_operand && instruction[4] ) |
barrel_shift_amount_sel_nxt = 2'd1; // Shift amount from Rs registter |
|
if ( !immediate_shifter_operand && !instruction[4] ) |
barrel_shift_amount_sel_nxt = 2'd2; // Shift immediate amount |
|
|
if ( !immediate_shifter_operand && !instruction[4] ) |
barrel_shift_amount_sel_nxt = 2'd2; // Shift immediate amount |
|
// regops that do not change the overflow flag |
if ( opcode == AND || opcode == EOR || opcode == TST || opcode == TEQ || |
if ( opcode == AND || opcode == EOR || opcode == TST || opcode == TEQ || |
opcode == ORR || opcode == MOV || opcode == BIC || opcode == MVN ) |
status_bits_sel_nxt = 3'd5; |
|
686,7 → 707,7
alu_out_sel_nxt = 4'd1; // Add |
use_carry_in_nxt = shift_extend; |
end |
|
|
if ( opcode == ADC ) // Add with Carry |
begin |
alu_out_sel_nxt = 4'd1; // Add |
693,7 → 714,7
alu_cin_sel_nxt = 2'd2; // carry in from status_bits |
use_carry_in_nxt = shift_extend; |
end |
|
|
if ( opcode == SUB || opcode == CMP ) // Subtract |
begin |
alu_out_sel_nxt = 4'd1; // Add |
700,8 → 721,8
alu_cin_sel_nxt = 2'd1; // cin = 1 |
alu_not_sel_nxt = 1'd1; // invert B |
end |
|
// SBC (Subtract with Carry) subtracts the value of its |
|
// SBC (Subtract with Carry) subtracts the value of its |
// second operand and the value of NOT(Carry flag) from |
// the value of its first operand. |
// Rd = Rn - shifter_operand - NOT(C Flag) |
712,7 → 733,7
alu_not_sel_nxt = 1'd1; // invert B |
use_carry_in_nxt = 1'd1; |
end |
|
|
if ( opcode == RSB ) // Reverse Subtract |
begin |
alu_out_sel_nxt = 4'd1; // Add |
720,7 → 741,7
alu_not_sel_nxt = 1'd1; // invert B |
alu_swap_sel_nxt = 1'd1; // swap A and B |
end |
|
|
if ( opcode == RSC ) // Reverse Subtract with carry |
begin |
alu_out_sel_nxt = 4'd1; // Add |
729,13 → 750,13
alu_swap_sel_nxt = 1'd1; // swap A and B |
use_carry_in_nxt = 1'd1; |
end |
|
|
if ( opcode == AND || opcode == TST ) // Logical AND, Test (using AND operator) |
begin |
alu_out_sel_nxt = 4'd8; // AND |
alu_cout_sel_nxt = 1'd1; // i_barrel_shift_carry |
end |
|
|
if ( opcode == EOR || opcode == TEQ ) // Logical Exclusive OR, Test Equivalence (using EOR operator) |
begin |
alu_out_sel_nxt = 4'd6; // XOR |
749,7 → 770,7
alu_cout_sel_nxt = 1'd1; // i_barrel_shift_carry |
use_carry_in_nxt = 1'd1; |
end |
|
|
if ( opcode == BIC ) // Bit Clear (using AND & NOT operators) |
begin |
alu_out_sel_nxt = 4'd8; // AND |
757,13 → 778,13
alu_cout_sel_nxt = 1'd1; // i_barrel_shift_carry |
use_carry_in_nxt = 1'd1; |
end |
|
|
if ( opcode == MOV ) // Move |
begin |
alu_cout_sel_nxt = 1'd1; // i_barrel_shift_carry |
use_carry_in_nxt = 1'd1; |
end |
|
|
if ( opcode == MVN ) // Move NOT |
begin |
alu_not_sel_nxt = 1'd1; // invert B |
771,22 → 792,22
use_carry_in_nxt = 1'd1; |
end |
end |
|
|
// Load & Store instructions |
if ( mem_op ) |
begin |
saved_current_instruction_wen = 1'd1; // Save the memory access instruction to refer back to later |
pc_wen_nxt = 1'd0; // hold current PC value |
data_access_exec_nxt = 1'd1; // indicate that its a data read or write, |
data_access_exec_nxt = 1'd1; // indicate that its a data read or write, |
// rather than an instruction fetch |
alu_out_sel_nxt = 4'd1; // Add |
|
|
if ( !instruction[23] ) // U: Subtract offset |
begin |
alu_cin_sel_nxt = 2'd1; // cin = 1 |
alu_not_sel_nxt = 1'd1; // invert B |
end |
|
|
if ( store_op ) |
begin |
write_data_wen_nxt = 1'd1; |
793,7 → 814,7
if ( itype == TRANS && instruction[22] ) |
byte_enable_sel_nxt = 2'd1; // Save byte |
end |
|
|
// need to update the register holding the address ? |
// This is Rn bits [19:16] |
if ( mem_op_pre_indexed || mem_op_post_indexed ) |
800,33 → 821,33
begin |
// Check is the load destination is the PC |
if ( o_rn_sel_nxt == 4'd15 ) |
pc_sel_nxt = 2'd1; |
else |
pc_sel_nxt = 2'd1; |
else |
reg_bank_wsel_nxt = o_rn_sel_nxt; |
end |
|
|
// if post-indexed, then use Rn rather than ALU output, as address |
if ( mem_op_post_indexed ) |
address_sel_nxt = 4'd4; // Rn |
else |
else |
address_sel_nxt = 4'd1; // alu out |
|
|
if ( instruction[25] && itype == TRANS ) |
barrel_shift_data_sel_nxt = 2'd2; // Shift value from Rm register |
|
if ( itype == TRANS && instruction[25] && shift_imm != 5'd0 ) |
begin |
|
if ( itype == TRANS && instruction[25] && shift_imm != 5'd0 ) |
begin |
barrel_shift_function_nxt = instruction[6:5]; |
barrel_shift_amount_sel_nxt = 2'd2; // imm_shift_amount |
end |
end |
|
|
if ( itype == BRANCH ) |
begin |
pc_sel_nxt = 2'd1; // alu_out |
address_sel_nxt = 4'd1; // alu_out |
alu_out_sel_nxt = 4'd1; // Add |
|
|
if ( instruction[24] ) // Link |
begin |
reg_bank_wsel_nxt = 4'd14; // Save PC to LR |
833,23 → 854,23
reg_write_sel_nxt = 3'd1; // pc - 32'd4 |
end |
end |
|
|
if ( itype == MTRANS ) |
begin |
saved_current_instruction_wen = 1'd1; // Save the memory access instruction to refer back to later |
pc_wen_nxt = 1'd0; // hold current PC value |
data_access_exec_nxt = 1'd1; // indicate that its a data read or write, |
data_access_exec_nxt = 1'd1; // indicate that its a data read or write, |
// rather than an instruction fetch |
alu_out_sel_nxt = 4'd1; // Add |
mtrans_r15_nxt = instruction[15]; // load or save r15 ? |
base_address_wen_nxt = 1'd1; // Save the value of the register used for the base address, |
// in case of a data abort, and need to restore the value |
// in case of a data abort, and need to restore the value |
|
// The spec says - |
// If the instruction would have overwritten the base with data |
// If the instruction would have overwritten the base with data |
// (that is, it has the base in the transfer list), the overwriting is prevented. |
// This is true even when the abort occurs after the base word gets loaded |
restore_base_address_nxt = instruction[20] && |
restore_base_address_nxt = instruction[20] && |
(instruction[15:0] & (1'd1 << instruction[19:16])); |
|
// Increment or Decrement |
857,7 → 878,7
begin |
if ( instruction[24] ) // increment before |
address_sel_nxt = 4'd7; // Rn + 4 |
else |
else |
address_sel_nxt = 4'd4; // Rn |
end |
else // decrement |
869,47 → 890,47
else |
address_sel_nxt = 4'd1; // alu out |
end |
|
|
// Load or store ? |
if ( !instruction[20] ) // Store |
write_data_wen_nxt = 1'd1; |
|
// LDM: load into user mode registers, when in priviledged mode |
// Don't use mtrans_r15 here because its not loaded yet |
write_data_wen_nxt = 1'd1; |
|
// LDM: load into user mode registers, when in priviledged mode |
// Don't use mtrans_r15 here because its not loaded yet |
//if ( {instruction[22],instruction[20],instruction[15]} == 3'b110 ) |
if ( {instruction[22:20],instruction[15]} == 4'b1010 ) |
if ( {instruction[22:20],instruction[15]} == 4'b1010 ) |
user_mode_regs_load_nxt = 1'd1; |
|
// SDM: store the user mode registers, when in priviledged mode |
//if ( {instruction[22],instruction[20]} == 3'b10 ) |
// SDM: store the user mode registers, when in priviledged mode |
//if ( {instruction[22],instruction[20]} == 3'b10 ) |
if ( {instruction[22:20]} == 3'b100 ) |
o_user_mode_regs_store_nxt = 1'd1; |
|
|
// update the base register ? |
if ( instruction[21] ) // the W bit |
reg_bank_wsel_nxt = o_rn_sel_nxt; |
end |
|
|
|
|
if ( itype == MULT ) |
begin |
multiply_function_nxt[0] = 1'd1; // set enable |
// some bits can be changed just below |
saved_current_instruction_wen = 1'd1; // Save the Multiply instruction to |
saved_current_instruction_wen = 1'd1; // Save the Multiply instruction to |
// refer back to later |
pc_wen_nxt = 1'd0; // hold current PC value |
|
|
if ( instruction[21] ) |
multiply_function_nxt[1] = 1'd1; // accumulate |
end |
|
|
|
|
// swp - do read part first |
if ( itype == SWAP ) |
begin |
saved_current_instruction_wen = 1'd1; // Save the memory access instruction to refer back to later |
pc_wen_nxt = 1'd0; // hold current PC value |
data_access_exec_nxt = 1'd1; // indicate that its a data read or write, |
data_access_exec_nxt = 1'd1; // indicate that its a data read or write, |
// rather than an instruction fetch |
barrel_shift_data_sel_nxt = 2'd2; // Shift value from Rm register |
address_sel_nxt = 4'd4; // Rn |
923,7 → 944,7
saved_current_instruction_wen = 1'd1; // Save the memory access instruction to refer back to later |
pc_wen_nxt = 1'd0; // hold current PC value |
address_sel_nxt = 4'd3; // pc (not pc + 4) |
|
|
if ( instruction[20] ) // MRC |
copro_operation_nxt = 2'd1; // Register transfer from Co-Processor |
else // MCR |
935,35 → 956,35
end |
end |
|
|
|
if ( itype == SWI || und_request ) |
begin |
// save address of next instruction to Supervisor Mode LR |
reg_write_sel_nxt = 3'd1; // pc -4 |
reg_bank_wsel_nxt = 4'd14; // LR |
|
|
address_sel_nxt = 4'd2; // interrupt_vector |
pc_sel_nxt = 2'd2; // interrupt_vector |
|
|
status_bits_mode_nxt = interrupt_mode; // e.g. Supervisor mode |
status_bits_mode_wen_nxt = 1'd1; |
|
|
// disable normal interrupts |
status_bits_irq_mask_nxt = 1'd1; |
status_bits_irq_mask_wen_nxt = 1'd1; |
end |
|
|
|
if ( regop_set_flags ) |
begin |
status_bits_flags_wen_nxt = 1'd1; |
|
// If <Rd> is r15, the ALU output is copied to the Status Bits. |
// Not allowed to use r15 for mul or lma instructions |
|
// If <Rd> is r15, the ALU output is copied to the Status Bits. |
// Not allowed to use r15 for mul or lma instructions |
if ( instruction[15:12] == 4'd15 ) |
begin |
status_bits_sel_nxt = 3'd1; // alu out |
|
|
// Priviledged mode? Then also update the other status bits |
if ( i_execute_status_bits[1:0] != USR ) |
begin |
973,9 → 994,9
end |
end |
end |
|
end |
|
end |
|
// Handle asynchronous interrupts. |
// interrupts are processed only during execution states |
// multicycle instructions must complete before the interrupt starts |
987,8 → 1008,8
// Save the interrupt causing instruction to refer back to later |
// This also saves the instruction abort vma and status, in the case of an |
// instruction abort interrupt |
saved_current_instruction_wen = 1'd1; |
|
saved_current_instruction_wen = 1'd1; |
|
// save address of next instruction to Supervisor Mode LR |
// Address Exception ? |
if ( next_interrupt == 3'd4 ) |
995,15 → 1016,15
reg_write_sel_nxt = 3'd7; // pc |
else |
reg_write_sel_nxt = 3'd1; // pc -4 |
|
|
reg_bank_wsel_nxt = 4'd14; // LR |
|
|
address_sel_nxt = 4'd2; // interrupt_vector |
pc_sel_nxt = 2'd2; // interrupt_vector |
|
|
status_bits_mode_nxt = interrupt_mode; // e.g. Supervisor mode |
status_bits_mode_wen_nxt = 1'd1; |
|
|
// disable normal interrupts |
status_bits_irq_mask_nxt = 1'd1; |
status_bits_irq_mask_wen_nxt = 1'd1; |
1015,16 → 1036,16
status_bits_firq_mask_wen_nxt = 1'd1; |
end |
end |
|
|
|
// previous instruction was either ldr or sdr |
// if it is currently executing in the execute stage do the following |
// if it is currently executing in the execute stage do the following |
if ( control_state == MEM_WAIT1 ) |
begin |
// Save the next instruction to execute later |
// Do this even if this instruction does not execute because of Condition |
pre_fetch_instruction_wen = 1'd1; |
|
|
if ( instruction_execute ) // conditional execution state |
begin |
address_sel_nxt = 4'd3; // pc (not pc + 4) |
1031,24 → 1052,24
pc_wen_nxt = 1'd0; // hold current PC value |
end |
end |
|
|
// completion of load operation |
|
|
// completion of load operation |
if ( control_state == MEM_WAIT2 && load_op ) |
begin |
barrel_shift_data_sel_nxt = 2'd1; // load word from memory |
barrel_shift_amount_sel_nxt = 2'd3; // shift by address[1:0] x 8 |
|
|
// shift needed |
if ( i_execute_address[1:0] != 2'd0 ) |
barrel_shift_function_nxt = ROR; |
|
// load a byte |
|
// load a byte |
if ( itype == TRANS && instruction[22] ) |
alu_out_sel_nxt = 4'd3; // zero_extend8 |
|
|
if ( !dabt ) // dont load data there is an abort on the data read |
begin |
begin |
// Check if the load destination is the PC |
if (instruction[15:12] == 4'd15) |
begin |
1055,12 → 1076,12
pc_sel_nxt = 2'd1; // alu_out |
address_sel_nxt = 4'd1; // alu_out |
end |
else |
else |
reg_bank_wsel_nxt = instruction[15:12]; |
end |
end |
|
|
|
|
// second cycle of multiple load or store |
if ( control_state == MTRANS_EXEC1 ) |
begin |
1067,39 → 1088,39
// Save the next instruction to execute later |
// Do this even if this instruction does not execute because of Condition |
pre_fetch_instruction_wen = 1'd1; |
|
|
if ( instruction_execute ) // conditional execution state |
begin |
address_sel_nxt = 4'd5; // o_address |
pc_wen_nxt = 1'd0; // hold current PC value |
data_access_exec_nxt = 1'd1; // indicate that its a data read or write, |
data_access_exec_nxt = 1'd1; // indicate that its a data read or write, |
// rather than an instruction fetch |
|
|
if ( !instruction[20] ) // Store |
write_data_wen_nxt = 1'd1; |
|
// LDM: load into user mode registers, when in priviledged mode |
|
// LDM: load into user mode registers, when in priviledged mode |
//if ( {instruction[22],instruction[20],mtrans_r15} == 3'b110 ) |
if ( {instruction[22:20],mtrans_r15} == 4'b1010 ) |
user_mode_regs_load_nxt = 1'd1; |
|
// SDM: store the user mode registers, when in priviledged mode |
//if ( {instruction[22],instruction[20]} == 2'b10 ) |
|
// SDM: store the user mode registers, when in priviledged mode |
//if ( {instruction[22],instruction[20]} == 2'b10 ) |
if ( {instruction[22:20]} == 3'b100 ) |
o_user_mode_regs_store_nxt = 1'd1; |
end |
end |
|
|
end |
end |
|
|
// third cycle of multiple load or store |
if ( control_state == MTRANS_EXEC2 ) |
begin |
address_sel_nxt = 4'd5; // o_address |
pc_wen_nxt = 1'd0; // hold current PC value |
data_access_exec_nxt = 1'd1; // indicate that its a data read or write, |
data_access_exec_nxt = 1'd1; // indicate that its a data read or write, |
// rather than an instruction fetch |
barrel_shift_data_sel_nxt = 2'd1; // load word from memory |
|
|
// Load or Store |
if ( instruction[20] ) // Load |
begin |
1110,17 → 1131,17
end |
else // Store |
write_data_wen_nxt = 1'd1; |
|
// LDM: load into user mode registers, when in priviledged mode |
|
// LDM: load into user mode registers, when in priviledged mode |
if ( {instruction[22],instruction[20],mtrans_r15} == 3'b110 ) |
user_mode_regs_load_nxt = 1'd1; |
|
// SDM: store the user mode registers, when in priviledged mode |
if ( {instruction[22],instruction[20]} == 2'b10 ) |
|
// SDM: store the user mode registers, when in priviledged mode |
if ( {instruction[22],instruction[20]} == 2'b10 ) |
o_user_mode_regs_store_nxt = 1'd1; |
end |
|
|
|
|
// second or fourth cycle of multiple load or store |
if ( control_state == MTRANS_EXEC3 && instruction_execute ) |
begin |
1127,19 → 1148,19
address_sel_nxt = 4'd3; // pc (not pc + 4) |
pc_wen_nxt = 1'd0; // hold current PC value |
barrel_shift_data_sel_nxt = 2'd1; // load word from memory |
|
|
// Can never be loading the PC in this state, as the PC is always |
// the last register in the set to be loaded |
if ( instruction[20] && !dabt ) // Load |
reg_bank_wsel_nxt = mtrans_reg_d2; |
|
// LDM: load into user mode registers, when in priviledged mode |
|
// LDM: load into user mode registers, when in priviledged mode |
if ( {instruction[22],instruction[20],mtrans_r15} == 3'b110 ) |
user_mode_regs_load_nxt = 1'd1; |
|
// SDM: store the user mode registers, when in priviledged mode |
//if ( {instruction[22:20]} == 3'b100 ) |
if ( {instruction[22],instruction[20]} == 2'b10 ) |
|
// SDM: store the user mode registers, when in priviledged mode |
//if ( {instruction[22:20]} == 3'b100 ) |
if ( {instruction[22],instruction[20]} == 2'b10 ) |
o_user_mode_regs_store_nxt = 1'd1; |
end |
|
1149,23 → 1170,23
// Save the next instruction to execute later |
// Do this even if this instruction does not execute because of Condition |
pre_fetch_instruction_wen = 1'd1; |
|
|
address_sel_nxt = 4'd3; // pc (not pc + 4) |
pc_wen_nxt = 1'd0; // hold current PC value |
|
// LDM: load into user mode registers, when in priviledged mode |
|
// LDM: load into user mode registers, when in priviledged mode |
if ( {instruction[22],instruction[20],mtrans_r15} == 3'b110 ) |
user_mode_regs_load_nxt = 1'd1; |
|
// SDM: store the user mode registers, when in priviledged mode |
if ( {instruction[22],instruction[20]} == 2'b10 ) |
|
// SDM: store the user mode registers, when in priviledged mode |
if ( {instruction[22],instruction[20]} == 2'b10 ) |
o_user_mode_regs_store_nxt = 1'd1; |
end |
|
|
if ( control_state == MTRANS_EXEC4 ) |
begin |
barrel_shift_data_sel_nxt = 2'd1; // load word from memory |
|
|
if ( instruction[20] ) // Load |
begin |
if (!dabt) // dont overwrite registers or status if theres a data abort |
1175,18 → 1196,18
address_sel_nxt = 4'd1; // alu_out - read instructions using new PC value |
pc_sel_nxt = 2'd1; // alu_out |
pc_wen_nxt = 1'd1; // write PC |
|
|
// ldm with S bit and pc: the Status bits are updated |
// Node this must be done only at the end |
// so the register set is the set in the mode before it |
// gets changed. |
if ( instruction[22] ) |
// gets changed. |
if ( instruction[22] ) |
begin |
status_bits_sel_nxt = 3'd1; // alu out |
status_bits_flags_wen_nxt = 1'd1; |
|
|
// Can't change the mode or mask bits in User mode |
if ( i_execute_status_bits[1:0] != USR ) |
if ( i_execute_status_bits[1:0] != USR ) |
begin |
status_bits_mode_wen_nxt = 1'd1; |
status_bits_irq_mask_wen_nxt = 1'd1; |
1200,23 → 1221,23
end |
end |
end |
|
|
// we have a data abort interrupt |
if ( dabt ) |
begin |
begin |
pc_wen_nxt = 1'd0; // hold current PC value |
end |
|
// LDM: load into user mode registers, when in priviledged mode |
|
// LDM: load into user mode registers, when in priviledged mode |
if ( {instruction[22],instruction[20],mtrans_r15} == 3'b110 ) |
user_mode_regs_load_nxt = 1'd1; |
|
// SDM: store the user mode registers, when in priviledged mode |
if ( {instruction[22],instruction[20]} == 2'b10 ) |
|
// SDM: store the user mode registers, when in priviledged mode |
if ( {instruction[22],instruction[20]} == 2'b10 ) |
o_user_mode_regs_store_nxt = 1'd1; |
end |
|
|
|
|
// state is for when a data abort interrupt is triggered during an LDM |
if ( control_state == MTRANS5_ABORT ) |
begin |
1228,8 → 1249,8
reg_bank_wsel_nxt = instruction[19:16]; // to Rn |
end |
end |
|
|
|
|
// Multiply or Multiply-Accumulate |
if ( control_state == MULT_PROC1 && instruction_execute ) |
begin |
1240,7 → 1261,7
multiply_function_nxt = o_multiply_function; |
end |
|
|
|
// Multiply or Multiply-Accumulate |
// Do multiplication |
// Wait for done or accumulate signal |
1253,7 → 1274,7
multiply_function_nxt = o_multiply_function; |
end |
|
|
|
// Save RdLo |
// always last cycle of all multiply or multiply accumulate operations |
if ( control_state == MULT_STORE ) |
1260,19 → 1281,19
begin |
reg_write_sel_nxt = 3'd2; // multiply_out |
multiply_function_nxt = o_multiply_function; |
|
|
if ( itype == MULT ) // 32-bit |
reg_bank_wsel_nxt = instruction[19:16]; // Rd |
else // 64-bit / Long |
reg_bank_wsel_nxt = instruction[15:12]; // RdLo |
|
|
if ( instruction[20] ) // the 'S' bit |
begin |
status_bits_sel_nxt = 3'd4; // { multiply_flags, status_bits_flags[1:0] } |
status_bits_sel_nxt = 3'd4; // { multiply_flags, status_bits_flags[1:0] } |
status_bits_flags_wen_nxt = 1'd1; |
end |
end |
|
|
// Add lower 32 bits to multiplication product |
if ( control_state == MULT_ACCUMU ) |
begin |
1280,7 → 1301,7
pc_wen_nxt = 1'd0; // hold current PC value |
address_sel_nxt = 4'd3; // pc (not pc + 4) |
end |
|
|
// swp - do write request in 2nd cycle |
if ( control_state == SWAP_WRITE && instruction_execute ) |
begin |
1287,44 → 1308,44
barrel_shift_data_sel_nxt = 2'd2; // Shift value from Rm register |
address_sel_nxt = 4'd4; // Rn |
write_data_wen_nxt = 1'd1; |
data_access_exec_nxt = 1'd1; // indicate that its a data read or write, |
data_access_exec_nxt = 1'd1; // indicate that its a data read or write, |
// rather than an instruction fetch |
|
|
if ( instruction[22] ) |
byte_enable_sel_nxt = 2'd1; // Save byte |
|
|
if ( instruction_execute ) // conditional execution state |
pc_wen_nxt = 1'd0; // hold current PC value |
|
|
// Save the next instruction to execute later |
// Do this even if this instruction does not execute because of Condition |
pre_fetch_instruction_wen = 1'd1; |
|
|
end |
|
|
|
// swp - receive read response in 3rd cycle |
if ( control_state == SWAP_WAIT1 ) |
if ( control_state == SWAP_WAIT1 ) |
begin |
barrel_shift_data_sel_nxt = 2'd1; // load word from memory |
barrel_shift_amount_sel_nxt = 2'd3; // shift by address[1:0] x 8 |
|
|
// shift needed |
if ( i_execute_address[1:0] != 2'd0 ) |
barrel_shift_function_nxt = ROR; |
|
|
if ( instruction_execute ) // conditional execution state |
begin |
address_sel_nxt = 4'd3; // pc (not pc + 4) |
pc_wen_nxt = 1'd0; // hold current PC value |
end |
|
// load a byte |
|
// load a byte |
if ( instruction[22] ) |
alu_out_sel_nxt = 4'd3; // zero_extend8 |
|
|
if ( !dabt ) |
begin |
begin |
// Check is the load destination is the PC |
if ( instruction[15:12] == 4'd15 ) |
begin |
1331,26 → 1352,26
pc_sel_nxt = 2'd1; // alu_out |
address_sel_nxt = 4'd1; // alu_out |
end |
else |
else |
reg_bank_wsel_nxt = instruction[15:12]; |
end |
end |
|
|
// 1 cycle delay for Co-Processor Register access |
if ( control_state == COPRO_WAIT && instruction_execute ) |
begin |
pre_fetch_instruction_wen = 1'd1; |
|
|
if ( instruction[20] ) // mrc instruction |
begin |
// Check is the load destination is the PC |
if ( instruction[15:12] == 4'd15 ) |
begin |
// If r15 is specified for <Rd>, the condition code flags are |
// If r15 is specified for <Rd>, the condition code flags are |
// updated instead of a general-purpose register. |
status_bits_sel_nxt = 3'd3; // i_copro_data |
status_bits_flags_wen_nxt = 1'd1; |
|
|
// Can't change these in USR mode |
if ( i_execute_status_bits[1:0] != USR ) |
begin |
1359,25 → 1380,25
status_bits_firq_mask_wen_nxt = 1'd1; |
end |
end |
else |
else |
reg_bank_wsel_nxt = instruction[15:12]; |
|
|
reg_write_sel_nxt = 3'd5; // i_copro_data |
end |
else // mcr instruction |
begin |
copro_operation_nxt = 2'd2; // Register transfer to Co-Processor |
end |
copro_operation_nxt = 2'd2; // Register transfer to Co-Processor |
end |
end |
|
|
|
// Have just changed the status_bits mode but this |
// creates a 1 cycle gap with the old mode |
// coming back from execute into instruction_decode |
// So squash that old mode value during this |
// cycle of the interrupt transition |
if ( control_state == INT_WAIT1 ) |
status_bits_mode_nxt = o_status_bits_mode; // Supervisor mode |
// cycle of the interrupt transition |
if ( control_state == INT_WAIT1 ) |
status_bits_mode_nxt = status_bits_mode_r; // Supervisor mode |
|
end |
|
1392,12 → 1413,12
// ======================================================== |
|
// this replicates the current value of the execute signal in the execute stage |
assign instruction_execute = conditional_execute ( o_condition, i_execute_status_bits[31:28] ); |
assign instruction_execute = conditional_execute ( condition_r, i_execute_status_bits[31:28] ); |
|
assign instruction_valid = (control_state == EXECUTE || control_state == PRE_FETCH_EXEC) || |
// when last instruction was multi-cycle instruction but did not execute |
// because condition was false then act like you're in the execute state |
(!instruction_execute && (control_state == PC_STALL1 || |
(!instruction_execute && (control_state == PC_STALL1 || |
control_state == MEM_WAIT1 || |
control_state == COPRO_WAIT || |
control_state == SWAP_WRITE || |
1411,7 → 1432,7
begin |
// default is to hold the current state |
control_state_nxt = control_state; |
|
|
// Note: The order is important here |
if ( control_state == RST_WAIT1 ) control_state_nxt = RST_WAIT2; |
if ( control_state == RST_WAIT2 ) control_state_nxt = EXECUTE; |
1419,39 → 1440,39
if ( control_state == INT_WAIT2 ) control_state_nxt = EXECUTE; |
if ( control_state == COPRO_WAIT ) control_state_nxt = PRE_FETCH_EXEC; |
if ( control_state == PC_STALL1 ) control_state_nxt = PC_STALL2; |
if ( control_state == PC_STALL2 ) control_state_nxt = EXECUTE; |
if ( control_state == SWAP_WRITE ) control_state_nxt = SWAP_WAIT1; |
if ( control_state == SWAP_WAIT1 ) control_state_nxt = SWAP_WAIT2; |
if ( control_state == MULT_STORE ) control_state_nxt = PRE_FETCH_EXEC; |
if ( control_state == PC_STALL2 ) control_state_nxt = EXECUTE; |
if ( control_state == SWAP_WRITE ) control_state_nxt = SWAP_WAIT1; |
if ( control_state == SWAP_WAIT1 ) control_state_nxt = SWAP_WAIT2; |
if ( control_state == MULT_STORE ) control_state_nxt = PRE_FETCH_EXEC; |
if ( control_state == MTRANS5_ABORT ) control_state_nxt = PRE_FETCH_EXEC; |
|
if ( control_state == MEM_WAIT1 ) |
control_state_nxt = MEM_WAIT2; |
|
if ( control_state == MEM_WAIT2 || |
if ( control_state == MEM_WAIT2 || |
control_state == SWAP_WAIT2 ) |
begin |
if ( write_pc ) // writing to the PC!! |
if ( write_pc ) // writing to the PC!! |
control_state_nxt = PC_STALL1; |
else |
control_state_nxt = PRE_FETCH_EXEC; |
end |
|
if ( control_state == MTRANS_EXEC1 ) |
begin |
|
if ( control_state == MTRANS_EXEC1 ) |
begin |
if (mtrans_instruction_nxt[15:0] != 16'd0) |
control_state_nxt = MTRANS_EXEC2; |
else // if the register list holds a single register |
else // if the register list holds a single register |
control_state_nxt = MTRANS_EXEC3; |
end |
|
|
// Stay in State MTRANS_EXEC2 until the full list of registers to |
// load or store has been processed |
if ( control_state == MTRANS_EXEC2 && mtrans_num_registers == 5'd1 ) |
control_state_nxt = MTRANS_EXEC3; |
|
if ( control_state == MTRANS_EXEC3 ) control_state_nxt = MTRANS_EXEC4; |
|
|
if ( control_state == MTRANS_EXEC3 ) control_state_nxt = MTRANS_EXEC4; |
|
if ( control_state == MTRANS_EXEC3B ) control_state_nxt = MTRANS_EXEC4; |
|
if ( control_state == MTRANS_EXEC4 ) |
1458,12 → 1479,12
begin |
if ( dabt ) // data abort |
control_state_nxt = MTRANS5_ABORT; |
else if (write_pc) // writing to the PC!! |
else if (write_pc) // writing to the PC!! |
control_state_nxt = PC_STALL1; |
else |
control_state_nxt = PRE_FETCH_EXEC; |
end |
|
|
if ( control_state == MULT_PROC1 ) |
begin |
if (!instruction_execute) |
1471,23 → 1492,23
else |
control_state_nxt = MULT_PROC2; |
end |
|
|
if ( control_state == MULT_PROC2 ) |
begin |
if ( i_multiply_done ) |
if ( o_multiply_function[1] ) // Accumulate ? |
control_state_nxt = MULT_ACCUMU; |
else |
else |
control_state_nxt = MULT_STORE; |
end |
|
|
|
|
if ( control_state == MULT_ACCUMU ) |
begin |
control_state_nxt = MULT_STORE; |
end |
|
|
|
|
// This should come at the end, so that conditional execution works |
// correctly |
if ( instruction_valid ) |
1495,10 → 1516,10
// default is to stay in execute state, or to move into this |
// state from a conditional execute state |
control_state_nxt = EXECUTE; |
|
|
if ( mem_op ) // load or store word or byte |
control_state_nxt = MEM_WAIT1; |
if ( write_pc ) |
if ( write_pc ) |
control_state_nxt = PC_STALL1; |
if ( itype == MTRANS ) |
begin |
1510,7 → 1531,7
else |
control_state_nxt = MTRANS_EXEC1; |
end |
else |
else |
control_state_nxt = MTRANS_EXEC3; |
end |
|
1517,14 → 1538,14
if ( itype == MULT ) |
control_state_nxt = MULT_PROC1; |
|
if ( itype == SWAP ) |
if ( itype == SWAP ) |
control_state_nxt = SWAP_WRITE; |
|
if ( itype == CORTRANS && !und_request ) |
if ( itype == CORTRANS && !und_request ) |
control_state_nxt = COPRO_WAIT; |
|
// interrupt overrides everything else so its last |
if ( interrupt ) |
|
// interrupt overrides everything else so its last |
if ( interrupt ) |
control_state_nxt = INT_WAIT1; |
end |
end |
1534,30 → 1555,30
// Register Update |
// ======================================================== |
always @ ( posedge i_clk ) |
if (!i_fetch_stall) |
begin |
if (!i_fetch_stall) |
begin |
o_read_data <= i_read_data; |
o_read_data_alignment <= {i_execute_address[1:0], 3'd0}; |
o_read_data_alignment <= {i_execute_address[1:0], 3'd0}; |
abt_address_reg <= i_execute_address; |
iabt_reg <= i_iabt; |
adex_reg <= i_adex; |
abt_status_reg <= i_abt_status; |
o_status_bits_mode <= status_bits_mode_nxt; |
o_status_bits_irq_mask <= status_bits_irq_mask_nxt; |
o_status_bits_firq_mask <= status_bits_firq_mask_nxt; |
status_bits_mode_r <= status_bits_mode_nxt; |
status_bits_irq_mask_r <= status_bits_irq_mask_nxt; |
status_bits_firq_mask_r <= status_bits_firq_mask_nxt; |
o_imm32 <= imm32_nxt; |
o_imm_shift_amount <= imm_shift_amount_nxt; |
o_shift_imm_zero <= shift_imm_zero_nxt; |
|
|
// when have an interrupt, execute the interrupt operation |
// unconditionally in the execute stage |
// ensures that status_bits register gets updated correctly |
// Likewise when in middle of multi-cycle instructions |
// execute them unconditionally |
o_condition <= instruction_valid && !interrupt ? condition_nxt : AL; |
condition_r <= instruction_valid && !interrupt ? condition_nxt : AL; |
o_exclusive_exec <= exclusive_exec_nxt; |
o_data_access_exec <= data_access_exec_nxt; |
|
|
o_rm_sel <= o_rm_sel_nxt; |
o_rds_sel <= o_rds_sel_nxt; |
o_rn_sel <= o_rn_sel_nxt; |
1568,8 → 1589,8
o_use_carry_in <= use_carry_in_nxt; |
o_multiply_function <= multiply_function_nxt; |
o_interrupt_vector_sel <= next_interrupt; |
o_address_sel <= address_sel_nxt; |
o_pc_sel <= pc_sel_nxt; |
address_sel_r <= address_sel_nxt; |
pc_sel_r <= pc_sel_nxt; |
o_byte_enable_sel <= byte_enable_sel_nxt; |
o_status_bits_sel <= status_bits_sel_nxt; |
o_reg_write_sel <= reg_write_sel_nxt; |
1577,7 → 1598,7
o_firq_not_user_mode <= firq_not_user_mode_nxt; |
o_write_data_wen <= write_data_wen_nxt; |
o_base_address_wen <= base_address_wen_nxt; |
o_pc_wen <= pc_wen_nxt; |
pc_wen_r <= pc_wen_nxt; |
o_reg_bank_wsel <= reg_bank_wsel_nxt; |
o_reg_bank_wen <= decode ( reg_bank_wsel_nxt ); |
o_status_bits_flags_wen <= status_bits_flags_wen_nxt; |
1584,7 → 1605,7
o_status_bits_mode_wen <= status_bits_mode_wen_nxt; |
o_status_bits_irq_mask_wen <= status_bits_irq_mask_wen_nxt; |
o_status_bits_firq_mask_wen <= status_bits_firq_mask_wen_nxt; |
|
|
o_copro_opcode1 <= instruction[23:21]; |
o_copro_opcode2 <= instruction[7:5]; |
o_copro_crn <= instruction[19:16]; |
1610,7 → 1631,7
// then when its decoded, a copy is saved to the saved_current_instruction |
// register |
if (itype == MTRANS) |
begin |
begin |
saved_current_instruction <= mtrans_instruction_nxt; |
saved_current_instruction_iabt <= instruction_iabt; |
saved_current_instruction_adex <= instruction_adex; |
1617,8 → 1638,8
saved_current_instruction_address <= instruction_address; |
saved_current_instruction_iabt_status <= instruction_iabt_status; |
end |
else if (saved_current_instruction_wen) |
begin |
else if (saved_current_instruction_wen) |
begin |
saved_current_instruction <= instruction; |
saved_current_instruction_iabt <= instruction_iabt; |
saved_current_instruction_adex <= instruction_adex; |
1626,36 → 1647,36
saved_current_instruction_iabt_status <= instruction_iabt_status; |
end |
|
if (pre_fetch_instruction_wen) |
if (pre_fetch_instruction_wen) |
begin |
pre_fetch_instruction <= o_read_data; |
pre_fetch_instruction_iabt <= iabt_reg; |
pre_fetch_instruction_adex <= adex_reg; |
pre_fetch_instruction_address <= abt_address_reg; |
pre_fetch_instruction_iabt_status <= abt_status_reg; |
end |
pre_fetch_instruction <= o_read_data; |
pre_fetch_instruction_iabt <= iabt_reg; |
pre_fetch_instruction_adex <= adex_reg; |
pre_fetch_instruction_address <= abt_address_reg; |
pre_fetch_instruction_iabt_status <= abt_status_reg; |
end |
end |
|
|
|
|
always @ ( posedge i_clk ) |
if ( !i_fetch_stall ) |
begin |
irq <= i_irq; |
firq <= i_firq; |
|
if ( control_state == INT_WAIT1 && o_status_bits_mode == SVC ) |
irq <= i_irq; |
firq <= i_firq; |
|
if ( control_state == INT_WAIT1 && status_bits_mode_r == SVC ) |
begin |
dabt_reg <= 1'd0; |
end |
else |
begin |
dabt_reg <= dabt_reg || i_dabt; |
dabt_reg <= dabt_reg || i_dabt; |
end |
|
dabt_reg_d1 <= dabt_reg; |
end |
|
dabt_reg_d1 <= dabt_reg; |
end |
|
assign dabt = dabt_reg || i_dabt; |
|
|
1676,15 → 1697,15
.i_interrupt ( {3{interrupt}} & next_interrupt ), |
.i_interrupt_state ( control_state == INT_WAIT2 ), |
.i_instruction_undefined ( und_request ), |
.i_pc_sel ( o_pc_sel ), |
.i_pc_wen ( o_pc_wen ) |
); |
.i_pc_sel ( pc_sel_r ), |
.i_pc_wen ( pc_wen_r )); |
|
|
|
wire [(15*8)-1:0] xCONTROL_STATE; |
wire [(15*8)-1:0] xMODE; |
|
assign xCONTROL_STATE = |
assign xCONTROL_STATE = |
control_state == RST_WAIT1 ? "RST_WAIT1" : |
control_state == RST_WAIT2 ? "RST_WAIT2" : |
|
1713,7 → 1734,7
control_state == COPRO_WAIT ? "COPRO_WAIT" : |
"UNKNOWN " ; |
|
assign xMODE = mode_name ( o_status_bits_mode ); |
assign xMODE = mode_name ( status_bits_mode_r ); |
|
always @( posedge i_clk ) |
if (control_state == EXECUTE && ((instruction[0] === 1'bx) || (instruction[31] === 1'bx))) |
/amber23/a23_execute.v
57,7 → 57,7
|
output reg [31:0] o_copro_write_data = 'd0, |
output reg [31:0] o_write_data = 'd0, |
output reg [31:0] o_address = 32'hdead_dead, |
output wire [31:0] o_address, |
output reg o_adex = 'd0, // Address Exception |
output reg o_address_valid = 'd0, // Prevents the reset address value being a |
// wishbone access |
200,7 → 200,9
|
wire carry_in; |
|
reg [31:0] address_r = 32'hdead_dead; |
|
|
// ======================================================== |
// Status Bits in PC register |
// ======================================================== |
264,10 → 266,11
// ======================================================== |
assign pc_plus4 = pc + 32'd4; |
assign pc_minus4 = pc - 32'd4; |
assign address_plus4 = o_address + 32'd4; |
assign address_plus4 = address_r + 32'd4; |
assign alu_plus4 = alu_out + 32'd4; |
assign rn_plus4 = rn + 32'd4; |
|
|
// ======================================================== |
// Barrel Shift Amount Select |
// ======================================================== |
456,7 → 459,7
o_data_access <= data_access_update ? i_data_access_exec : o_data_access; |
o_write_enable <= write_enable_update ? write_enable_nxt : o_write_enable; |
o_write_data <= write_data_update ? write_data_nxt : o_write_data; |
o_address <= address_update ? o_address_nxt : o_address; |
address_r <= address_update ? o_address_nxt : address_r; |
o_adex <= address_update ? adex_nxt : o_adex; |
o_address_valid <= address_update ? 1'd1 : o_address_valid; |
o_byte_enable <= byte_enable_update ? byte_enable_nxt : o_byte_enable; |
472,7 → 475,9
status_bits_firq_mask <= status_bits_firq_mask_update ? status_bits_firq_mask_nxt : status_bits_firq_mask; |
end |
|
assign o_address = address_r; |
|
|
// ======================================================== |
// Instantiate Barrel Shift |
// ======================================================== |
/amber25/a25_decode.v
64,13 → 64,13
output reg [31:0] o_imm32 = 'd0, |
output reg [4:0] o_imm_shift_amount = 'd0, |
output reg o_shift_imm_zero = 'd0, |
output reg [3:0] o_condition = 4'he, // 4'he = al |
output wire [3:0] o_condition, |
output reg o_decode_exclusive = 'd0, // exclusive access request ( swap instruction ) |
output reg o_decode_iaccess = 1'd1, // Indicates an instruction access |
output wire o_decode_iaccess, // Indicates an instruction access |
output reg o_decode_daccess = 'd0, // Indicates a data access |
output reg [1:0] o_status_bits_mode = 2'b11, // SVC |
output reg o_status_bits_irq_mask = 1'd1, |
output reg o_status_bits_firq_mask = 1'd1, |
output wire [1:0] o_status_bits_mode, |
output wire o_status_bits_irq_mask, |
output wire o_status_bits_firq_mask, |
|
output reg [3:0] o_rm_sel = 'd0, |
output reg [3:0] o_rs_sel = 'd0, |
86,9 → 86,9
output reg [8:0] o_alu_function = 'd0, |
output reg [1:0] o_multiply_function = 'd0, |
output reg [2:0] o_interrupt_vector_sel = 'd0, |
output reg [3:0] o_iaddress_sel = 4'd2, |
output reg [3:0] o_daddress_sel = 4'd2, |
output reg [2:0] o_pc_sel = 3'd2, |
output wire [3:0] o_iaddress_sel, |
output wire [3:0] o_daddress_sel, |
output wire [2:0] o_pc_sel, |
output reg [1:0] o_byte_enable_sel = 'd0, // byte, halfword or word write |
output reg [2:0] o_status_bits_sel = 'd0, |
output reg [2:0] o_reg_write_sel, |
99,7 → 99,7
output reg o_write_data_wen = 'd0, |
output reg o_base_address_wen = 'd0, // save ldm base address register |
// in case of data abort |
output reg o_pc_wen = 1'd1, |
output wire o_pc_wen, |
output reg [14:0] o_reg_bank_wen = 'd0, |
output reg o_status_bits_flags_wen = 'd0, |
output reg o_status_bits_mode_wen = 'd0, |
111,10 → 111,10
// -------------------------------------------------- |
output reg [2:0] o_copro_opcode1 = 'd0, |
output reg [2:0] o_copro_opcode2 = 'd0, |
output reg [3:0] o_copro_crn = 'd0, |
output reg [3:0] o_copro_crn = 'd0, |
output reg [3:0] o_copro_crm = 'd0, |
output reg [3:0] o_copro_num = 'd0, |
output reg [1:0] o_copro_operation = 'd0, // 0 = no operation, |
output reg [1:0] o_copro_operation = 'd0, // 0 = no operation, |
// 1 = Move to Amber Core Register from Coprocessor |
// 2 = Move to Coprocessor from Amber Core Register |
output reg o_copro_write_data_wen = 'd0, |
159,8 → 159,8
SWAP_WAIT1 = 5'd18, |
SWAP_WAIT2 = 5'd19, |
COPRO_WAIT = 5'd20; |
|
|
|
|
// ======================================================== |
// Internal signals |
// ======================================================== |
168,7 → 168,7
wire [3:0] type; // regop, mem access etc. |
wire instruction_iabt; // abort flag, follows the instruction |
wire instruction_adex; // address exception flag, follows the instruction |
wire [31:0] instruction_address; // instruction virtual address, follows |
wire [31:0] instruction_address; // instruction virtual address, follows |
// the instruction |
wire [7:0] instruction_iabt_status; // abort status, follows the instruction |
wire [1:0] instruction_sel; |
310,8 → 310,8
wire [7:0] load_rd_nxt; |
wire load_rd_byte; |
wire ldm_user_mode; |
wire ldm_status_bits; |
wire ldm_flags; |
wire ldm_status_bits; |
wire ldm_flags; |
wire [6:0] load_rd_d1_nxt; |
reg [6:0] load_rd_d1 = 'd0; // MSB is the valid bit |
|
341,12 → 341,37
reg rs_conflict1_r = 'd0; |
reg rd_conflict1_r = 'd0; |
|
// ======================================================== |
// registers for output ports with non-zero initial values |
// ======================================================== |
reg [3:0] condition_r = 4'he; // 4'he = al |
reg decode_iaccess_r = 1'd1; // Indicates an instruction access |
reg [1:0] status_bits_mode_r = 2'b11; // SVC |
reg status_bits_irq_mask_r = 1'd1; |
reg status_bits_firq_mask_r = 1'd1; |
reg [3:0] iaddress_sel_r = 4'd2; |
reg [3:0] daddress_sel_r = 4'd2; |
reg [2:0] pc_sel_r = 3'd2; |
reg pc_wen_r = 1'd1; |
|
|
assign o_condition = condition_r; |
assign o_decode_iaccess = decode_iaccess_r; |
assign o_status_bits_mode = status_bits_mode_r; |
assign o_status_bits_irq_mask = status_bits_irq_mask_r; |
assign o_status_bits_firq_mask = status_bits_firq_mask_r; |
assign o_iaddress_sel = iaddress_sel_r; |
assign o_daddress_sel = daddress_sel_r; |
assign o_pc_sel = pc_sel_r; |
assign o_pc_wen = pc_wen_r; |
|
|
|
// ======================================================== |
// Instruction Abort and Data Abort outputs |
// ======================================================== |
|
assign o_iabt_trigger = instruction_iabt && o_status_bits_mode == SVC && control_state == INT_WAIT1; |
assign o_iabt_trigger = instruction_iabt && status_bits_mode_r == SVC && control_state == INT_WAIT1; |
assign o_iabt_address = instruction_address; |
assign o_iabt_status = instruction_iabt_status; |
|
370,7 → 395,7
( control_state == MEM_WAIT1 || |
control_state == MEM_WAIT2 || |
control_state == MTRANS_EXEC1 || |
control_state == MTRANS_EXEC2 || |
control_state == MTRANS_EXEC2 || |
control_state == MTRANS_ABORT || |
control_state == MULT_PROC1 || |
control_state == MULT_PROC2 || |
389,19 → 414,19
|
|
assign instruction_sel = use_hold_instruction ? 2'd3 : // hold_instruction |
use_saved_current_instruction ? 2'd1 : // saved_current_instruction |
use_pre_fetch_instruction ? 2'd2 : // pre_fetch_instruction |
2'd0 ; // fetch_instruction_r |
use_saved_current_instruction ? 2'd1 : // saved_current_instruction |
use_pre_fetch_instruction ? 2'd2 : // pre_fetch_instruction |
2'd0 ; // fetch_instruction_r |
|
assign instruction = instruction_sel == 2'd0 ? fetch_instruction_r : |
instruction_sel == 2'd1 ? saved_current_instruction : |
instruction_sel == 2'd3 ? hold_instruction : |
pre_fetch_instruction ; |
|
|
assign type = instruction_sel == 2'd0 ? fetch_instruction_type_r : |
instruction_sel == 2'd1 ? saved_current_instruction_type : |
instruction_sel == 2'd3 ? hold_instruction_type : |
pre_fetch_instruction_type ; |
pre_fetch_instruction_type ; |
|
// abort flag |
assign instruction_iabt = instruction_sel == 2'd0 ? iabt_reg : |
408,7 → 433,7
instruction_sel == 2'd1 ? saved_current_instruction_iabt : |
instruction_sel == 2'd3 ? hold_instruction_iabt : |
pre_fetch_instruction_iabt ; |
|
|
assign instruction_address = instruction_sel == 2'd0 ? fetch_address_r : |
instruction_sel == 2'd1 ? saved_current_instruction_address : |
instruction_sel == 2'd3 ? hold_instruction_address : |
425,11 → 450,11
instruction_sel == 2'd3 ? hold_instruction_adex : |
pre_fetch_instruction_adex ; |
|
|
|
// ======================================================== |
// Fixed fields within the instruction |
// ======================================================== |
|
|
assign opcode = instruction[24:21]; |
assign condition_nxt = instruction[31:28]; |
|
438,7 → 463,7
assign rs_sel_nxt = control_state == SWAP_WRITE ? instruction[3:0] : // Rm gets written out to memory |
type == MTRANS ? mtrans_reg1 : |
branch ? 4'd15 : // Update the PC |
rds_use_rs ? instruction[11:8] : |
rds_use_rs ? instruction[11:8] : |
instruction[15:12] ; |
|
// Load from memory into registers |
460,8 → 485,8
|
assign immediate_shift_op = instruction[25]; |
assign rds_use_rs = (type == REGOP && !instruction[25] && instruction[4]) || |
(type == MULT && |
(control_state == MULT_PROC1 || |
(type == MULT && |
(control_state == MULT_PROC1 || |
control_state == MULT_PROC2 || |
// instruction_valid && !interrupt )) ; |
// remove the '!conflict' term from the interrupt logic used here |
476,7 → 501,7
assign store_op = mem_op && !instruction[20]; |
assign write_pc = (pc_wen_nxt && pc_sel_nxt != 3'd0) || load_pc_r || load_pc_nxt; |
assign current_write_pc = (pc_wen_nxt && pc_sel_nxt != 3'd0) || load_pc_nxt; |
assign regop_set_flags = type == REGOP && instruction[20]; |
assign regop_set_flags = type == REGOP && instruction[20]; |
|
assign mem_op_pre_indexed = instruction[24] && instruction[21]; |
assign mem_op_post_indexed = !instruction[24]; |
483,7 → 508,7
|
assign imm32_nxt = // add 0 to Rm |
type == MULT ? { 32'd0 } : |
|
|
// 4 x number of registers |
type == MTRANS ? { mtrans_base_reg_change } : |
type == BRANCH ? { offset24 } : |
508,17 → 533,17
|
assign imm_shift_amount_nxt = shift_imm ; |
|
// This signal is encoded in the decode stage because |
// This signal is encoded in the decode stage because |
// it is on the critical path in the execute stage |
assign shift_imm_zero_nxt = imm_shift_amount_nxt == 5'd0 && // immediate amount = 0 |
barrel_shift_amount_sel_nxt == 2'd2; // shift immediate amount |
|
assign alu_function_nxt = { alu_swap_sel_nxt, |
alu_not_sel_nxt, |
assign alu_function_nxt = { alu_swap_sel_nxt, |
alu_not_sel_nxt, |
alu_cin_sel_nxt, |
alu_cout_sel_nxt, |
alu_cout_sel_nxt, |
alu_out_sel_nxt }; |
|
|
// ======================================================== |
// Register Conflict Detection |
// ======================================================== |
538,13 → 563,13
assign rd_conflict1 = instruction_execute && rd_valid && ( load_rd_d1_nxt[4] && instruction[15:12] == load_rd_d1_nxt[3:0] ); |
assign rd_conflict2 = instruction_execute_r && rd_valid && ( load_rd_d1 [4] && instruction[15:12] == load_rd_d1 [3:0] ); |
|
assign stm_conflict1a = instruction_execute && stm_valid && ( load_rd_d1_nxt[4] && mtrans_reg1 == load_rd_d1_nxt[3:0] ); |
assign stm_conflict1b = instruction_execute && stm_valid && ( load_rd_d1_nxt[4] && mtrans_reg2 == load_rd_d1_nxt[3:0] ); |
assign stm_conflict1a = instruction_execute && stm_valid && ( load_rd_d1_nxt[4] && mtrans_reg1 == load_rd_d1_nxt[3:0] ); |
assign stm_conflict1b = instruction_execute && stm_valid && ( load_rd_d1_nxt[4] && mtrans_reg2 == load_rd_d1_nxt[3:0] ); |
assign stm_conflict2a = instruction_execute_r && stm_valid && ( load_rd_d1 [4] && mtrans_reg1 == load_rd_d1 [3:0] ); |
assign stm_conflict2b = instruction_execute_r && stm_valid && ( load_rd_d1 [4] && mtrans_reg2 == load_rd_d1 [3:0] ); |
|
|
assign conflict1 = instruction_valid && |
(rn_conflict1 || rm_conflict1 || rs_conflict1 || rd_conflict1 || |
(rn_conflict1 || rm_conflict1 || rs_conflict1 || rd_conflict1 || |
stm_conflict1a || stm_conflict1b); |
|
assign conflict2 = instruction_valid && (stm_conflict2a || stm_conflict2b); |
573,10 → 598,10
// ======================================================== |
// MTRANS Operations |
// ======================================================== |
|
|
// Bit 15 = r15 |
// Bit 0 = r0 |
// In ldm and stm instructions r0 is loaded or stored first |
// In ldm and stm instructions r0 is loaded or stored first |
always @* |
casez ( instruction[15:0] ) |
16'b???????????????1 : mtrans_reg1 = 4'h0 ; |
623,28 → 648,28
always @* |
casez (instruction[15:0]) |
16'b???????????????1 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 1], 1'd0}; |
16'b??????????????10 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 2], 2'd0}; |
16'b?????????????100 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 3], 3'd0}; |
16'b????????????1000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 4], 4'd0}; |
16'b???????????10000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 5], 5'd0}; |
16'b??????????100000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 6], 6'd0}; |
16'b?????????1000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 7], 7'd0}; |
16'b????????10000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 8], 8'd0}; |
16'b???????100000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 9], 9'd0}; |
16'b??????1000000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15:10], 10'd0}; |
16'b?????10000000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15:11], 11'd0}; |
16'b????100000000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15:12], 12'd0}; |
16'b???1000000000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15:13], 13'd0}; |
16'b??10000000000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15:14], 14'd0}; |
16'b?100000000000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15 ], 15'd0}; |
default : mtrans_instruction_nxt = {instruction[31:16], 16'd0}; |
16'b??????????????10 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 2], 2'd0}; |
16'b?????????????100 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 3], 3'd0}; |
16'b????????????1000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 4], 4'd0}; |
16'b???????????10000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 5], 5'd0}; |
16'b??????????100000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 6], 6'd0}; |
16'b?????????1000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 7], 7'd0}; |
16'b????????10000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 8], 8'd0}; |
16'b???????100000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 9], 9'd0}; |
16'b??????1000000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15:10], 10'd0}; |
16'b?????10000000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15:11], 11'd0}; |
16'b????100000000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15:12], 12'd0}; |
16'b???1000000000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15:13], 13'd0}; |
16'b??10000000000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15:14], 14'd0}; |
16'b?100000000000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15 ], 15'd0}; |
default : mtrans_instruction_nxt = {instruction[31:16], 16'd0}; |
endcase |
|
|
// number of registers to be stored |
assign mtrans_num_registers = {4'd0, instruction[15]} + |
{4'd0, instruction[14]} + |
{4'd0, instruction[13]} + |
assign mtrans_num_registers = {4'd0, instruction[15]} + |
{4'd0, instruction[14]} + |
{4'd0, instruction[13]} + |
{4'd0, instruction[12]} + |
{4'd0, instruction[11]} + |
{4'd0, instruction[10]} + |
658,7 → 683,7
{4'd0, instruction[ 2]} + |
{4'd0, instruction[ 1]} + |
{4'd0, instruction[ 0]} ; |
|
|
// 4 x number of registers to be stored |
assign mtrans_base_reg_change = {25'd0, mtrans_num_registers, 2'd0}; |
|
672,15 → 697,15
assign dabt_request = dabt_reg; |
|
// copro15 and copro13 only supports reg trans opcodes |
// all other opcodes involving co-processors cause an |
// all other opcodes involving co-processors cause an |
// undefined instrution interrupt |
assign und_request = type == CODTRANS || |
type == COREGOP || |
assign und_request = type == CODTRANS || |
type == COREGOP || |
( type == CORTRANS && instruction[11:8] != 4'd15 ); |
|
|
// in order of priority !! |
// Highest |
// in order of priority !! |
// Highest |
// 1 Reset |
// 2 Data Abort (including data TLB miss) |
// 3 FIRQ |
687,22 → 712,22
// 4 IRQ |
// 5 Prefetch Abort (including prefetch TLB miss) |
// 6 Undefined instruction, SWI |
// Lowest |
// Lowest |
assign next_interrupt = dabt_request ? 3'd1 : // Data Abort |
firq_request ? 3'd2 : // FIRQ |
irq_request ? 3'd3 : // IRQ |
instruction_adex ? 3'd4 : // Address Exception |
instruction_iabt ? 3'd5 : // PreFetch Abort, only triggered |
instruction_adex ? 3'd4 : // Address Exception |
instruction_iabt ? 3'd5 : // PreFetch Abort, only triggered |
// if the instruction is used |
und_request ? 3'd6 : // Undefined Instruction |
swi_request ? 3'd7 : // SWI |
3'd0 ; // none |
3'd0 ; // none |
|
|
// SWI and undefined instructions do not cause an interrupt in the decode |
// stage. They only trigger interrupts if they arfe executed, so the |
// interrupt is triggered if the execute condition is met in the execute stage |
assign interrupt = next_interrupt != 3'd0 && |
assign interrupt = next_interrupt != 3'd0 && |
next_interrupt != 3'd7 && // SWI |
next_interrupt != 3'd6 && // undefined interrupt |
!conflict ; // Wait for conflicts to resolve before |
711,8 → 736,8
|
// Added to use in rds_use_rs logic to break a combinational loop invloving |
// the conflict signal |
assign interrupt_or_conflict |
= next_interrupt != 3'd0 && |
assign interrupt_or_conflict |
= next_interrupt != 3'd0 && |
next_interrupt != 3'd7 && // SWI |
next_interrupt != 3'd6 ; // undefined interrupt |
|
734,40 → 759,40
// default mode |
status_bits_mode_nxt = i_execute_status_bits[1:0]; // change to mode in execute stage get reflected |
// back to this stage automatically |
status_bits_irq_mask_nxt = o_status_bits_irq_mask; |
status_bits_firq_mask_nxt = o_status_bits_firq_mask; |
status_bits_irq_mask_nxt = status_bits_irq_mask_r; |
status_bits_firq_mask_nxt = status_bits_firq_mask_r; |
decode_exclusive_nxt = 1'd0; |
decode_daccess_nxt = 1'd0; |
decode_iaccess_nxt = 1'd1; |
copro_operation_nxt = 'd0; |
|
|
// Save an instruction to use later |
saved_current_instruction_wen = 1'd0; |
pre_fetch_instruction_wen = 1'd0; |
restore_base_address_nxt = restore_base_address; |
|
|
// default Mux Select values |
barrel_shift_amount_sel_nxt = 'd0; // don't shift the input |
barrel_shift_data_sel_nxt = 'd0; // immediate value |
barrel_shift_function_nxt = 'd0; |
barrel_shift_function_nxt = 'd0; |
use_carry_in_nxt = 'd0; |
multiply_function_nxt = 'd0; |
iaddress_sel_nxt = 'd0; |
daddress_sel_nxt = 'd0; |
pc_sel_nxt = 'd0; |
load_pc_nxt = 'd0; |
byte_enable_sel_nxt = 'd0; |
status_bits_sel_nxt = 'd0; |
reg_write_sel_nxt = 'd0; |
o_user_mode_regs_store_nxt = 'd0; |
|
iaddress_sel_nxt = 'd0; |
daddress_sel_nxt = 'd0; |
pc_sel_nxt = 'd0; |
load_pc_nxt = 'd0; |
byte_enable_sel_nxt = 'd0; |
status_bits_sel_nxt = 'd0; |
reg_write_sel_nxt = 'd0; |
o_user_mode_regs_store_nxt = 'd0; |
|
// ALU Muxes |
alu_swap_sel_nxt = 'd0; |
alu_not_sel_nxt = 'd0; |
alu_cin_sel_nxt = 'd0; |
alu_cout_sel_nxt = 'd0; |
alu_out_sel_nxt = 'd0; |
|
alu_swap_sel_nxt = 'd0; |
alu_not_sel_nxt = 'd0; |
alu_cin_sel_nxt = 'd0; |
alu_cout_sel_nxt = 'd0; |
alu_out_sel_nxt = 'd0; |
|
// default Flop Write Enable values |
write_data_wen_nxt = 'd0; |
copro_write_data_wen_nxt = 'd0; |
774,7 → 799,7
base_address_wen_nxt = 'd0; |
pc_wen_nxt = 'd1; |
reg_bank_wen_nxt = 'd0; // Don't select any |
|
|
status_bits_flags_wen_nxt = 'd0; |
status_bits_mode_wen_nxt = 'd0; |
status_bits_irq_mask_wen_nxt = 'd0; |
792,35 → 817,35
pc_sel_nxt = 3'd1; // alu_out |
iaddress_sel_nxt = 4'd1; // alu_out |
end |
else |
else |
reg_bank_wen_nxt = decode (instruction[15:12]); |
end |
|
|
if ( !immediate_shift_op ) |
begin |
barrel_shift_function_nxt = instruction[6:5]; |
end |
|
|
if ( !immediate_shift_op ) |
barrel_shift_data_sel_nxt = 2'd2; // Shift value from Rm register |
|
|
if ( !immediate_shift_op && instruction[4] ) |
barrel_shift_amount_sel_nxt = 2'd1; // Shift amount from Rs registter |
|
if ( !immediate_shift_op && !instruction[4] ) |
barrel_shift_amount_sel_nxt = 2'd2; // Shift immediate amount |
|
if ( !immediate_shift_op && !instruction[4] ) |
barrel_shift_amount_sel_nxt = 2'd2; // Shift immediate amount |
|
// regops that do not change the overflow flag |
if ( opcode == AND || opcode == EOR || opcode == TST || opcode == TEQ || |
if ( opcode == AND || opcode == EOR || opcode == TST || opcode == TEQ || |
opcode == ORR || opcode == MOV || opcode == BIC || opcode == MVN ) |
status_bits_sel_nxt = 3'd5; |
|
|
if ( opcode == ADD || opcode == CMN ) // CMN is just like an ADD |
begin |
alu_out_sel_nxt = 4'd1; // Add |
use_carry_in_nxt = shift_extend; |
end |
|
|
if ( opcode == ADC ) // Add with Carry |
begin |
alu_out_sel_nxt = 4'd1; // Add |
827,7 → 852,7
alu_cin_sel_nxt = 2'd2; // carry in from status_bits |
use_carry_in_nxt = shift_extend; |
end |
|
|
if ( opcode == SUB || opcode == CMP ) // Subtract |
begin |
alu_out_sel_nxt = 4'd1; // Add |
834,8 → 859,8
alu_cin_sel_nxt = 2'd1; // cin = 1 |
alu_not_sel_nxt = 1'd1; // invert B |
end |
|
// SBC (Subtract with Carry) subtracts the value of its |
|
// SBC (Subtract with Carry) subtracts the value of its |
// second operand and the value of NOT(Carry flag) from |
// the value of its first operand. |
// Rd = Rn - shifter_operand - NOT(C Flag) |
846,7 → 871,7
alu_not_sel_nxt = 1'd1; // invert B |
use_carry_in_nxt = 1'd1; |
end |
|
|
if ( opcode == RSB ) // Reverse Subtract |
begin |
alu_out_sel_nxt = 4'd1; // Add |
855,7 → 880,7
alu_swap_sel_nxt = 1'd1; // swap A and B |
use_carry_in_nxt = 1'd1; |
end |
|
|
if ( opcode == RSC ) // Reverse Subtract with carry |
begin |
alu_out_sel_nxt = 4'd1; // Add |
864,13 → 889,13
alu_swap_sel_nxt = 1'd1; // swap A and B |
use_carry_in_nxt = 1'd1; |
end |
|
|
if ( opcode == AND || opcode == TST ) // Logical AND, Test (using AND operator) |
begin |
alu_out_sel_nxt = 4'd8; // AND |
alu_cout_sel_nxt = 1'd1; // i_barrel_shift_carry |
end |
|
|
if ( opcode == EOR || opcode == TEQ ) // Logical Exclusive OR, Test Equivalence (using EOR operator) |
begin |
alu_out_sel_nxt = 4'd6; // XOR |
884,7 → 909,7
alu_cout_sel_nxt = 1'd1; // i_barrel_shift_carry |
use_carry_in_nxt = 1'd1; |
end |
|
|
if ( opcode == BIC ) // Bit Clear (using AND & NOT operators) |
begin |
alu_out_sel_nxt = 4'd8; // AND |
892,13 → 917,13
alu_cout_sel_nxt = 1'd1; // i_barrel_shift_carry |
use_carry_in_nxt = 1'd1; |
end |
|
|
if ( opcode == MOV ) // Move |
begin |
alu_cout_sel_nxt = 1'd1; // i_barrel_shift_carry |
use_carry_in_nxt = 1'd1; |
end |
|
|
if ( opcode == MVN ) // Move NOT |
begin |
alu_not_sel_nxt = 1'd1; // invert B |
906,7 → 931,7
use_carry_in_nxt = 1'd1; |
end |
end |
|
|
// Load & Store instructions |
if ( mem_op ) |
begin |
919,13 → 944,13
|
decode_daccess_nxt = 1'd1; // indicate a valid data access |
alu_out_sel_nxt = 4'd1; // Add |
|
|
if ( !instruction[23] ) // U: Subtract offset |
begin |
alu_cin_sel_nxt = 2'd1; // cin = 1 |
alu_not_sel_nxt = 1'd1; // invert B |
end |
|
|
if ( store_op ) |
begin |
write_data_wen_nxt = 1'd1; |
932,7 → 957,7
if ( type == TRANS && instruction[22] ) |
byte_enable_sel_nxt = 2'd1; // Save byte |
end |
|
|
// need to update the register holding the address ? |
// This is Rn bits [19:16] |
if ( mem_op_pre_indexed || mem_op_post_indexed ) |
939,34 → 964,34
begin |
// Check is the load destination is the PC |
if ( rn_sel_nxt == 4'd15 ) |
pc_sel_nxt = 3'd1; |
else |
pc_sel_nxt = 3'd1; |
else |
reg_bank_wen_nxt = decode ( rn_sel_nxt ); |
end |
|
|
// if post-indexed, then use Rn rather than ALU output, as address |
if ( mem_op_post_indexed ) |
daddress_sel_nxt = 4'd4; // Rn |
else |
else |
daddress_sel_nxt = 4'd1; // alu out |
|
|
if ( instruction[25] && type == TRANS ) |
barrel_shift_data_sel_nxt = 2'd2; // Shift value from Rm register |
|
if ( type == TRANS && instruction[25] && shift_imm != 5'd0 ) |
begin |
|
if ( type == TRANS && instruction[25] && shift_imm != 5'd0 ) |
begin |
barrel_shift_function_nxt = instruction[6:5]; |
barrel_shift_amount_sel_nxt = 2'd2; // imm_shift_amount |
end |
end |
|
|
|
if ( type == BRANCH ) |
begin |
pc_sel_nxt = 3'd1; // alu_out |
iaddress_sel_nxt = 4'd1; // alu_out |
alu_out_sel_nxt = 4'd1; // Add |
|
|
if ( instruction[24] ) // Link |
begin |
reg_bank_wen_nxt = decode (4'd14); // Save PC to LR |
974,7 → 999,7
end |
end |
|
|
|
if ( type == MTRANS ) |
begin |
saved_current_instruction_wen = 1'd1; // Save the memory access instruction to refer back to later |
981,7 → 1006,7
decode_daccess_nxt = 1'd1; // valid data access |
alu_out_sel_nxt = 4'd1; // Add |
base_address_wen_nxt = 1'd1; // Save the value of the register used for the base address, |
// in case of a data abort, and need to restore the value |
// in case of a data abort, and need to restore the value |
|
if ( mtrans_num_registers > 4'd1 ) |
begin |
991,10 → 1016,10
|
|
// The spec says - |
// If the instruction would have overwritten the base with data |
// If the instruction would have overwritten the base with data |
// (that is, it has the base in the transfer list), the overwriting is prevented. |
// This is true even when the abort occurs after the base word gets loaded |
restore_base_address_nxt = instruction[20] && |
restore_base_address_nxt = instruction[20] && |
(instruction[15:0] & (1'd1 << instruction[19:16])); |
|
// Increment |
1002,10 → 1027,10
begin |
if ( instruction[24] ) // increment before |
daddress_sel_nxt = 4'd7; // Rn + 4 |
else |
else |
daddress_sel_nxt = 4'd4; // Rn |
end |
else |
else |
// Decrement |
begin |
alu_cin_sel_nxt = 2'd1; // cin = 1 |
1015,15 → 1040,15
else |
daddress_sel_nxt = 4'd1; // alu out |
end |
|
|
// Load or store ? |
if ( !instruction[20] ) // Store |
write_data_wen_nxt = 1'd1; |
|
// stm: store the user mode registers, when in priviledged mode |
if ( {instruction[22],instruction[20]} == 2'b10 ) |
write_data_wen_nxt = 1'd1; |
|
// stm: store the user mode registers, when in priviledged mode |
if ( {instruction[22],instruction[20]} == 2'b10 ) |
o_user_mode_regs_store_nxt = 1'd1; |
|
|
// update the base register ? |
if ( instruction[21] ) // the W bit |
reg_bank_wen_nxt = decode (rn_sel_nxt); |
1036,21 → 1061,21
load_pc_nxt = 1'd1; |
end |
end |
|
|
|
|
if ( type == MULT ) |
begin |
multiply_function_nxt[0] = 1'd1; // set enable |
// some bits can be changed just below |
saved_current_instruction_wen = 1'd1; // Save the Multiply instruction to |
saved_current_instruction_wen = 1'd1; // Save the Multiply instruction to |
// refer back to later |
pc_wen_nxt = 1'd0; // hold current PC value |
|
|
if ( instruction[21] ) |
multiply_function_nxt[1] = 1'd1; // accumulate |
end |
|
|
|
|
// swp - do read part first |
if ( type == SWAP ) |
begin |
1070,7 → 1095,7
saved_current_instruction_wen = 1'd1; // Save the memory access instruction to refer back to later |
pc_wen_nxt = 1'd0; // hold current PC value |
iaddress_sel_nxt = 4'd3; // pc (not pc + 4) |
|
|
if ( instruction[20] ) // MRC |
copro_operation_nxt = 2'd1; // Register transfer from Co-Processor |
else // MCR |
1082,35 → 1107,35
end |
end |
|
|
|
if ( type == SWI || und_request ) |
begin |
// save address of next instruction to Supervisor Mode LR |
reg_write_sel_nxt = 3'd1; // pc -4 |
reg_bank_wen_nxt = decode (4'd14); // LR |
|
|
iaddress_sel_nxt = 4'd2; // interrupt_vector |
pc_sel_nxt = 3'd2; // interrupt_vector |
|
|
status_bits_mode_nxt = interrupt_mode; // e.g. Supervisor mode |
status_bits_mode_wen_nxt = 1'd1; |
|
|
// disable normal interrupts |
status_bits_irq_mask_nxt = 1'd1; |
status_bits_irq_mask_wen_nxt = 1'd1; |
end |
|
|
|
if ( regop_set_flags ) |
begin |
status_bits_flags_wen_nxt = 1'd1; |
|
// If <Rd> is r15, the ALU output is copied to the Status Bits. |
// Not allowed to use r15 for mul or lma instructions |
|
// If <Rd> is r15, the ALU output is copied to the Status Bits. |
// Not allowed to use r15 for mul or lma instructions |
if ( instruction[15:12] == 4'd15 ) |
begin |
status_bits_sel_nxt = 3'd1; // alu out |
|
|
// Priviledged mode? Then also update the other status bits |
if ( i_execute_status_bits[1:0] != USR ) |
begin |
1120,9 → 1145,9
end |
end |
end |
|
end |
|
end |
|
// Handle asynchronous interrupts. |
// interrupts are processed only during execution states |
// multicycle instructions must complete before the interrupt starts |
1134,8 → 1159,8
// Save the interrupt causing instruction to refer back to later |
// This also saves the instruction abort vma and status, in the case of an |
// instruction abort interrupt |
saved_current_instruction_wen = 1'd1; |
|
saved_current_instruction_wen = 1'd1; |
|
// save address of next instruction to Supervisor Mode LR |
// Address Exception ? |
if ( next_interrupt == 3'd4 ) |
1142,15 → 1167,15
reg_write_sel_nxt = 3'd7; // pc |
else |
reg_write_sel_nxt = 3'd1; // pc -4 |
|
|
reg_bank_wen_nxt = decode (4'd14); // LR |
|
|
iaddress_sel_nxt = 4'd2; // interrupt_vector |
pc_sel_nxt = 3'd2; // interrupt_vector |
|
|
status_bits_mode_nxt = interrupt_mode; // e.g. Supervisor mode |
status_bits_mode_wen_nxt = 1'd1; |
|
|
// disable normal interrupts |
status_bits_irq_mask_nxt = 1'd1; |
status_bits_irq_mask_wen_nxt = 1'd1; |
1162,16 → 1187,16
status_bits_firq_mask_wen_nxt = 1'd1; |
end |
end |
|
|
|
// previous instruction was ldr |
// if it is currently executing in the execute stage do the following |
// if it is currently executing in the execute stage do the following |
if ( control_state == MEM_WAIT1 && !conflict ) |
begin |
// Save the next instruction to execute later |
// Do this even if the ldr instruction does not execute because of Condition |
pre_fetch_instruction_wen = 1'd1; |
|
|
if ( instruction_execute ) // conditional execution state |
begin |
iaddress_sel_nxt = 4'd3; // pc (not pc + 4) |
1179,17 → 1204,17
load_pc_nxt = load_pc_r; |
end |
end |
|
|
|
|
// completion of ldr instruction |
if ( control_state == MEM_WAIT2 ) |
begin |
if ( !dabt ) // dont load data there is an abort on the data read |
begin |
begin |
pc_wen_nxt = 1'd0; // hold current PC value |
|
|
// Check if the load destination is the PC |
if (( type == TRANS && instruction[15:12] == 4'd15 ) || |
if (( type == TRANS && instruction[15:12] == 4'd15 ) || |
( type == MTRANS && instruction[20] && mtrans_reg1 == 4'd15 )) |
begin |
pc_sel_nxt = 3'd3; // read_data_filtered |
1198,19 → 1223,19
end |
end |
end |
|
|
|
|
// second cycle of multiple load or store |
if ( control_state == MTRANS_EXEC1 && !conflict ) |
begin |
// Save the next instruction to execute later |
pre_fetch_instruction_wen = 1'd1; |
|
|
if ( instruction_execute ) // conditional execution state |
begin |
daddress_sel_nxt = 4'd5; // o_address |
decode_daccess_nxt = 1'd1; // data access |
|
|
if ( mtrans_num_registers > 4'd2 ) |
decode_iaccess_nxt = 1'd0; // skip the instruction fetch |
|
1221,14 → 1246,14
iaddress_sel_nxt = 4'd3; // pc (not pc + 4) |
end |
|
|
|
if ( !instruction[20] ) // Store |
write_data_wen_nxt = 1'd1; |
|
// stm: store the user mode registers, when in priviledged mode |
if ( {instruction[22],instruction[20]} == 2'b10 ) |
|
// stm: store the user mode registers, when in priviledged mode |
if ( {instruction[22],instruction[20]} == 2'b10 ) |
o_user_mode_regs_store_nxt = 1'd1; |
|
|
// write to the pc ? |
if ( instruction[20] && mtrans_reg1 == 4'd15 ) // Write to PC |
begin |
1236,10 → 1261,10
pc_wen_nxt = 1'd0; // hold current PC value rather than an instruction fetch |
load_pc_nxt = 1'd1; |
end |
end |
end |
|
|
end |
end |
|
|
// third cycle of multiple load or store |
if ( control_state == MTRANS_EXEC2 ) |
begin |
1256,13 → 1281,13
pc_wen_nxt = 1'd0; // hold current PC value |
iaddress_sel_nxt = 4'd3; // pc (not pc + 4) |
end |
|
|
// Store |
if ( !instruction[20] ) |
write_data_wen_nxt = 1'd1; |
|
// stm: store the user mode registers, when in priviledged mode |
if ( {instruction[22],instruction[20]} == 2'b10 ) |
|
// stm: store the user mode registers, when in priviledged mode |
if ( {instruction[22],instruction[20]} == 2'b10 ) |
o_user_mode_regs_store_nxt = 1'd1; |
|
// write to the pc ? |
1273,8 → 1298,8
load_pc_nxt = 1'd1; |
end |
end |
|
|
|
|
// state is for when a data abort interrupt is triggered during an ldm |
if ( control_state == MTRANS_ABORT ) |
begin |
1286,8 → 1311,8
reg_bank_wen_nxt = decode ( instruction[19:16] ); // to Rn |
end |
end |
|
|
|
|
// Multiply or Multiply-Accumulate |
if ( control_state == MULT_PROC1 && instruction_execute && !conflict ) |
begin |
1298,7 → 1323,7
multiply_function_nxt = o_multiply_function; |
end |
|
|
|
// Multiply or Multiply-Accumulate |
// Do multiplication |
// Wait for done or accumulate signal |
1311,7 → 1336,7
multiply_function_nxt = o_multiply_function; |
end |
|
|
|
// Save RdLo |
// always last cycle of all multiply or multiply accumulate operations |
if ( control_state == MULT_STORE ) |
1318,20 → 1343,20
begin |
reg_write_sel_nxt = 3'd2; // multiply_out |
multiply_function_nxt = o_multiply_function; |
|
|
if ( type == MULT ) // 32-bit |
reg_bank_wen_nxt = decode (instruction[19:16]); // Rd |
else // 64-bit / Long |
reg_bank_wen_nxt = decode (instruction[15:12]); // RdLo |
|
|
if ( instruction[20] ) // the 'S' bit |
begin |
status_bits_sel_nxt = 3'd4; // { multiply_flags, status_bits_flags[1:0] } |
status_bits_sel_nxt = 3'd4; // { multiply_flags, status_bits_flags[1:0] } |
status_bits_flags_wen_nxt = 1'd1; |
end |
end |
|
|
|
// Add lower 32 bits to multiplication product |
if ( control_state == MULT_ACCUMU ) |
begin |
1339,8 → 1364,8
pc_wen_nxt = 1'd0; // hold current PC value |
iaddress_sel_nxt = 4'd3; // pc (not pc + 4) |
end |
|
|
|
// swp - do write request in 2nd cycle |
if ( control_state == SWAP_WRITE && instruction_execute && !conflict ) |
begin |
1349,23 → 1374,23
write_data_wen_nxt = 1'd1; |
decode_iaccess_nxt = 1'd0; // skip the instruction fetch |
decode_daccess_nxt = 1'd1; // data access |
|
|
if ( instruction[22] ) |
byte_enable_sel_nxt = 2'd1; // Save byte |
|
|
if ( instruction_execute ) // conditional execution state |
pc_wen_nxt = 1'd0; // hold current PC value |
|
|
// Save the next instruction to execute later |
// Do this even if this instruction does not execute because of Condition |
pre_fetch_instruction_wen = 1'd1; |
|
|
load_pc_nxt = load_pc_r; |
end |
|
|
|
// swp - receive read response in 3rd cycle |
if ( control_state == SWAP_WAIT1 ) |
if ( control_state == SWAP_WAIT1 ) |
begin |
|
if ( instruction_execute ) // conditional execution state |
1373,9 → 1398,9
iaddress_sel_nxt = 4'd3; // pc (not pc + 4) |
pc_wen_nxt = 1'd0; // hold current PC value |
end |
|
|
if ( !dabt ) |
begin |
begin |
// Check is the load destination is the PC |
if ( instruction[15:12] == 4'd15 ) |
begin |
1385,23 → 1410,23
end |
end |
end |
|
|
|
// 1 cycle delay for Co-Processor Register access |
if ( control_state == COPRO_WAIT && instruction_execute && !conflict ) |
begin |
pre_fetch_instruction_wen = 1'd1; |
|
|
if ( instruction[20] ) // mrc instruction |
begin |
// Check is the load destination is the PC |
if ( instruction[15:12] == 4'd15 ) |
begin |
// If r15 is specified for <Rd>, the condition code flags are |
// If r15 is specified for <Rd>, the condition code flags are |
// updated instead of a general-purpose register. |
status_bits_sel_nxt = 3'd3; // i_copro_data |
status_bits_flags_wen_nxt = 1'd1; |
|
|
// Can't change these in USR mode |
if ( i_execute_status_bits[1:0] != USR ) |
begin |
1410,25 → 1435,25
status_bits_firq_mask_wen_nxt = 1'd1; |
end |
end |
else |
else |
reg_bank_wen_nxt = decode (instruction[15:12]); |
|
|
reg_write_sel_nxt = 3'd5; // i_copro_data |
end |
else // mcr instruction |
begin |
copro_operation_nxt = 2'd2; // Register transfer to Co-Processor |
end |
copro_operation_nxt = 2'd2; // Register transfer to Co-Processor |
end |
end |
|
|
|
// Have just changed the status_bits mode but this |
// creates a 1 cycle gap with the old mode |
// coming back from execute into instruction_decode |
// So squash that old mode value during this |
// cycle of the interrupt transition |
if ( control_state == INT_WAIT1 ) |
status_bits_mode_nxt = o_status_bits_mode; // Supervisor mode |
// cycle of the interrupt transition |
if ( control_state == INT_WAIT1 ) |
status_bits_mode_nxt = status_bits_mode_r; // Supervisor mode |
|
end |
|
1443,7 → 1468,7
// ======================================================== |
|
// this replicates the current value of the execute signal in the execute stage |
assign instruction_execute = conditional_execute ( o_condition, i_execute_status_bits[31:28] ); |
assign instruction_execute = conditional_execute ( condition_r, i_execute_status_bits[31:28] ); |
|
|
// First state of executing a new instruction |
1451,7 → 1476,7
assign instruction_valid = ((control_state == EXECUTE || control_state == PRE_FETCH_EXEC) || |
// when last instruction was multi-cycle instruction but did not execute |
// because condition was false then act like you're in the execute state |
(!instruction_execute && (control_state == PC_STALL1 || |
(!instruction_execute && (control_state == PC_STALL1 || |
control_state == MEM_WAIT1 || |
control_state == COPRO_WAIT || |
control_state == SWAP_WRITE || |
1463,7 → 1488,7
begin |
// default is to hold the current state |
control_state_nxt = control_state; |
|
|
// Note: The order is important here |
if ( control_state == RST_WAIT1 ) control_state_nxt = RST_WAIT2; |
if ( control_state == RST_WAIT2 ) control_state_nxt = EXECUTE; |
1471,39 → 1496,39
if ( control_state == INT_WAIT2 ) control_state_nxt = EXECUTE; |
if ( control_state == COPRO_WAIT ) control_state_nxt = PRE_FETCH_EXEC; |
if ( control_state == PC_STALL1 ) control_state_nxt = PC_STALL2; |
if ( control_state == PC_STALL2 ) control_state_nxt = EXECUTE; |
if ( control_state == SWAP_WRITE ) control_state_nxt = SWAP_WAIT1; |
if ( control_state == SWAP_WAIT1 ) control_state_nxt = SWAP_WAIT2; |
if ( control_state == MULT_STORE ) control_state_nxt = PRE_FETCH_EXEC; |
if ( control_state == PC_STALL2 ) control_state_nxt = EXECUTE; |
if ( control_state == SWAP_WRITE ) control_state_nxt = SWAP_WAIT1; |
if ( control_state == SWAP_WAIT1 ) control_state_nxt = SWAP_WAIT2; |
if ( control_state == MULT_STORE ) control_state_nxt = PRE_FETCH_EXEC; |
if ( control_state == MTRANS_ABORT ) control_state_nxt = PRE_FETCH_EXEC; |
|
if ( control_state == MEM_WAIT1 ) |
control_state_nxt = MEM_WAIT2; |
|
if ( control_state == MEM_WAIT2 || |
if ( control_state == MEM_WAIT2 || |
control_state == SWAP_WAIT2 ) |
begin |
if ( write_pc ) // writing to the PC!! |
if ( write_pc ) // writing to the PC!! |
control_state_nxt = PC_STALL1; |
else |
control_state_nxt = PRE_FETCH_EXEC; |
end |
|
if ( control_state == MTRANS_EXEC1 ) |
begin |
|
if ( control_state == MTRANS_EXEC1 ) |
begin |
if ( mtrans_instruction_nxt[15:0] != 16'd0 ) |
control_state_nxt = MTRANS_EXEC2; |
else // if the register list holds a single register |
else // if the register list holds a single register |
begin |
if ( dabt ) // data abort |
control_state_nxt = MTRANS_ABORT; |
else if ( write_pc ) // writing to the PC!! |
else if ( write_pc ) // writing to the PC!! |
control_state_nxt = MEM_WAIT1; |
else |
control_state_nxt = PRE_FETCH_EXEC; |
end |
end |
|
|
// Stay in State MTRANS_EXEC2 until the full list of registers to |
// load or store has been processed |
if ( control_state == MTRANS_EXEC2 && mtrans_num_registers == 5'd1 ) |
1510,13 → 1535,13
begin |
if ( dabt ) // data abort |
control_state_nxt = MTRANS_ABORT; |
else if ( write_pc ) // writing to the PC!! |
else if ( write_pc ) // writing to the PC!! |
control_state_nxt = MEM_WAIT1; |
else |
control_state_nxt = PRE_FETCH_EXEC; |
end |
|
|
|
|
if ( control_state == MULT_PROC1 ) |
begin |
if (!instruction_execute) |
1524,23 → 1549,23
else |
control_state_nxt = MULT_PROC2; |
end |
|
|
if ( control_state == MULT_PROC2 ) |
begin |
if ( i_multiply_done ) |
if ( o_multiply_function[1] ) // Accumulate ? |
control_state_nxt = MULT_ACCUMU; |
else |
else |
control_state_nxt = MULT_STORE; |
end |
|
|
|
|
if ( control_state == MULT_ACCUMU ) |
begin |
control_state_nxt = MULT_STORE; |
end |
|
|
|
|
// This should come at the end, so that conditional execution works |
// correctly |
if ( instruction_valid ) |
1548,8 → 1573,8
// default is to stay in execute state, or to move into this |
// state from a conditional execute state |
control_state_nxt = EXECUTE; |
|
if ( current_write_pc ) |
|
if ( current_write_pc ) |
control_state_nxt = PC_STALL1; |
|
if ( load_op && instruction[15:12] == 4'd15 ) // load new PC value |
1565,17 → 1590,17
if ( type == MULT && !conflict ) |
control_state_nxt = MULT_PROC1; |
|
if ( type == SWAP && !conflict ) |
if ( type == SWAP && !conflict ) |
control_state_nxt = SWAP_WRITE; |
|
if ( type == CORTRANS && !und_request && !conflict ) |
if ( type == CORTRANS && !und_request && !conflict ) |
control_state_nxt = COPRO_WAIT; |
|
// interrupt overrides everything else so its last |
if ( interrupt && !conflict ) |
|
// interrupt overrides everything else so its last |
if ( interrupt && !conflict ) |
control_state_nxt = INT_WAIT1; |
end |
|
|
end |
|
|
1583,10 → 1608,10
// Register Update |
// ======================================================== |
always @ ( posedge i_clk ) |
if ( !i_core_stall ) |
begin |
if ( !i_core_stall ) |
begin |
if (!conflict) |
begin |
begin |
fetch_instruction_r <= i_fetch_instruction; |
fetch_instruction_type_r <= instruction_type(i_fetch_instruction); |
fetch_address_r <= i_execute_iaddress; |
1595,27 → 1620,27
abt_status_reg <= i_abt_status; |
end |
|
o_status_bits_mode <= status_bits_mode_nxt; |
o_status_bits_irq_mask <= status_bits_irq_mask_nxt; |
o_status_bits_firq_mask <= status_bits_firq_mask_nxt; |
status_bits_mode_r <= status_bits_mode_nxt; |
status_bits_irq_mask_r <= status_bits_irq_mask_nxt; |
status_bits_firq_mask_r <= status_bits_firq_mask_nxt; |
o_imm32 <= imm32_nxt; |
o_imm_shift_amount <= imm_shift_amount_nxt; |
o_shift_imm_zero <= shift_imm_zero_nxt; |
|
|
// when have an interrupt, execute the interrupt operation |
// unconditionally in the execute stage |
// ensures that status_bits register gets updated correctly |
// Likewise when in middle of multi-cycle instructions |
// execute them unconditionally |
o_condition <= instruction_valid && !interrupt ? condition_nxt : AL; |
condition_r <= instruction_valid && !interrupt ? condition_nxt : AL; |
o_decode_exclusive <= decode_exclusive_nxt; |
o_decode_iaccess <= decode_iaccess_nxt; |
decode_iaccess_r <= decode_iaccess_nxt; |
o_decode_daccess <= decode_daccess_nxt; |
|
|
o_rm_sel <= rm_sel_nxt; |
o_rs_sel <= rs_sel_nxt; |
o_load_rd <= load_rd_nxt; |
load_rd_d1 <= load_rd_d1_nxt; |
load_rd_d1 <= load_rd_d1_nxt; |
load_pc_r <= load_pc_nxt; |
o_rn_sel <= rn_sel_nxt; |
o_barrel_shift_amount_sel <= barrel_shift_amount_sel_nxt; |
1625,9 → 1650,9
o_use_carry_in <= use_carry_in_nxt; |
o_multiply_function <= multiply_function_nxt; |
o_interrupt_vector_sel <= next_interrupt; |
o_iaddress_sel <= iaddress_sel_nxt; |
o_daddress_sel <= daddress_sel_nxt; |
o_pc_sel <= pc_sel_nxt; |
iaddress_sel_r <= iaddress_sel_nxt; |
daddress_sel_r <= daddress_sel_nxt; |
pc_sel_r <= pc_sel_nxt; |
o_byte_enable_sel <= byte_enable_sel_nxt; |
o_status_bits_sel <= status_bits_sel_nxt; |
o_reg_write_sel <= reg_write_sel_nxt; |
1634,13 → 1659,13
o_firq_not_user_mode <= firq_not_user_mode_nxt; |
o_write_data_wen <= write_data_wen_nxt; |
o_base_address_wen <= base_address_wen_nxt; |
o_pc_wen <= pc_wen_nxt; |
pc_wen_r <= pc_wen_nxt; |
o_reg_bank_wen <= reg_bank_wen_nxt; |
o_status_bits_flags_wen <= status_bits_flags_wen_nxt; |
o_status_bits_mode_wen <= status_bits_mode_wen_nxt; |
o_status_bits_irq_mask_wen <= status_bits_irq_mask_wen_nxt; |
o_status_bits_firq_mask_wen <= status_bits_firq_mask_wen_nxt; |
|
|
o_copro_opcode1 <= instruction[23:21]; |
o_copro_opcode2 <= instruction[7:5]; |
o_copro_crn <= instruction[19:16]; |
1663,7 → 1688,7
// then when its decoded, a copy is saved to the saved_current_instruction |
// register |
if ( type == MTRANS ) |
begin |
begin |
saved_current_instruction <= mtrans_instruction_nxt; |
saved_current_instruction_type <= type; |
saved_current_instruction_iabt <= instruction_iabt; |
1671,8 → 1696,8
saved_current_instruction_address <= instruction_address; |
saved_current_instruction_iabt_status <= instruction_iabt_status; |
end |
else if ( saved_current_instruction_wen ) |
begin |
else if ( saved_current_instruction_wen ) |
begin |
saved_current_instruction <= instruction; |
saved_current_instruction_type <= type; |
saved_current_instruction_iabt <= instruction_iabt; |
1681,18 → 1706,18
saved_current_instruction_iabt_status <= instruction_iabt_status; |
end |
|
if ( pre_fetch_instruction_wen ) |
if ( pre_fetch_instruction_wen ) |
begin |
pre_fetch_instruction <= fetch_instruction_r; |
pre_fetch_instruction_type <= fetch_instruction_type_r; |
pre_fetch_instruction_iabt <= iabt_reg; |
pre_fetch_instruction_adex <= adex_reg; |
pre_fetch_instruction_address <= fetch_address_r; |
pre_fetch_instruction_iabt_status <= abt_status_reg; |
pre_fetch_instruction <= fetch_instruction_r; |
pre_fetch_instruction_type <= fetch_instruction_type_r; |
pre_fetch_instruction_iabt <= iabt_reg; |
pre_fetch_instruction_adex <= adex_reg; |
pre_fetch_instruction_address <= fetch_address_r; |
pre_fetch_instruction_iabt_status <= abt_status_reg; |
end |
|
|
// TODO possible to use saved_current_instruction instead and save some regs? |
|
|
// TODO possible to use saved_current_instruction instead and save some regs? |
hold_instruction <= instruction; |
hold_instruction_type <= type; |
hold_instruction_iabt <= instruction_iabt; |
1702,25 → 1727,25
end |
|
|
|
|
always @ ( posedge i_clk ) |
if ( !i_core_stall ) |
begin |
irq <= i_irq; |
firq <= i_firq; |
|
if ( control_state == INT_WAIT1 && o_status_bits_mode == SVC ) |
irq <= i_irq; |
firq <= i_firq; |
|
if ( control_state == INT_WAIT1 && status_bits_mode_r == SVC ) |
begin |
dabt_reg <= 1'd0; |
end |
else |
begin |
dabt_reg <= dabt_reg || i_dabt; |
dabt_reg <= dabt_reg || i_dabt; |
end |
|
dabt_reg_d1 <= dabt_reg; |
end |
|
dabt_reg_d1 <= dabt_reg; |
end |
|
assign dabt = dabt_reg || i_dabt; |
|
|
1741,9 → 1766,8
.i_interrupt ( {3{interrupt}} & next_interrupt ), |
.i_interrupt_state ( control_state == INT_WAIT2 ), |
.i_instruction_undefined ( und_request ), |
.i_pc_sel ( o_pc_sel ), |
.i_pc_wen ( o_pc_wen ) |
); |
.i_pc_sel ( pc_sel_r ), |
.i_pc_wen ( pc_wen_r )); |
|
|
wire [(15*8)-1:0] xCONTROL_STATE; |
1750,7 → 1774,7
wire [(15*8)-1:0] xMODE; |
wire [( 8*8)-1:0] xTYPE; |
|
assign xCONTROL_STATE = |
assign xCONTROL_STATE = |
control_state == RST_WAIT1 ? "RST_WAIT1" : |
control_state == RST_WAIT2 ? "RST_WAIT2" : |
|
1776,9 → 1800,9
control_state == COPRO_WAIT ? "COPRO_WAIT" : |
"UNKNOWN " ; |
|
assign xMODE = mode_name ( o_status_bits_mode ); |
assign xMODE = mode_name ( status_bits_mode_r ); |
|
assign xTYPE = |
assign xTYPE = |
type == REGOP ? "REGOP" : |
type == MULT ? "MULT" : |
type == SWAP ? "SWAP" : |
/amber25/a25_execute.v
53,7 → 53,7
input i_wb_read_data_valid, // read data is valid |
input [10:0] i_wb_load_rd, // Rd for data reads |
|
input [31:0] i_copro_read_data, // From Co-Processor, to either Register |
input [31:0] i_copro_read_data, // From Co-Processor, to either Register |
// or Memory |
input i_decode_iaccess, // Indicates an instruction access |
input i_decode_daccess, // Indicates a data access |
61,12 → 61,12
|
output reg [31:0] o_copro_write_data = 'd0, |
output reg [31:0] o_write_data = 'd0, |
output reg [31:0] o_iaddress = 32'hdead_dead, |
output [31:0] o_iaddress_nxt, // un-registered version of address to the |
output wire [31:0] o_iaddress, |
output [31:0] o_iaddress_nxt, // un-registered version of address to the |
// cache rams address ports |
output reg o_iaddress_valid = 'd0, // High when instruction address is valid |
output reg [31:0] o_daddress = 32'h0, // Address to data cache |
output [31:0] o_daddress_nxt, // un-registered version of address to the |
output [31:0] o_daddress_nxt, // un-registered version of address to the |
// cache rams address ports |
output reg o_daddress_valid = 'd0, // High when data address is valid |
output reg o_adex = 'd0, // Address Exception |
111,7 → 111,7
input i_use_carry_in, // e.g. add with carry instruction |
|
input i_write_data_wen, |
input i_base_address_wen, // save LDM base address register, |
input i_base_address_wen, // save LDM base address register, |
// in case of data abort |
input i_pc_wen, |
input [14:0] i_reg_bank_wen, |
180,7 → 180,7
wire [14:0] reg_bank_wen; |
wire [31:0] multiply_out; |
wire [1:0] multiply_flags; |
reg [31:0] base_address = 'd0; // Saves base address during LDM instruction in |
reg [31:0] base_address = 'd0; // Saves base address during LDM instruction in |
// case of data abort |
wire [31:0] read_data_filtered1; |
wire [31:0] read_data_filtered; |
192,7 → 192,7
wire write_enable_nxt; |
wire daddress_valid_nxt; |
wire iaddress_valid_nxt; |
wire priviledged_nxt; |
wire priviledged_nxt; |
wire priviledged_update; |
wire iaddress_update; |
wire daddress_update; |
217,12 → 217,14
|
wire carry_in; |
|
reg [31:0] iaddress_r = 32'hdead_dead; |
|
|
// ======================================================== |
// Status Bits in PC register |
// ======================================================== |
wire [1:0] status_bits_mode_out; |
assign status_bits_mode_out = (i_status_bits_mode_wen && i_status_bits_sel == 3'd1 && !ldm_status_bits) ? |
assign status_bits_mode_out = (i_status_bits_mode_wen && i_status_bits_sel == 3'd1 && !ldm_status_bits) ? |
alu_out[1:0] : status_bits_mode ; |
|
assign o_status_bits = { status_bits_flags, // 31:28 |
246,7 → 248,7
// 4 = update flags after a multiply operation |
i_status_bits_sel == 3'd4 ? { multiply_flags, status_bits_flags[1:0] } : |
// regops that do not change the overflow flag |
i_status_bits_sel == 3'd5 ? { alu_flags[3:1], status_bits_flags[0] } : |
i_status_bits_sel == 3'd5 ? { alu_flags[3:1], status_bits_flags[0] } : |
4'b1111 ; |
|
assign status_bits_mode_nxt = ldm_status_bits ? read_data_filtered [1:0] : |
266,14 → 268,14
assign status_bits_mode_rds_oh_nxt = i_user_mode_regs_store_nxt ? 1'd1 << OH_USR : |
status_bits_mode_update ? oh_status_bits_mode(status_bits_mode_nxt) : |
oh_status_bits_mode(status_bits_mode) ; |
|
|
|
assign status_bits_irq_mask_nxt = ldm_status_bits ? read_data_filtered [27] : |
i_status_bits_sel == 3'd0 ? i_status_bits_irq_mask : |
i_status_bits_sel == 3'd5 ? i_status_bits_irq_mask : |
i_status_bits_sel == 3'd1 ? alu_out [27] : |
i_copro_read_data [27] ; |
|
|
assign status_bits_firq_mask_nxt = ldm_status_bits ? read_data_filtered [26] : |
i_status_bits_sel == 3'd0 ? i_status_bits_firq_mask : |
i_status_bits_sel == 3'd5 ? i_status_bits_firq_mask : |
311,10 → 313,10
// ======================================================== |
|
assign interrupt_vector = // Reset vector |
(i_interrupt_vector_sel == 3'd0) ? 32'h00000000 : |
// Data abort interrupt vector |
(i_interrupt_vector_sel == 3'd0) ? 32'h00000000 : |
// Data abort interrupt vector |
(i_interrupt_vector_sel == 3'd1) ? 32'h00000010 : |
// Fast interrupt vector |
// Fast interrupt vector |
(i_interrupt_vector_sel == 3'd2) ? 32'h0000001c : |
// Regular interrupt vector |
(i_interrupt_vector_sel == 3'd3) ? 32'h00000018 : |
340,7 → 342,7
// if current instruction does not execute because it does not meet the condition |
// then address advances to next instruction |
assign o_iaddress_nxt = (pc_dmem_wen) ? pcf(read_data_filtered) : |
(!execute) ? pc_plus4 : |
(!execute) ? pc_plus4 : |
(i_iaddress_sel == 4'd0) ? pc_plus4 : |
(i_iaddress_sel == 4'd1) ? alu_out_pc_filtered : |
(i_iaddress_sel == 4'd2) ? interrupt_vector : |
370,13 → 372,13
// mem_load_rd[7] -> load status bits with PC |
// mem_load_rd[6:5] -> Write into this Mode registers |
// mem_load_rd[4] -> zero_extend byte |
// mem_load_rd[3:0] -> Destination Register |
// mem_load_rd[3:0] -> Destination Register |
assign read_data_filtered1 = i_wb_load_rd[10:9] == 2'd0 ? i_wb_read_data : |
i_wb_load_rd[10:9] == 2'd1 ? {i_wb_read_data[7:0], i_wb_read_data[31:8]} : |
i_wb_load_rd[10:9] == 2'd2 ? {i_wb_read_data[15:0], i_wb_read_data[31:16]} : |
{i_wb_read_data[23:0], i_wb_read_data[31:24]} ; |
|
assign read_data_filtered = i_wb_load_rd[4] ? {24'd0, read_data_filtered1[7:0]} : read_data_filtered1 ; |
assign read_data_filtered = i_wb_load_rd[4] ? {24'd0, read_data_filtered1[7:0]} : read_data_filtered1 ; |
|
|
// ======================================================== |
396,22 → 398,22
// Register Write Select |
// ======================================================== |
|
assign save_int_pc = { status_bits_flags, |
status_bits_irq_mask, |
status_bits_firq_mask, |
pc[25:2], |
assign save_int_pc = { status_bits_flags, |
status_bits_irq_mask, |
status_bits_firq_mask, |
pc[25:2], |
status_bits_mode }; |
|
|
assign save_int_pc_m4 = { status_bits_flags, |
status_bits_irq_mask, |
status_bits_firq_mask, |
pc_minus4[25:2], |
assign save_int_pc_m4 = { status_bits_flags, |
status_bits_irq_mask, |
status_bits_firq_mask, |
pc_minus4[25:2], |
status_bits_mode }; |
|
|
assign reg_write_nxt = i_reg_write_sel == 3'd0 ? alu_out : |
// save pc to lr on an interrupt |
// save pc to lr on an interrupt |
i_reg_write_sel == 3'd1 ? save_int_pc_m4 : |
// to update Rd at the end of Multiplication |
i_reg_write_sel == 3'd2 ? multiply_out : |
418,7 → 420,7
i_reg_write_sel == 3'd3 ? o_status_bits : |
i_reg_write_sel == 3'd5 ? i_copro_read_data : // mrc |
i_reg_write_sel == 3'd6 ? base_address : |
save_int_pc ; |
save_int_pc ; |
|
|
// ======================================================== |
426,9 → 428,9
// ======================================================== |
assign byte_enable_nxt = i_byte_enable_sel == 2'd0 ? 4'b1111 : // word write |
i_byte_enable_sel == 2'd2 ? // halfword write |
( o_daddress_nxt[1] == 1'd0 ? 4'b0011 : |
( o_daddress_nxt[1] == 1'd0 ? 4'b0011 : |
4'b1100 ) : |
|
|
o_daddress_nxt[1:0] == 2'd0 ? 4'b0001 : // byte write |
o_daddress_nxt[1:0] == 2'd1 ? 4'b0010 : |
o_daddress_nxt[1:0] == 2'd2 ? 4'b0100 : |
446,7 → 448,7
// Conditional Execution |
// ======================================================== |
assign execute = conditional_execute ( i_condition, status_bits_flags ); |
|
|
// allow the PC to increment to the next instruction when current |
// instruction does not execute |
assign pc_wen = (i_pc_wen || !execute) && !i_conflict; |
507,11 → 509,11
// Set mode for the destination registers of a mem read |
// ======================================================== |
// The mode is either user mode, or the current mode |
assign exec_load_rd_nxt = { i_decode_load_rd[7:6], |
assign exec_load_rd_nxt = { i_decode_load_rd[7:6], |
i_decode_load_rd[5] ? USR : status_bits_mode, // 1 bit -> 2 bits |
i_decode_load_rd[4:0] }; |
|
|
|
// ======================================================== |
// Register Update |
// ======================================================== |
519,7 → 521,7
|
assign daddress_update = !i_core_stall; |
assign exec_load_rd_update = !i_core_stall && execute; |
assign priviledged_update = !i_core_stall; |
assign priviledged_update = !i_core_stall; |
assign exclusive_update = !i_core_stall && execute; |
assign write_enable_update = !i_core_stall; |
assign write_data_update = !i_core_stall && execute && i_write_data_wen; |
528,7 → 530,7
assign iaddress_update = pc_dmem_wen || (!i_core_stall && !i_conflict); |
assign copro_write_data_update = !i_core_stall && execute && i_copro_write_data_wen; |
|
assign base_address_update = !i_core_stall && execute && i_base_address_wen; |
assign base_address_update = !i_core_stall && execute && i_base_address_wen; |
assign status_bits_flags_update = ldm_flags || (!i_core_stall && execute && i_status_bits_flags_wen); |
assign status_bits_mode_update = ldm_status_bits || (!i_core_stall && execute && i_status_bits_mode_wen); |
assign status_bits_mode_rds_oh_update = !i_core_stall; |
537,21 → 539,21
|
|
always @( posedge i_clk ) |
begin |
o_daddress <= daddress_update ? o_daddress_nxt : o_daddress; |
begin |
o_daddress <= daddress_update ? o_daddress_nxt : o_daddress; |
o_daddress_valid <= daddress_update ? daddress_valid_nxt : o_daddress_valid; |
o_exec_load_rd <= exec_load_rd_update ? exec_load_rd_nxt : o_exec_load_rd; |
o_priviledged <= priviledged_update ? priviledged_nxt : o_priviledged; |
o_exclusive <= exclusive_update ? i_decode_exclusive : o_exclusive; |
o_write_enable <= write_enable_update ? write_enable_nxt : o_write_enable; |
o_write_data <= write_data_update ? write_data_nxt : o_write_data; |
o_write_data <= write_data_update ? write_data_nxt : o_write_data; |
o_byte_enable <= byte_enable_update ? byte_enable_nxt : o_byte_enable; |
o_iaddress <= iaddress_update ? o_iaddress_nxt : o_iaddress; |
iaddress_r <= iaddress_update ? o_iaddress_nxt : iaddress_r; |
o_iaddress_valid <= iaddress_update ? iaddress_valid_nxt : o_iaddress_valid; |
o_adex <= iaddress_update ? adex_nxt : o_adex; |
o_copro_write_data <= copro_write_data_update ? write_data_nxt : o_copro_write_data; |
o_adex <= iaddress_update ? adex_nxt : o_adex; |
o_copro_write_data <= copro_write_data_update ? write_data_nxt : o_copro_write_data; |
|
base_address <= base_address_update ? rn : base_address; |
base_address <= base_address_update ? rn : base_address; |
|
status_bits_flags <= status_bits_flags_update ? status_bits_flags_nxt : status_bits_flags; |
status_bits_mode <= status_bits_mode_update ? status_bits_mode_nxt : status_bits_mode; |
560,7 → 562,9
status_bits_firq_mask <= status_bits_firq_mask_update ? status_bits_firq_mask_nxt : status_bits_firq_mask; |
end |
|
|
assign o_iaddress = iaddress_r; |
|
|
// ======================================================== |
// Instantiate Barrel Shift |
// ======================================================== |
582,10 → 586,10
// ======================================================== |
// Instantiate ALU |
// ======================================================== |
assign barrel_shift_carry_alu = i_barrel_shift_data_sel == 2'd0 ? |
(i_imm_shift_amount[4:1] == 0 ? status_bits_flags[1] : i_imm32[31]) : |
assign barrel_shift_carry_alu = i_barrel_shift_data_sel == 2'd0 ? |
(i_imm_shift_amount[4:1] == 0 ? status_bits_flags[1] : i_imm32[31]) : |
barrel_shift_carry; |
|
|
a25_alu u_alu ( |
.i_a_in ( rn ), |
.i_b_in ( barrel_shift_out ), |
610,7 → 614,7
.i_execute ( execute ), |
.o_out ( multiply_out ), |
.o_flags ( multiply_flags ), // [1] = N, [0] = Z |
.o_done ( o_multiply_done ) |
.o_done ( o_multiply_done ) |
); |
|
|
642,10 → 646,10
|
// pre-encoded in decode stage to speed up long path |
.i_firq_not_user_mode ( i_firq_not_user_mode ), |
|
|
// use one-hot version for speed, combine with i_user_mode_regs_store |
.i_mode_rds_exec ( status_bits_mode_rds_oh ), |
|
.i_mode_rds_exec ( status_bits_mode_rds_oh ), |
|
.o_rm ( reg_bank_rm ), |
.o_rs ( reg_bank_rs ), |
.o_rd ( reg_bank_rd ), |
685,8 → 689,8
status_bits_mode == FIRQ ? "FIRQ" : |
status_bits_mode == USR ? "USR" : |
"XXX" ; |
|
|
|
//synopsys translate_on |
|
endmodule |