Line 43... |
Line 43... |
|
|
module a25_decode
|
module a25_decode
|
(
|
(
|
input i_clk,
|
input i_clk,
|
input [31:0] i_fetch_instruction,
|
input [31:0] i_fetch_instruction,
|
input i_access_stall, // stall all stages of the cpu at the same time
|
input i_core_stall, // stall all stages of the Amber core at the same time
|
input i_irq, // interrupt request
|
input i_irq, // interrupt request
|
input i_firq, // Fast interrupt request
|
input i_firq, // Fast interrupt request
|
input i_dabt, // data abort interrupt request
|
input i_dabt, // data abort interrupt request
|
input i_iabt, // instruction pre-fetch abort flag
|
input i_iabt, // instruction pre-fetch abort flag
|
input i_adex, // Address Exception
|
input i_adex, // Address Exception
|
Line 59... |
Line 59... |
|
|
|
|
// --------------------------------------------------
|
// --------------------------------------------------
|
// Control signals to execute stage
|
// Control signals to execute stage
|
// --------------------------------------------------
|
// --------------------------------------------------
|
// output reg [4:0] o_read_data_alignment = 1'd0, // 2 LSBs of read address used for calculating shift in ldrb ops
|
|
|
|
output reg [31:0] o_imm32 = 'd0,
|
output reg [31:0] o_imm32 = 'd0,
|
output reg [4:0] o_imm_shift_amount = 'd0,
|
output reg [4:0] o_imm_shift_amount = 'd0,
|
output reg o_shift_imm_zero = 'd0,
|
output reg o_shift_imm_zero = 'd0,
|
output reg [3:0] o_condition = 4'he, // 4'he = al
|
output reg [3:0] o_condition = 4'he, // 4'he = al
|
output reg o_decode_exclusive = 'd0, // exclusive access request ( swap instruction )
|
output reg o_decode_exclusive = 'd0, // exclusive access request ( swap instruction )
|
Line 164... |
Line 162... |
|
|
// ========================================================
|
// ========================================================
|
// Internal signals
|
// Internal signals
|
// ========================================================
|
// ========================================================
|
wire [31:0] instruction;
|
wire [31:0] instruction;
|
|
wire [3:0] type; // regop, mem access etc.
|
wire instruction_iabt; // abort flag, follows the instruction
|
wire instruction_iabt; // abort flag, follows the instruction
|
wire instruction_adex; // address exception 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
|
// the instruction
|
wire [7:0] instruction_iabt_status; // abort status, follows the instruction
|
wire [7:0] instruction_iabt_status; // abort status, follows the instruction
|
wire [1:0] instruction_sel;
|
wire [1:0] instruction_sel;
|
reg [3:0] type;
|
|
wire [3:0] opcode;
|
wire [3:0] opcode;
|
wire [7:0] imm8;
|
wire [7:0] imm8;
|
wire [31:0] offset12;
|
wire [31:0] offset12;
|
wire [31:0] offset24;
|
wire [31:0] offset24;
|
wire [4:0] shift_imm;
|
wire [4:0] shift_imm;
|
Line 253... |
Line 251... |
reg iabt_reg = 'd0;
|
reg iabt_reg = 'd0;
|
reg adex_reg = 'd0;
|
reg adex_reg = 'd0;
|
reg [31:0] fetch_address_r = 'd0;
|
reg [31:0] fetch_address_r = 'd0;
|
reg [7:0] abt_status_reg = 'd0;
|
reg [7:0] abt_status_reg = 'd0;
|
reg [31:0] fetch_instruction_r = 'd0;
|
reg [31:0] fetch_instruction_r = 'd0;
|
|
reg [3:0] fetch_instruction_type_r = 'd0;
|
reg [31:0] saved_current_instruction = 'd0;
|
reg [31:0] saved_current_instruction = 'd0;
|
|
reg [3:0] saved_current_instruction_type = 'd0;
|
reg saved_current_instruction_iabt = 'd0; // access abort flag
|
reg saved_current_instruction_iabt = 'd0; // access abort flag
|
reg saved_current_instruction_adex = 'd0; // address exception
|
reg saved_current_instruction_adex = 'd0; // address exception
|
reg [31:0] saved_current_instruction_address = 'd0; // virtual address of abort instruction
|
reg [31:0] saved_current_instruction_address = 'd0; // virtual address of abort instruction
|
reg [7:0] saved_current_instruction_iabt_status = 'd0; // status of abort instruction
|
reg [7:0] saved_current_instruction_iabt_status = 'd0; // status of abort instruction
|
reg [31:0] pre_fetch_instruction = 'd0;
|
reg [31:0] pre_fetch_instruction = 'd0;
|
|
reg [3:0] pre_fetch_instruction_type = 'd0;
|
reg pre_fetch_instruction_iabt = 'd0; // access abort flag
|
reg pre_fetch_instruction_iabt = 'd0; // access abort flag
|
reg pre_fetch_instruction_adex = 'd0; // address exception
|
reg pre_fetch_instruction_adex = 'd0; // address exception
|
reg [31:0] pre_fetch_instruction_address = 'd0; // virtual address of abort instruction
|
reg [31:0] pre_fetch_instruction_address = 'd0; // virtual address of abort instruction
|
reg [7:0] pre_fetch_instruction_iabt_status = 'd0; // status of abort instruction
|
reg [7:0] pre_fetch_instruction_iabt_status = 'd0; // status of abort instruction
|
reg [31:0] hold_instruction = 'd0;
|
reg [31:0] hold_instruction = 'd0;
|
|
reg [3:0] hold_instruction_type = 'd0;
|
reg hold_instruction_iabt = 'd0; // access abort flag
|
reg hold_instruction_iabt = 'd0; // access abort flag
|
reg hold_instruction_adex = 'd0; // address exception
|
reg hold_instruction_adex = 'd0; // address exception
|
reg [31:0] hold_instruction_address = 'd0; // virtual address of abort instruction
|
reg [31:0] hold_instruction_address = 'd0; // virtual address of abort instruction
|
reg [7:0] hold_instruction_iabt_status = 'd0; // status of abort instruction
|
reg [7:0] hold_instruction_iabt_status = 'd0; // status of abort instruction
|
|
|
Line 308... |
Line 310... |
wire ldm_user_mode;
|
wire ldm_user_mode;
|
wire ldm_status_bits;
|
wire ldm_status_bits;
|
wire ldm_flags;
|
wire ldm_flags;
|
wire [6:0] load_rd_d1_nxt;
|
wire [6:0] load_rd_d1_nxt;
|
reg [6:0] load_rd_d1 = 'd0; // MSB is the valid bit
|
reg [6:0] load_rd_d1 = 'd0; // MSB is the valid bit
|
|
|
wire rn_valid;
|
wire rn_valid;
|
wire rm_valid;
|
wire rm_valid;
|
wire rs_valid;
|
wire rs_valid;
|
wire rd_valid;
|
wire rd_valid;
|
wire stm_valid;
|
wire stm_valid;
|
Line 391... |
Line 394... |
assign instruction = instruction_sel == 2'd0 ? fetch_instruction_r :
|
assign instruction = instruction_sel == 2'd0 ? fetch_instruction_r :
|
instruction_sel == 2'd1 ? saved_current_instruction :
|
instruction_sel == 2'd1 ? saved_current_instruction :
|
instruction_sel == 2'd3 ? hold_instruction :
|
instruction_sel == 2'd3 ? hold_instruction :
|
pre_fetch_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 ;
|
|
|
// abort flag
|
// abort flag
|
assign instruction_iabt = instruction_sel == 2'd0 ? iabt_reg :
|
assign instruction_iabt = instruction_sel == 2'd0 ? iabt_reg :
|
instruction_sel == 2'd1 ? saved_current_instruction_iabt :
|
instruction_sel == 2'd1 ? saved_current_instruction_iabt :
|
instruction_sel == 2'd3 ? hold_instruction_iabt :
|
instruction_sel == 2'd3 ? hold_instruction_iabt :
|
pre_fetch_instruction_iabt ;
|
pre_fetch_instruction_iabt ;
|
Line 413... |
Line 421... |
assign instruction_adex = instruction_sel == 2'd0 ? adex_reg :
|
assign instruction_adex = instruction_sel == 2'd0 ? adex_reg :
|
instruction_sel == 2'd1 ? saved_current_instruction_adex :
|
instruction_sel == 2'd1 ? saved_current_instruction_adex :
|
instruction_sel == 2'd3 ? hold_instruction_adex :
|
instruction_sel == 2'd3 ? hold_instruction_adex :
|
pre_fetch_instruction_adex ;
|
pre_fetch_instruction_adex ;
|
|
|
// Instruction Decode - Order is important!
|
|
always @*
|
|
casez ({instruction[27:20], instruction[7:4]})
|
|
12'b00010?001001 : type = SWAP;
|
|
12'b000000??1001 : type = MULT;
|
|
12'b00?????????? : type = REGOP;
|
|
12'b01?????????? : type = TRANS;
|
|
12'b100????????? : type = MTRANS;
|
|
12'b101????????? : type = BRANCH;
|
|
12'b110????????? : type = CODTRANS;
|
|
12'b1110???????0 : type = COREGOP;
|
|
12'b1110???????1 : type = CORTRANS;
|
|
default: type = SWI;
|
|
endcase
|
|
|
|
|
|
// ========================================================
|
// ========================================================
|
// Fixed fields within the instruction
|
// Fixed fields within the instruction
|
// ========================================================
|
// ========================================================
|
|
|
Line 549... |
Line 542... |
|
|
assign conflict = conflict1 || conflict2;
|
assign conflict = conflict1 || conflict2;
|
|
|
|
|
always @( posedge i_clk )
|
always @( posedge i_clk )
|
if ( !i_access_stall )
|
if ( !i_core_stall )
|
begin
|
begin
|
conflict_r <= conflict;
|
conflict_r <= conflict;
|
instruction_execute_r <= instruction_execute;
|
instruction_execute_r <= instruction_execute;
|
rn_conflict1_r <= rn_conflict1 && instruction_execute;
|
rn_conflict1_r <= rn_conflict1 && instruction_execute;
|
rm_conflict1_r <= rm_conflict1 && instruction_execute;
|
rm_conflict1_r <= rm_conflict1 && instruction_execute;
|
Line 786... |
Line 779... |
else
|
else
|
reg_bank_wen_nxt = decode (instruction[15:12]);
|
reg_bank_wen_nxt = decode (instruction[15:12]);
|
end
|
end
|
|
|
if ( !immediate_shift_op )
|
if ( !immediate_shift_op )
|
|
begin
|
barrel_shift_function_nxt = instruction[6:5];
|
barrel_shift_function_nxt = instruction[6:5];
|
|
end
|
|
|
if ( !immediate_shift_op )
|
if ( !immediate_shift_op )
|
barrel_shift_data_sel_nxt = 2'd2; // Shift value from Rm register
|
barrel_shift_data_sel_nxt = 2'd2; // Shift value from Rm register
|
|
|
if ( !immediate_shift_op && instruction[4] )
|
if ( !immediate_shift_op && instruction[4] )
|
Line 1557... |
Line 1552... |
|
|
// ========================================================
|
// ========================================================
|
// Register Update
|
// Register Update
|
// ========================================================
|
// ========================================================
|
always @ ( posedge i_clk )
|
always @ ( posedge i_clk )
|
if ( !i_access_stall )
|
if ( !i_core_stall )
|
begin
|
begin
|
if (!conflict)
|
if (!conflict)
|
begin
|
begin
|
fetch_instruction_r <= i_fetch_instruction;
|
fetch_instruction_r <= i_fetch_instruction;
|
|
fetch_instruction_type_r <= instruction_type(i_fetch_instruction);
|
fetch_address_r <= i_execute_iaddress;
|
fetch_address_r <= i_execute_iaddress;
|
iabt_reg <= i_iabt;
|
iabt_reg <= i_iabt;
|
adex_reg <= i_adex;
|
adex_reg <= i_adex;
|
abt_status_reg <= i_abt_status;
|
abt_status_reg <= i_abt_status;
|
end
|
end
|
Line 1628... |
Line 1624... |
end
|
end
|
|
|
|
|
|
|
always @ ( posedge i_clk )
|
always @ ( posedge i_clk )
|
if ( !i_access_stall )
|
if ( !i_core_stall )
|
begin
|
begin
|
// sometimes this is a pre-fetch instruction
|
// sometimes this is a pre-fetch instruction
|
// e.g. two ldr instructions in a row. The second ldr will be saved
|
// e.g. two ldr instructions in a row. The second ldr will be saved
|
// to the pre-fetch instruction register
|
// to the pre-fetch instruction register
|
// then when its decoded, a copy is saved to the saved_current_instruction
|
// then when its decoded, a copy is saved to the saved_current_instruction
|
// register
|
// register
|
if ( type == MTRANS )
|
if ( type == MTRANS )
|
begin
|
begin
|
saved_current_instruction <= mtrans_instruction_nxt;
|
saved_current_instruction <= mtrans_instruction_nxt;
|
|
saved_current_instruction_type <= type;
|
saved_current_instruction_iabt <= instruction_iabt;
|
saved_current_instruction_iabt <= instruction_iabt;
|
saved_current_instruction_adex <= instruction_adex;
|
saved_current_instruction_adex <= instruction_adex;
|
saved_current_instruction_address <= instruction_address;
|
saved_current_instruction_address <= instruction_address;
|
saved_current_instruction_iabt_status <= instruction_iabt_status;
|
saved_current_instruction_iabt_status <= instruction_iabt_status;
|
end
|
end
|
else if ( saved_current_instruction_wen )
|
else if ( saved_current_instruction_wen )
|
begin
|
begin
|
saved_current_instruction <= instruction;
|
saved_current_instruction <= instruction;
|
|
saved_current_instruction_type <= type;
|
saved_current_instruction_iabt <= instruction_iabt;
|
saved_current_instruction_iabt <= instruction_iabt;
|
saved_current_instruction_adex <= instruction_adex;
|
saved_current_instruction_adex <= instruction_adex;
|
saved_current_instruction_address <= instruction_address;
|
saved_current_instruction_address <= instruction_address;
|
saved_current_instruction_iabt_status <= instruction_iabt_status;
|
saved_current_instruction_iabt_status <= instruction_iabt_status;
|
end
|
end
|
|
|
if ( pre_fetch_instruction_wen )
|
if ( pre_fetch_instruction_wen )
|
begin
|
begin
|
pre_fetch_instruction <= fetch_instruction_r;
|
pre_fetch_instruction <= fetch_instruction_r;
|
|
pre_fetch_instruction_type <= fetch_instruction_type_r;
|
pre_fetch_instruction_iabt <= iabt_reg;
|
pre_fetch_instruction_iabt <= iabt_reg;
|
pre_fetch_instruction_adex <= adex_reg;
|
pre_fetch_instruction_adex <= adex_reg;
|
pre_fetch_instruction_address <= fetch_address_r;
|
pre_fetch_instruction_address <= fetch_address_r;
|
pre_fetch_instruction_iabt_status <= abt_status_reg;
|
pre_fetch_instruction_iabt_status <= abt_status_reg;
|
end
|
end
|
|
|
|
|
|
// TODO possible to use saved_current_instruction instead and save some regs?
|
hold_instruction <= instruction;
|
hold_instruction <= instruction;
|
|
hold_instruction_type <= type;
|
hold_instruction_iabt <= instruction_iabt;
|
hold_instruction_iabt <= instruction_iabt;
|
hold_instruction_adex <= instruction_adex;
|
hold_instruction_adex <= instruction_adex;
|
hold_instruction_address <= instruction_address;
|
hold_instruction_address <= instruction_address;
|
hold_instruction_iabt_status <= instruction_iabt_status;
|
hold_instruction_iabt_status <= instruction_iabt_status;
|
end
|
end
|
|
|
|
|
|
|
always @ ( posedge i_clk )
|
always @ ( posedge i_clk )
|
if ( !i_access_stall )
|
if ( !i_core_stall )
|
begin
|
begin
|
irq <= i_irq;
|
irq <= i_irq;
|
firq <= i_firq;
|
firq <= i_firq;
|
|
|
if ( control_state == INT_WAIT1 && o_status_bits_mode == SVC )
|
if ( control_state == INT_WAIT1 && o_status_bits_mode == SVC )
|
Line 1700... |
Line 1702... |
|
|
`include "debug_functions.v"
|
`include "debug_functions.v"
|
|
|
a25_decompile u_decompile (
|
a25_decompile u_decompile (
|
.i_clk ( i_clk ),
|
.i_clk ( i_clk ),
|
.i_access_stall ( i_access_stall ),
|
.i_core_stall ( i_core_stall ),
|
.i_instruction ( instruction ),
|
.i_instruction ( instruction ),
|
.i_instruction_valid ( instruction_valid &&!conflict ),
|
.i_instruction_valid ( instruction_valid &&!conflict ),
|
.i_instruction_execute ( instruction_execute ),
|
.i_instruction_execute ( instruction_execute ),
|
.i_instruction_address ( instruction_address ),
|
.i_instruction_address ( instruction_address ),
|
.i_interrupt ( {3{interrupt}} & next_interrupt ),
|
.i_interrupt ( {3{interrupt}} & next_interrupt ),
|