//////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////
|
// //
|
// //
|
// Execute stage of Amber 25 Core //
|
// Execute stage of Amber 25 Core //
|
// //
|
// //
|
// This file is part of the Amber project //
|
// This file is part of the Amber project //
|
// http://www.opencores.org/project,amber //
|
// http://www.opencores.org/project,amber //
|
// //
|
// //
|
// Description //
|
// Description //
|
// Executes instructions. Instantiates the register file, ALU //
|
// Executes instructions. Instantiates the register file, ALU //
|
// multiplication unit and barrel shifter. This stage is //
|
// multiplication unit and barrel shifter. This stage is //
|
// relitively simple. All the complex stuff is done in the //
|
// relitively simple. All the complex stuff is done in the //
|
// decode stage. //
|
// decode stage. //
|
// //
|
// //
|
// Author(s): //
|
// Author(s): //
|
// - Conor Santifort, csantifort.amber@gmail.com //
|
// - Conor Santifort, csantifort.amber@gmail.com //
|
// //
|
// //
|
//////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////
|
// //
|
// //
|
// Copyright (C) 2011 Authors and OPENCORES.ORG //
|
// Copyright (C) 2011 Authors and OPENCORES.ORG //
|
// //
|
// //
|
// This source file may be used and distributed without //
|
// This source file may be used and distributed without //
|
// restriction provided that this copyright statement is not //
|
// restriction provided that this copyright statement is not //
|
// removed from the file and that any derivative work contains //
|
// removed from the file and that any derivative work contains //
|
// the original copyright notice and the associated disclaimer. //
|
// the original copyright notice and the associated disclaimer. //
|
// //
|
// //
|
// This source file is free software; you can redistribute it //
|
// This source file is free software; you can redistribute it //
|
// and/or modify it under the terms of the GNU Lesser General //
|
// and/or modify it under the terms of the GNU Lesser General //
|
// Public License as published by the Free Software Foundation; //
|
// Public License as published by the Free Software Foundation; //
|
// either version 2.1 of the License, or (at your option) any //
|
// either version 2.1 of the License, or (at your option) any //
|
// later version. //
|
// later version. //
|
// //
|
// //
|
// This source is distributed in the hope that it will be //
|
// This source is distributed in the hope that it will be //
|
// useful, but WITHOUT ANY WARRANTY; without even the implied //
|
// useful, but WITHOUT ANY WARRANTY; without even the implied //
|
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //
|
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //
|
// PURPOSE. See the GNU Lesser General Public License for more //
|
// PURPOSE. See the GNU Lesser General Public License for more //
|
// details. //
|
// details. //
|
// //
|
// //
|
// You should have received a copy of the GNU Lesser General //
|
// You should have received a copy of the GNU Lesser General //
|
// Public License along with this source; if not, download it //
|
// Public License along with this source; if not, download it //
|
// from http://www.opencores.org/lgpl.shtml //
|
// from http://www.opencores.org/lgpl.shtml //
|
// //
|
// //
|
//////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////
|
|
|
|
|
module a25_execute (
|
module a25_execute (
|
|
|
input i_clk,
|
input i_clk,
|
input i_core_stall, // stall all stages of the Amber core at the same time
|
input i_core_stall, // stall all stages of the Amber core at the same time
|
input i_mem_stall, // data memory access stalls
|
input i_mem_stall, // data memory access stalls
|
output o_exec_stall, // stall the core pipeline
|
output o_exec_stall, // stall the core pipeline
|
|
|
input [31:0] i_wb_read_data, // data reads
|
input [31:0] i_wb_read_data, // data reads
|
input i_wb_read_data_valid, // read data is valid
|
input i_wb_read_data_valid, // read data is valid
|
input [10:0] i_wb_load_rd, // Rd for data reads
|
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
|
// or Memory
|
input i_decode_iaccess, // Indicates an instruction access
|
input i_decode_iaccess, // Indicates an instruction access
|
input i_decode_daccess, // Indicates a data access
|
input i_decode_daccess, // Indicates a data access
|
input [7:0] i_decode_load_rd, // The destination register for a load instruction
|
input [7:0] i_decode_load_rd, // The destination register for a load instruction
|
|
|
output reg [31:0] o_copro_write_data = 'd0,
|
output reg [31:0] o_copro_write_data = 'd0,
|
output reg [31:0] o_write_data = 'd0,
|
output reg [31:0] o_write_data = 'd0,
|
output reg [31:0] o_iaddress = 32'hdead_dead,
|
output reg [31:0] o_iaddress = 32'hdead_dead,
|
output [31:0] o_iaddress_nxt, // un-registered version of address to the
|
output [31:0] o_iaddress_nxt, // un-registered version of address to the
|
// cache rams address ports
|
// cache rams address ports
|
output reg o_iaddress_valid = 'd0, // High when instruction address is valid
|
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 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
|
// cache rams address ports
|
output reg o_daddress_valid = 'd0, // High when data address is valid
|
output reg o_daddress_valid = 'd0, // High when data address is valid
|
output reg o_adex = 'd0, // Address Exception
|
output reg o_adex = 'd0, // Address Exception
|
output reg o_priviledged = 'd0, // Priviledged access
|
output reg o_priviledged = 'd0, // Priviledged access
|
output reg o_exclusive = 'd0, // swap access
|
output reg o_exclusive = 'd0, // swap access
|
output reg o_write_enable = 'd0,
|
output reg o_write_enable = 'd0,
|
output reg [3:0] o_byte_enable = 'd0,
|
output reg [3:0] o_byte_enable = 'd0,
|
output reg [8:0] o_exec_load_rd = 'd0, // The destination register for a load instruction
|
output reg [8:0] o_exec_load_rd = 'd0, // The destination register for a load instruction
|
output [31:0] o_status_bits, // Full PC will all status bits, but PC part zero'ed out
|
output [31:0] o_status_bits, // Full PC will all status bits, but PC part zero'ed out
|
output o_multiply_done,
|
output o_multiply_done,
|
|
|
|
|
// --------------------------------------------------
|
// --------------------------------------------------
|
// Control signals from Instruction Decode stage
|
// Control signals from Instruction Decode stage
|
// --------------------------------------------------
|
// --------------------------------------------------
|
input [1:0] i_status_bits_mode,
|
input [1:0] i_status_bits_mode,
|
input i_status_bits_irq_mask,
|
input i_status_bits_irq_mask,
|
input i_status_bits_firq_mask,
|
input i_status_bits_firq_mask,
|
input [31:0] i_imm32,
|
input [31:0] i_imm32,
|
input [4:0] i_imm_shift_amount,
|
input [4:0] i_imm_shift_amount,
|
input i_shift_imm_zero,
|
input i_shift_imm_zero,
|
input [3:0] i_condition,
|
input [3:0] i_condition,
|
input i_decode_exclusive, // swap access
|
input i_decode_exclusive, // swap access
|
|
|
input [3:0] i_rm_sel,
|
input [3:0] i_rm_sel,
|
input [3:0] i_rs_sel,
|
input [3:0] i_rs_sel,
|
input [3:0] i_rn_sel,
|
input [3:0] i_rn_sel,
|
input [1:0] i_barrel_shift_amount_sel,
|
input [1:0] i_barrel_shift_amount_sel,
|
input [1:0] i_barrel_shift_data_sel,
|
input [1:0] i_barrel_shift_data_sel,
|
input [1:0] i_barrel_shift_function,
|
input [1:0] i_barrel_shift_function,
|
input [8:0] i_alu_function,
|
input [8:0] i_alu_function,
|
input [1:0] i_multiply_function,
|
input [1:0] i_multiply_function,
|
input [2:0] i_interrupt_vector_sel,
|
input [2:0] i_interrupt_vector_sel,
|
input [3:0] i_iaddress_sel,
|
input [3:0] i_iaddress_sel,
|
input [3:0] i_daddress_sel,
|
input [3:0] i_daddress_sel,
|
input [2:0] i_pc_sel,
|
input [2:0] i_pc_sel,
|
input [1:0] i_byte_enable_sel,
|
input [1:0] i_byte_enable_sel,
|
input [2:0] i_status_bits_sel,
|
input [2:0] i_status_bits_sel,
|
input [2:0] i_reg_write_sel,
|
input [2:0] i_reg_write_sel,
|
// input i_user_mode_regs_load,
|
// input i_user_mode_regs_load,
|
input i_user_mode_regs_store_nxt,
|
input i_user_mode_regs_store_nxt,
|
input i_firq_not_user_mode,
|
input i_firq_not_user_mode,
|
|
|
input i_write_data_wen,
|
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
|
// in case of data abort
|
input i_pc_wen,
|
input i_pc_wen,
|
input [14:0] i_reg_bank_wen,
|
input [14:0] i_reg_bank_wen,
|
input i_status_bits_flags_wen,
|
input i_status_bits_flags_wen,
|
input i_status_bits_mode_wen,
|
input i_status_bits_mode_wen,
|
input i_status_bits_irq_mask_wen,
|
input i_status_bits_irq_mask_wen,
|
input i_status_bits_firq_mask_wen,
|
input i_status_bits_firq_mask_wen,
|
input i_copro_write_data_wen,
|
input i_copro_write_data_wen,
|
input i_conflict,
|
input i_conflict,
|
input i_rn_use_read,
|
input i_rn_use_read,
|
input i_rm_use_read,
|
input i_rm_use_read,
|
input i_rs_use_read,
|
input i_rs_use_read,
|
input i_rd_use_read
|
input i_rd_use_read
|
);
|
);
|
|
|
`include "a25_localparams.v"
|
`include "a25_localparams.v"
|
`include "a25_functions.v"
|
`include "a25_functions.v"
|
|
|
// ========================================================
|
// ========================================================
|
// Internal signals
|
// Internal signals
|
// ========================================================
|
// ========================================================
|
wire [31:0] write_data_nxt;
|
wire [31:0] write_data_nxt;
|
wire [3:0] byte_enable_nxt;
|
wire [3:0] byte_enable_nxt;
|
wire [31:0] pc_plus4;
|
wire [31:0] pc_plus4;
|
wire [31:0] pc_minus4;
|
wire [31:0] pc_minus4;
|
wire [31:0] daddress_plus4;
|
wire [31:0] daddress_plus4;
|
wire [31:0] alu_plus4;
|
wire [31:0] alu_plus4;
|
wire [31:0] rn_plus4;
|
wire [31:0] rn_plus4;
|
wire [31:0] alu_out;
|
wire [31:0] alu_out;
|
wire [3:0] alu_flags;
|
wire [3:0] alu_flags;
|
wire [31:0] rm;
|
wire [31:0] rm;
|
wire [31:0] rs;
|
wire [31:0] rs;
|
wire [31:0] rd;
|
wire [31:0] rd;
|
wire [31:0] rn;
|
wire [31:0] rn;
|
wire [31:0] reg_bank_rn;
|
wire [31:0] reg_bank_rn;
|
wire [31:0] reg_bank_rm;
|
wire [31:0] reg_bank_rm;
|
wire [31:0] reg_bank_rs;
|
wire [31:0] reg_bank_rs;
|
wire [31:0] reg_bank_rd;
|
wire [31:0] reg_bank_rd;
|
wire [31:0] pc;
|
wire [31:0] pc;
|
wire [31:0] pc_nxt;
|
wire [31:0] pc_nxt;
|
wire [31:0] interrupt_vector;
|
wire [31:0] interrupt_vector;
|
wire [7:0] shift_amount;
|
wire [7:0] shift_amount;
|
wire [31:0] barrel_shift_in;
|
wire [31:0] barrel_shift_in;
|
wire [31:0] barrel_shift_out;
|
wire [31:0] barrel_shift_out;
|
wire barrel_shift_carry;
|
wire barrel_shift_carry;
|
wire barrel_shift_stall;
|
wire barrel_shift_stall;
|
|
|
wire [3:0] status_bits_flags_nxt;
|
wire [3:0] status_bits_flags_nxt;
|
reg [3:0] status_bits_flags = 'd0;
|
reg [3:0] status_bits_flags = 'd0;
|
wire [1:0] status_bits_mode_nxt;
|
wire [1:0] status_bits_mode_nxt;
|
reg [1:0] status_bits_mode = SVC;
|
reg [1:0] status_bits_mode = SVC;
|
// one-hot encoded rs select
|
// one-hot encoded rs select
|
wire [3:0] status_bits_mode_rds_oh_nxt;
|
wire [3:0] status_bits_mode_rds_oh_nxt;
|
reg [3:0] status_bits_mode_rds_oh = 1'd1 << OH_SVC;
|
reg [3:0] status_bits_mode_rds_oh = 1'd1 << OH_SVC;
|
wire status_bits_mode_rds_oh_update;
|
wire status_bits_mode_rds_oh_update;
|
wire status_bits_irq_mask_nxt;
|
wire status_bits_irq_mask_nxt;
|
reg status_bits_irq_mask = 1'd1;
|
reg status_bits_irq_mask = 1'd1;
|
wire status_bits_firq_mask_nxt;
|
wire status_bits_firq_mask_nxt;
|
reg status_bits_firq_mask = 1'd1;
|
reg status_bits_firq_mask = 1'd1;
|
wire [8:0] exec_load_rd_nxt;
|
wire [8:0] exec_load_rd_nxt;
|
|
|
wire execute; // high when condition execution is true
|
wire execute; // high when condition execution is true
|
wire [31:0] reg_write_nxt;
|
wire [31:0] reg_write_nxt;
|
wire pc_wen;
|
wire pc_wen;
|
wire [14:0] reg_bank_wen;
|
wire [14:0] reg_bank_wen;
|
wire [31:0] multiply_out;
|
wire [31:0] multiply_out;
|
wire [1:0] multiply_flags;
|
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
|
// case of data abort
|
wire [31:0] read_data_filtered1;
|
wire [31:0] read_data_filtered1;
|
wire [31:0] read_data_filtered;
|
wire [31:0] read_data_filtered;
|
wire [31:0] read_data_filtered_c;
|
wire [31:0] read_data_filtered_c;
|
reg [31:0] read_data_filtered_r = 'd0;
|
reg [31:0] read_data_filtered_r = 'd0;
|
reg [3:0] load_rd_r = 'd0;
|
reg [3:0] load_rd_r = 'd0;
|
wire [3:0] load_rd_c;
|
wire [3:0] load_rd_c;
|
|
|
wire write_enable_nxt;
|
wire write_enable_nxt;
|
wire daddress_valid_nxt;
|
wire daddress_valid_nxt;
|
wire iaddress_valid_nxt;
|
wire iaddress_valid_nxt;
|
wire priviledged_nxt;
|
wire priviledged_nxt;
|
wire priviledged_update;
|
wire priviledged_update;
|
wire iaddress_update;
|
wire iaddress_update;
|
wire daddress_update;
|
wire daddress_update;
|
wire base_address_update;
|
wire base_address_update;
|
wire write_data_update;
|
wire write_data_update;
|
wire copro_write_data_update;
|
wire copro_write_data_update;
|
wire byte_enable_update;
|
wire byte_enable_update;
|
wire exec_load_rd_update;
|
wire exec_load_rd_update;
|
wire write_enable_update;
|
wire write_enable_update;
|
wire exclusive_update;
|
wire exclusive_update;
|
wire status_bits_flags_update;
|
wire status_bits_flags_update;
|
wire status_bits_mode_update;
|
wire status_bits_mode_update;
|
wire status_bits_irq_mask_update;
|
wire status_bits_irq_mask_update;
|
wire status_bits_firq_mask_update;
|
wire status_bits_firq_mask_update;
|
|
|
wire [31:0] alu_out_pc_filtered;
|
wire [31:0] alu_out_pc_filtered;
|
wire adex_nxt;
|
wire adex_nxt;
|
wire [31:0] save_int_pc;
|
wire [31:0] save_int_pc;
|
wire [31:0] save_int_pc_m4;
|
wire [31:0] save_int_pc_m4;
|
wire ldm_flags;
|
wire ldm_flags;
|
wire ldm_status_bits;
|
wire ldm_status_bits;
|
|
|
// ========================================================
|
// ========================================================
|
// Status Bits in PC register
|
// Status Bits in PC register
|
// ========================================================
|
// ========================================================
|
assign o_status_bits = { status_bits_flags, // 31:28
|
assign o_status_bits = { status_bits_flags, // 31:28
|
status_bits_irq_mask, // 7
|
status_bits_irq_mask, // 7
|
status_bits_firq_mask, // 6
|
status_bits_firq_mask, // 6
|
24'd0,
|
24'd0,
|
status_bits_mode }; // 1:0 = mode
|
status_bits_mode }; // 1:0 = mode
|
|
|
|
|
// ========================================================
|
// ========================================================
|
// Status Bits Select
|
// Status Bits Select
|
// ========================================================
|
// ========================================================
|
assign ldm_flags = i_wb_read_data_valid & ~i_mem_stall & i_wb_load_rd[8];
|
assign ldm_flags = i_wb_read_data_valid & ~i_mem_stall & i_wb_load_rd[8];
|
assign ldm_status_bits = i_wb_read_data_valid & ~i_mem_stall & i_wb_load_rd[7];
|
assign ldm_status_bits = i_wb_read_data_valid & ~i_mem_stall & i_wb_load_rd[7];
|
|
|
|
|
assign status_bits_flags_nxt = ldm_flags ? read_data_filtered[31:28] :
|
assign status_bits_flags_nxt = ldm_flags ? read_data_filtered[31:28] :
|
i_status_bits_sel == 3'd0 ? alu_flags :
|
i_status_bits_sel == 3'd0 ? alu_flags :
|
i_status_bits_sel == 3'd1 ? alu_out [31:28] :
|
i_status_bits_sel == 3'd1 ? alu_out [31:28] :
|
i_status_bits_sel == 3'd3 ? i_copro_read_data[31:28] :
|
i_status_bits_sel == 3'd3 ? i_copro_read_data[31:28] :
|
// 4 = update flags after a multiply operation
|
// 4 = update flags after a multiply operation
|
{ multiply_flags, status_bits_flags[1:0] } ;
|
{ multiply_flags, status_bits_flags[1:0] } ;
|
|
|
assign status_bits_mode_nxt = ldm_status_bits ? read_data_filtered [1:0] :
|
assign status_bits_mode_nxt = ldm_status_bits ? read_data_filtered [1:0] :
|
i_status_bits_sel == 3'd0 ? i_status_bits_mode :
|
i_status_bits_sel == 3'd0 ? i_status_bits_mode :
|
i_status_bits_sel == 3'd1 ? alu_out [1:0] :
|
i_status_bits_sel == 3'd1 ? alu_out [1:0] :
|
i_copro_read_data [1:0] ;
|
i_copro_read_data [1:0] ;
|
|
|
|
|
// Used for the Rds output of register_bank - this special version of
|
// Used for the Rds output of register_bank - this special version of
|
// status_bits_mode speeds up the critical path from status_bits_mode through the
|
// status_bits_mode speeds up the critical path from status_bits_mode through the
|
// register_bank, barrel_shifter and alu. It moves a mux needed for the
|
// register_bank, barrel_shifter and alu. It moves a mux needed for the
|
// i_user_mode_regs_store_nxt signal back into the previous stage -
|
// i_user_mode_regs_store_nxt signal back into the previous stage -
|
// so its really part of the decode stage even though the logic is right here
|
// so its really part of the decode stage even though the logic is right here
|
// In addition the signal is one-hot encoded to further speed up the logic
|
// In addition the signal is one-hot encoded to further speed up the logic
|
|
|
assign status_bits_mode_rds_oh_nxt = i_user_mode_regs_store_nxt ? 1'd1 << OH_USR :
|
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) :
|
status_bits_mode_update ? oh_status_bits_mode(status_bits_mode_nxt) :
|
oh_status_bits_mode(status_bits_mode) ;
|
oh_status_bits_mode(status_bits_mode) ;
|
|
|
|
|
assign status_bits_irq_mask_nxt = ldm_status_bits ? read_data_filtered [27] :
|
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'd0 ? i_status_bits_irq_mask :
|
i_status_bits_sel == 3'd1 ? alu_out [27] :
|
i_status_bits_sel == 3'd1 ? alu_out [27] :
|
i_copro_read_data [27] ;
|
i_copro_read_data [27] ;
|
|
|
assign status_bits_firq_mask_nxt = ldm_status_bits ? read_data_filtered [26] :
|
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'd0 ? i_status_bits_firq_mask :
|
i_status_bits_sel == 3'd1 ? alu_out [26] :
|
i_status_bits_sel == 3'd1 ? alu_out [26] :
|
i_copro_read_data [26] ;
|
i_copro_read_data [26] ;
|
|
|
|
|
|
|
// ========================================================
|
// ========================================================
|
// Adders
|
// Adders
|
// ========================================================
|
// ========================================================
|
assign pc_plus4 = pc + 32'd4;
|
assign pc_plus4 = pc + 32'd4;
|
assign pc_minus4 = pc - 32'd4;
|
assign pc_minus4 = pc - 32'd4;
|
assign daddress_plus4 = o_daddress + 32'd4;
|
assign daddress_plus4 = o_daddress + 32'd4;
|
assign alu_plus4 = alu_out + 32'd4;
|
assign alu_plus4 = alu_out + 32'd4;
|
assign rn_plus4 = rn + 32'd4;
|
assign rn_plus4 = rn + 32'd4;
|
|
|
// ========================================================
|
// ========================================================
|
// Barrel Shift Amount Select
|
// Barrel Shift Amount Select
|
// ========================================================
|
// ========================================================
|
// An immediate shift value of 0 is translated into 32
|
// An immediate shift value of 0 is translated into 32
|
assign shift_amount = i_barrel_shift_amount_sel == 2'd0 ? 8'd0 :
|
assign shift_amount = i_barrel_shift_amount_sel == 2'd0 ? 8'd0 :
|
i_barrel_shift_amount_sel == 2'd1 ? rs[7:0] :
|
i_barrel_shift_amount_sel == 2'd1 ? rs[7:0] :
|
{3'd0, i_imm_shift_amount } ;
|
{3'd0, i_imm_shift_amount } ;
|
|
|
|
|
// ========================================================
|
// ========================================================
|
// Barrel Shift Data Select
|
// Barrel Shift Data Select
|
// ========================================================
|
// ========================================================
|
assign barrel_shift_in = i_barrel_shift_data_sel == 2'd0 ? i_imm32 : rm ;
|
assign barrel_shift_in = i_barrel_shift_data_sel == 2'd0 ? i_imm32 : rm ;
|
|
|
|
|
// ========================================================
|
// ========================================================
|
// Interrupt vector Select
|
// Interrupt vector Select
|
// ========================================================
|
// ========================================================
|
|
|
assign interrupt_vector = // Reset vector
|
assign interrupt_vector = // Reset vector
|
(i_interrupt_vector_sel == 3'd0) ? 32'h00000000 :
|
(i_interrupt_vector_sel == 3'd0) ? 32'h00000000 :
|
// Data abort interrupt vector
|
// Data abort interrupt vector
|
(i_interrupt_vector_sel == 3'd1) ? 32'h00000010 :
|
(i_interrupt_vector_sel == 3'd1) ? 32'h00000010 :
|
// Fast interrupt vector
|
// Fast interrupt vector
|
(i_interrupt_vector_sel == 3'd2) ? 32'h0000001c :
|
(i_interrupt_vector_sel == 3'd2) ? 32'h0000001c :
|
// Regular interrupt vector
|
// Regular interrupt vector
|
(i_interrupt_vector_sel == 3'd3) ? 32'h00000018 :
|
(i_interrupt_vector_sel == 3'd3) ? 32'h00000018 :
|
// Prefetch abort interrupt vector
|
// Prefetch abort interrupt vector
|
(i_interrupt_vector_sel == 3'd5) ? 32'h0000000c :
|
(i_interrupt_vector_sel == 3'd5) ? 32'h0000000c :
|
// Undefined instruction interrupt vector
|
// Undefined instruction interrupt vector
|
(i_interrupt_vector_sel == 3'd6) ? 32'h00000004 :
|
(i_interrupt_vector_sel == 3'd6) ? 32'h00000004 :
|
// Software (SWI) interrupt vector
|
// Software (SWI) interrupt vector
|
(i_interrupt_vector_sel == 3'd7) ? 32'h00000008 :
|
(i_interrupt_vector_sel == 3'd7) ? 32'h00000008 :
|
// Default is the address exception interrupt
|
// Default is the address exception interrupt
|
32'h00000014 ;
|
32'h00000014 ;
|
|
|
|
|
// ========================================================
|
// ========================================================
|
// Address Select
|
// Address Select
|
// ========================================================
|
// ========================================================
|
assign pc_dmem_wen = i_wb_read_data_valid & ~i_mem_stall & i_wb_load_rd[3:0] == 4'd15;
|
assign pc_dmem_wen = i_wb_read_data_valid & ~i_mem_stall & i_wb_load_rd[3:0] == 4'd15;
|
|
|
// If rd is the pc, then seperate the address bits from the status bits for
|
// If rd is the pc, then seperate the address bits from the status bits for
|
// generating the next address to fetch
|
// generating the next address to fetch
|
assign alu_out_pc_filtered = pc_wen && i_pc_sel == 3'd1 ? pcf(alu_out) : alu_out;
|
assign alu_out_pc_filtered = pc_wen && i_pc_sel == 3'd1 ? pcf(alu_out) : alu_out;
|
|
|
// if current instruction does not execute because it does not meet the condition
|
// if current instruction does not execute because it does not meet the condition
|
// then address advances to next instruction
|
// then address advances to next instruction
|
assign o_iaddress_nxt = (pc_dmem_wen) ? pcf(read_data_filtered) :
|
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'd0) ? pc_plus4 :
|
(i_iaddress_sel == 4'd1) ? alu_out_pc_filtered :
|
(i_iaddress_sel == 4'd1) ? alu_out_pc_filtered :
|
(i_iaddress_sel == 4'd2) ? interrupt_vector :
|
(i_iaddress_sel == 4'd2) ? interrupt_vector :
|
pc ;
|
pc ;
|
|
|
|
|
|
|
// if current instruction does not execute because it does not meet the condition
|
// if current instruction does not execute because it does not meet the condition
|
// then address advances to next instruction
|
// then address advances to next instruction
|
assign o_daddress_nxt = (i_daddress_sel == 4'd1) ? alu_out_pc_filtered :
|
assign o_daddress_nxt = (i_daddress_sel == 4'd1) ? alu_out_pc_filtered :
|
(i_daddress_sel == 4'd2) ? interrupt_vector :
|
(i_daddress_sel == 4'd2) ? interrupt_vector :
|
(i_daddress_sel == 4'd4) ? rn :
|
(i_daddress_sel == 4'd4) ? rn :
|
(i_daddress_sel == 4'd5) ? daddress_plus4 : // MTRANS address incrementer
|
(i_daddress_sel == 4'd5) ? daddress_plus4 : // MTRANS address incrementer
|
(i_daddress_sel == 4'd6) ? alu_plus4 : // MTRANS decrement after
|
(i_daddress_sel == 4'd6) ? alu_plus4 : // MTRANS decrement after
|
rn_plus4 ; // MTRANS increment before
|
rn_plus4 ; // MTRANS increment before
|
|
|
// Data accesses use 32-bit address space, but instruction
|
// Data accesses use 32-bit address space, but instruction
|
// accesses are restricted to 26 bit space
|
// accesses are restricted to 26 bit space
|
assign adex_nxt = |o_iaddress_nxt[31:26] && i_decode_iaccess;
|
assign adex_nxt = |o_iaddress_nxt[31:26] && i_decode_iaccess;
|
|
|
|
|
// ========================================================
|
// ========================================================
|
// Filter Read Data
|
// Filter Read Data
|
// ========================================================
|
// ========================================================
|
// mem_load_rd[10:9]-> shift ROR bytes
|
// mem_load_rd[10:9]-> shift ROR bytes
|
// mem_load_rd[8] -> load flags with PC
|
// mem_load_rd[8] -> load flags with PC
|
// mem_load_rd[7] -> load status bits with PC
|
// mem_load_rd[7] -> load status bits with PC
|
// mem_load_rd[6:5] -> Write into this Mode registers
|
// mem_load_rd[6:5] -> Write into this Mode registers
|
// mem_load_rd[4] -> zero_extend byte
|
// 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 :
|
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'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_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]} ;
|
{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 ;
|
|
|
|
|
// ========================================================
|
// ========================================================
|
// Program Counter Select
|
// Program Counter Select
|
// ========================================================
|
// ========================================================
|
// If current instruction does not execute because it does not meet the condition
|
// If current instruction does not execute because it does not meet the condition
|
// then PC advances to next instruction
|
// then PC advances to next instruction
|
assign pc_nxt = (!execute) ? pc_plus4 :
|
assign pc_nxt = (!execute) ? pc_plus4 :
|
i_pc_sel == 3'd0 ? pc_plus4 :
|
i_pc_sel == 3'd0 ? pc_plus4 :
|
i_pc_sel == 3'd1 ? alu_out :
|
i_pc_sel == 3'd1 ? alu_out :
|
i_pc_sel == 3'd2 ? interrupt_vector :
|
i_pc_sel == 3'd2 ? interrupt_vector :
|
i_pc_sel == 3'd3 ? pcf(read_data_filtered) :
|
i_pc_sel == 3'd3 ? pcf(read_data_filtered) :
|
pc_minus4 ;
|
pc_minus4 ;
|
|
|
|
|
// ========================================================
|
// ========================================================
|
// Register Write Select
|
// Register Write Select
|
// ========================================================
|
// ========================================================
|
|
|
assign save_int_pc = { status_bits_flags,
|
assign save_int_pc = { status_bits_flags,
|
status_bits_irq_mask,
|
status_bits_irq_mask,
|
status_bits_firq_mask,
|
status_bits_firq_mask,
|
pc[25:2],
|
pc[25:2],
|
status_bits_mode };
|
status_bits_mode };
|
|
|
|
|
assign save_int_pc_m4 = { status_bits_flags,
|
assign save_int_pc_m4 = { status_bits_flags,
|
status_bits_irq_mask,
|
status_bits_irq_mask,
|
status_bits_firq_mask,
|
status_bits_firq_mask,
|
pc_minus4[25:2],
|
pc_minus4[25:2],
|
status_bits_mode };
|
status_bits_mode };
|
|
|
|
|
assign reg_write_nxt = i_reg_write_sel == 3'd0 ? alu_out :
|
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 :
|
i_reg_write_sel == 3'd1 ? save_int_pc_m4 :
|
// to update Rd at the end of Multiplication
|
// to update Rd at the end of Multiplication
|
i_reg_write_sel == 3'd2 ? multiply_out :
|
i_reg_write_sel == 3'd2 ? multiply_out :
|
i_reg_write_sel == 3'd3 ? o_status_bits :
|
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'd5 ? i_copro_read_data : // mrc
|
i_reg_write_sel == 3'd6 ? base_address :
|
i_reg_write_sel == 3'd6 ? base_address :
|
save_int_pc ;
|
save_int_pc ;
|
|
|
|
|
// ========================================================
|
// ========================================================
|
// Byte Enable Select
|
// Byte Enable Select
|
// ========================================================
|
// ========================================================
|
assign byte_enable_nxt = i_byte_enable_sel == 2'd0 ? 4'b1111 : // word write
|
assign byte_enable_nxt = i_byte_enable_sel == 2'd0 ? 4'b1111 : // word write
|
i_byte_enable_sel == 2'd2 ? // halfword 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 ) :
|
4'b1100 ) :
|
|
|
o_daddress_nxt[1:0] == 2'd0 ? 4'b0001 : // byte write
|
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'd1 ? 4'b0010 :
|
o_daddress_nxt[1:0] == 2'd2 ? 4'b0100 :
|
o_daddress_nxt[1:0] == 2'd2 ? 4'b0100 :
|
4'b1000 ;
|
4'b1000 ;
|
|
|
|
|
// ========================================================
|
// ========================================================
|
// Write Data Select
|
// Write Data Select
|
// ========================================================
|
// ========================================================
|
assign write_data_nxt = i_byte_enable_sel == 2'd0 ? rd :
|
assign write_data_nxt = i_byte_enable_sel == 2'd0 ? rd :
|
{4{rd[ 7:0]}} ;
|
{4{rd[ 7:0]}} ;
|
|
|
|
|
// ========================================================
|
// ========================================================
|
// Conditional Execution
|
// Conditional Execution
|
// ========================================================
|
// ========================================================
|
assign execute = conditional_execute ( i_condition, status_bits_flags );
|
assign execute = conditional_execute ( i_condition, status_bits_flags );
|
|
|
// allow the PC to increment to the next instruction when current
|
// allow the PC to increment to the next instruction when current
|
// instruction does not execute
|
// instruction does not execute
|
assign pc_wen = (i_pc_wen || !execute) && !i_conflict;
|
assign pc_wen = (i_pc_wen || !execute) && !i_conflict;
|
|
|
// only update register bank if current instruction executes
|
// only update register bank if current instruction executes
|
assign reg_bank_wen = {{15{execute}} & i_reg_bank_wen};
|
assign reg_bank_wen = {{15{execute}} & i_reg_bank_wen};
|
|
|
|
|
// ========================================================
|
// ========================================================
|
// Priviledged output flag
|
// Priviledged output flag
|
// ========================================================
|
// ========================================================
|
// Need to look at status_bits_mode_nxt so switch to priviledged mode
|
// Need to look at status_bits_mode_nxt so switch to priviledged mode
|
// at the same time as assert interrupt vector address
|
// at the same time as assert interrupt vector address
|
assign priviledged_nxt = ( i_status_bits_mode_wen ? status_bits_mode_nxt : status_bits_mode ) != USR ;
|
assign priviledged_nxt = ( i_status_bits_mode_wen ? status_bits_mode_nxt : status_bits_mode ) != USR ;
|
|
|
|
|
// ========================================================
|
// ========================================================
|
// Write Enable
|
// Write Enable
|
// ========================================================
|
// ========================================================
|
// This must be de-asserted when execute is fault
|
// This must be de-asserted when execute is fault
|
assign write_enable_nxt = execute && i_write_data_wen;
|
assign write_enable_nxt = execute && i_write_data_wen;
|
|
|
|
|
// ========================================================
|
// ========================================================
|
// Address Valid
|
// Address Valid
|
// ========================================================
|
// ========================================================
|
assign daddress_valid_nxt = execute && i_decode_daccess && !i_core_stall;
|
assign daddress_valid_nxt = execute && i_decode_daccess && !i_core_stall;
|
|
|
// For some multi-cycle instructions, the stream of instrution
|
// For some multi-cycle instructions, the stream of instrution
|
// reads can be paused. However if the instruction does not execute
|
// reads can be paused. However if the instruction does not execute
|
// then the read stream must not be interrupted.
|
// then the read stream must not be interrupted.
|
assign iaddress_valid_nxt = i_decode_iaccess || !execute;
|
assign iaddress_valid_nxt = i_decode_iaccess || !execute;
|
|
|
|
|
// ========================================================
|
// ========================================================
|
// Use read value from data memory instead of from register
|
// Use read value from data memory instead of from register
|
// ========================================================
|
// ========================================================
|
assign rn = i_rn_use_read && i_rn_sel == load_rd_c ? read_data_filtered_c : reg_bank_rn;
|
assign rn = i_rn_use_read && i_rn_sel == load_rd_c ? read_data_filtered_c : reg_bank_rn;
|
assign rm = i_rm_use_read && i_rm_sel == load_rd_c ? read_data_filtered_c : reg_bank_rm;
|
assign rm = i_rm_use_read && i_rm_sel == load_rd_c ? read_data_filtered_c : reg_bank_rm;
|
assign rs = i_rs_use_read && i_rs_sel == load_rd_c ? read_data_filtered_c : reg_bank_rs;
|
assign rs = i_rs_use_read && i_rs_sel == load_rd_c ? read_data_filtered_c : reg_bank_rs;
|
assign rd = i_rd_use_read && i_rs_sel == load_rd_c ? read_data_filtered_c : reg_bank_rd;
|
assign rd = i_rd_use_read && i_rs_sel == load_rd_c ? read_data_filtered_c : reg_bank_rd;
|
|
|
|
|
always@( posedge i_clk )
|
always@( posedge i_clk )
|
if ( i_wb_read_data_valid )
|
if ( i_wb_read_data_valid )
|
begin
|
begin
|
read_data_filtered_r <= read_data_filtered;
|
read_data_filtered_r <= read_data_filtered;
|
load_rd_r <= i_wb_load_rd[3:0];
|
load_rd_r <= i_wb_load_rd[3:0];
|
end
|
end
|
|
|
assign read_data_filtered_c = i_wb_read_data_valid ? read_data_filtered : read_data_filtered_r;
|
assign read_data_filtered_c = i_wb_read_data_valid ? read_data_filtered : read_data_filtered_r;
|
assign load_rd_c = i_wb_read_data_valid ? i_wb_load_rd[3:0] : load_rd_r;
|
assign load_rd_c = i_wb_read_data_valid ? i_wb_load_rd[3:0] : load_rd_r;
|
|
|
|
|
// ========================================================
|
// ========================================================
|
// Set mode for the destination registers of a mem read
|
// Set mode for the destination registers of a mem read
|
// ========================================================
|
// ========================================================
|
// The mode is either user mode, or the current mode
|
// 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[5] ? USR : status_bits_mode, // 1 bit -> 2 bits
|
i_decode_load_rd[4:0] };
|
i_decode_load_rd[4:0] };
|
|
|
|
|
// ========================================================
|
// ========================================================
|
// Register Update
|
// Register Update
|
// ========================================================
|
// ========================================================
|
assign o_exec_stall = barrel_shift_stall;
|
assign o_exec_stall = barrel_shift_stall;
|
|
|
assign daddress_update = !i_core_stall;
|
assign daddress_update = !i_core_stall;
|
assign exec_load_rd_update = !i_core_stall && execute;
|
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 exclusive_update = !i_core_stall && execute;
|
assign write_enable_update = !i_core_stall;
|
assign write_enable_update = !i_core_stall;
|
assign write_data_update = !i_core_stall && execute && i_write_data_wen;
|
assign write_data_update = !i_core_stall && execute && i_write_data_wen;
|
assign byte_enable_update = !i_core_stall && execute && i_write_data_wen;
|
assign byte_enable_update = !i_core_stall && execute && i_write_data_wen;
|
|
|
assign iaddress_update = pc_dmem_wen || (!i_core_stall && !i_conflict);
|
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 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_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_update = ldm_status_bits || (!i_core_stall && execute && i_status_bits_mode_wen);
|
assign status_bits_mode_rds_oh_update = !i_core_stall;
|
assign status_bits_mode_rds_oh_update = !i_core_stall;
|
assign status_bits_irq_mask_update = ldm_status_bits || (!i_core_stall && execute && i_status_bits_irq_mask_wen);
|
assign status_bits_irq_mask_update = ldm_status_bits || (!i_core_stall && execute && i_status_bits_irq_mask_wen);
|
assign status_bits_firq_mask_update = ldm_status_bits || (!i_core_stall && execute && i_status_bits_firq_mask_wen);
|
assign status_bits_firq_mask_update = ldm_status_bits || (!i_core_stall && execute && i_status_bits_firq_mask_wen);
|
|
|
|
|
always @( posedge i_clk )
|
always @( posedge i_clk )
|
begin
|
begin
|
o_daddress <= daddress_update ? o_daddress_nxt : o_daddress;
|
o_daddress <= daddress_update ? o_daddress_nxt : o_daddress;
|
o_daddress_valid <= daddress_update ? daddress_valid_nxt : o_daddress_valid;
|
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_exec_load_rd <= exec_load_rd_update ? exec_load_rd_nxt : o_exec_load_rd;
|
o_priviledged <= priviledged_update ? priviledged_nxt : o_priviledged;
|
o_priviledged <= priviledged_update ? priviledged_nxt : o_priviledged;
|
o_exclusive <= exclusive_update ? i_decode_exclusive : o_exclusive;
|
o_exclusive <= exclusive_update ? i_decode_exclusive : o_exclusive;
|
o_write_enable <= write_enable_update ? write_enable_nxt : o_write_enable;
|
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_byte_enable <= byte_enable_update ? byte_enable_nxt : o_byte_enable;
|
o_iaddress <= iaddress_update ? o_iaddress_nxt : o_iaddress;
|
o_iaddress <= iaddress_update ? o_iaddress_nxt : o_iaddress;
|
o_iaddress_valid <= iaddress_update ? iaddress_valid_nxt : o_iaddress_valid;
|
o_iaddress_valid <= iaddress_update ? iaddress_valid_nxt : o_iaddress_valid;
|
o_adex <= iaddress_update ? adex_nxt : o_adex;
|
o_adex <= iaddress_update ? adex_nxt : o_adex;
|
o_copro_write_data <= copro_write_data_update ? write_data_nxt : o_copro_write_data;
|
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_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;
|
status_bits_mode <= status_bits_mode_update ? status_bits_mode_nxt : status_bits_mode;
|
status_bits_mode_rds_oh <= status_bits_mode_rds_oh_update ? status_bits_mode_rds_oh_nxt : status_bits_mode_rds_oh;
|
status_bits_mode_rds_oh <= status_bits_mode_rds_oh_update ? status_bits_mode_rds_oh_nxt : status_bits_mode_rds_oh;
|
status_bits_irq_mask <= status_bits_irq_mask_update ? status_bits_irq_mask_nxt : status_bits_irq_mask;
|
status_bits_irq_mask <= status_bits_irq_mask_update ? status_bits_irq_mask_nxt : status_bits_irq_mask;
|
status_bits_firq_mask <= status_bits_firq_mask_update ? status_bits_firq_mask_nxt : status_bits_firq_mask;
|
status_bits_firq_mask <= status_bits_firq_mask_update ? status_bits_firq_mask_nxt : status_bits_firq_mask;
|
end
|
end
|
|
|
|
|
// ========================================================
|
// ========================================================
|
// Instantiate Barrel Shift
|
// Instantiate Barrel Shift
|
// ========================================================
|
// ========================================================
|
a25_barrel_shift u_barrel_shift (
|
a25_barrel_shift u_barrel_shift (
|
.i_clk ( i_clk ),
|
.i_clk ( i_clk ),
|
.i_in ( barrel_shift_in ),
|
.i_in ( barrel_shift_in ),
|
.i_carry_in ( status_bits_flags[1] ),
|
.i_carry_in ( status_bits_flags[1] ),
|
.i_shift_amount ( shift_amount ),
|
.i_shift_amount ( shift_amount ),
|
.i_shift_imm_zero ( i_shift_imm_zero ),
|
.i_shift_imm_zero ( i_shift_imm_zero ),
|
.i_function ( i_barrel_shift_function ),
|
.i_function ( i_barrel_shift_function ),
|
|
|
.o_out ( barrel_shift_out ),
|
.o_out ( barrel_shift_out ),
|
.o_carry_out ( barrel_shift_carry ),
|
.o_carry_out ( barrel_shift_carry ),
|
.o_stall ( barrel_shift_stall )
|
.o_stall ( barrel_shift_stall )
|
);
|
);
|
|
|
|
|
// ========================================================
|
// ========================================================
|
// Instantiate ALU
|
// Instantiate ALU
|
// ========================================================
|
// ========================================================
|
a25_alu u_alu (
|
a25_alu u_alu (
|
.i_a_in ( rn ),
|
.i_a_in ( rn ),
|
.i_b_in ( barrel_shift_out ),
|
.i_b_in ( barrel_shift_out ),
|
.i_barrel_shift_carry ( barrel_shift_carry ),
|
.i_barrel_shift_carry ( barrel_shift_carry ),
|
.i_status_bits_carry ( status_bits_flags[1] ),
|
.i_status_bits_carry ( status_bits_flags[1] ),
|
.i_function ( i_alu_function ),
|
.i_function ( i_alu_function ),
|
|
|
.o_out ( alu_out ),
|
.o_out ( alu_out ),
|
.o_flags ( alu_flags )
|
.o_flags ( alu_flags )
|
);
|
);
|
|
|
|
|
// ========================================================
|
// ========================================================
|
// Instantiate Booth 64-bit Multiplier-Accumulator
|
// Instantiate Booth 64-bit Multiplier-Accumulator
|
// ========================================================
|
// ========================================================
|
a25_multiply u_multiply (
|
a25_multiply u_multiply (
|
.i_clk ( i_clk ),
|
.i_clk ( i_clk ),
|
.i_core_stall ( i_core_stall ),
|
.i_core_stall ( i_core_stall ),
|
.i_a_in ( rs ),
|
.i_a_in ( rs ),
|
.i_b_in ( rm ),
|
.i_b_in ( rm ),
|
.i_function ( i_multiply_function ),
|
.i_function ( i_multiply_function ),
|
.i_execute ( execute ),
|
.i_execute ( execute ),
|
.o_out ( multiply_out ),
|
.o_out ( multiply_out ),
|
.o_flags ( multiply_flags ), // [1] = N, [0] = Z
|
.o_flags ( multiply_flags ), // [1] = N, [0] = Z
|
.o_done ( o_multiply_done )
|
.o_done ( o_multiply_done )
|
);
|
);
|
|
|
|
|
// ========================================================
|
// ========================================================
|
// Instantiate Register Bank
|
// Instantiate Register Bank
|
// ========================================================
|
// ========================================================
|
a25_register_bank u_register_bank(
|
a25_register_bank u_register_bank(
|
.i_clk ( i_clk ),
|
.i_clk ( i_clk ),
|
.i_core_stall ( i_core_stall ),
|
.i_core_stall ( i_core_stall ),
|
.i_mem_stall ( i_mem_stall ),
|
.i_mem_stall ( i_mem_stall ),
|
.i_rm_sel ( i_rm_sel ),
|
.i_rm_sel ( i_rm_sel ),
|
.i_rs_sel ( i_rs_sel ),
|
.i_rs_sel ( i_rs_sel ),
|
.i_rn_sel ( i_rn_sel ),
|
.i_rn_sel ( i_rn_sel ),
|
.i_pc_wen ( pc_wen ),
|
.i_pc_wen ( pc_wen ),
|
.i_reg_bank_wen ( reg_bank_wen ),
|
.i_reg_bank_wen ( reg_bank_wen ),
|
.i_pc ( pc_nxt[25:2] ),
|
.i_pc ( pc_nxt[25:2] ),
|
.i_reg ( reg_write_nxt ),
|
.i_reg ( reg_write_nxt ),
|
.i_mode_idec ( i_status_bits_mode ),
|
.i_mode_idec ( i_status_bits_mode ),
|
.i_mode_exec ( status_bits_mode ),
|
.i_mode_exec ( status_bits_mode ),
|
|
|
.i_wb_read_data ( read_data_filtered ),
|
.i_wb_read_data ( read_data_filtered ),
|
.i_wb_read_data_valid ( i_wb_read_data_valid ),
|
.i_wb_read_data_valid ( i_wb_read_data_valid ),
|
.i_wb_read_data_rd ( i_wb_load_rd[3:0] ),
|
.i_wb_read_data_rd ( i_wb_load_rd[3:0] ),
|
.i_wb_mode ( i_wb_load_rd[6:5] ),
|
.i_wb_mode ( i_wb_load_rd[6:5] ),
|
|
|
.i_status_bits_flags ( status_bits_flags ),
|
.i_status_bits_flags ( status_bits_flags ),
|
.i_status_bits_irq_mask ( status_bits_irq_mask ),
|
.i_status_bits_irq_mask ( status_bits_irq_mask ),
|
.i_status_bits_firq_mask ( status_bits_firq_mask ),
|
.i_status_bits_firq_mask ( status_bits_firq_mask ),
|
|
|
// pre-encoded in decode stage to speed up long path
|
// pre-encoded in decode stage to speed up long path
|
.i_firq_not_user_mode ( i_firq_not_user_mode ),
|
.i_firq_not_user_mode ( i_firq_not_user_mode ),
|
|
|
// use one-hot version for speed, combine with i_user_mode_regs_store
|
// 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_rm ( reg_bank_rm ),
|
.o_rs ( reg_bank_rs ),
|
.o_rs ( reg_bank_rs ),
|
.o_rd ( reg_bank_rd ),
|
.o_rd ( reg_bank_rd ),
|
.o_rn ( reg_bank_rn ),
|
.o_rn ( reg_bank_rn ),
|
.o_pc ( pc )
|
.o_pc ( pc )
|
);
|
);
|
|
|
|
|
|
|
// ========================================================
|
// ========================================================
|
// Debug - non-synthesizable code
|
// Debug - non-synthesizable code
|
// ========================================================
|
// ========================================================
|
//synopsys translate_off
|
//synopsys translate_off
|
|
|
wire [(2*8)-1:0] xCONDITION;
|
wire [(2*8)-1:0] xCONDITION;
|
wire [(4*8)-1:0] xMODE;
|
wire [(4*8)-1:0] xMODE;
|
|
|
assign xCONDITION = i_condition == EQ ? "EQ" :
|
assign xCONDITION = i_condition == EQ ? "EQ" :
|
i_condition == NE ? "NE" :
|
i_condition == NE ? "NE" :
|
i_condition == CS ? "CS" :
|
i_condition == CS ? "CS" :
|
i_condition == CC ? "CC" :
|
i_condition == CC ? "CC" :
|
i_condition == MI ? "MI" :
|
i_condition == MI ? "MI" :
|
i_condition == PL ? "PL" :
|
i_condition == PL ? "PL" :
|
i_condition == VS ? "VS" :
|
i_condition == VS ? "VS" :
|
i_condition == VC ? "VC" :
|
i_condition == VC ? "VC" :
|
i_condition == HI ? "HI" :
|
i_condition == HI ? "HI" :
|
i_condition == LS ? "LS" :
|
i_condition == LS ? "LS" :
|
i_condition == GE ? "GE" :
|
i_condition == GE ? "GE" :
|
i_condition == LT ? "LT" :
|
i_condition == LT ? "LT" :
|
i_condition == GT ? "GT" :
|
i_condition == GT ? "GT" :
|
i_condition == LE ? "LE" :
|
i_condition == LE ? "LE" :
|
i_condition == AL ? "AL" :
|
i_condition == AL ? "AL" :
|
"NV " ;
|
"NV " ;
|
|
|
assign xMODE = status_bits_mode == SVC ? "SVC" :
|
assign xMODE = status_bits_mode == SVC ? "SVC" :
|
status_bits_mode == IRQ ? "IRQ" :
|
status_bits_mode == IRQ ? "IRQ" :
|
status_bits_mode == FIRQ ? "FIRQ" :
|
status_bits_mode == FIRQ ? "FIRQ" :
|
status_bits_mode == USR ? "USR" :
|
status_bits_mode == USR ? "USR" :
|
"XXX" ;
|
"XXX" ;
|
|
|
|
|
//synopsys translate_on
|
//synopsys translate_on
|
|
|
endmodule
|
endmodule
|
|
|
|
|
|
|