mirror of
https://github.com/lowRISC/ibex.git
synced 2025-04-22 04:47:25 -04:00
Merge remote-tracking branch 'origin/master' into exc_ctrl
This commit is contained in:
commit
c7cec664ac
11 changed files with 432 additions and 301 deletions
4
alu.sv
4
alu.sv
|
@ -327,11 +327,11 @@ module riscv_alu
|
|||
`ALU_XOR: result_o = operand_a_i ^ operand_b_i;
|
||||
|
||||
// Shift Operations
|
||||
`ALU_SLL: result_o = shift_left_result;
|
||||
`ALU_SLL: result_o = shift_left_result;
|
||||
|
||||
`ALU_SRL,
|
||||
`ALU_SRA,
|
||||
`ALU_ROR: result_o = shift_result;
|
||||
`ALU_ROR: result_o = shift_result;
|
||||
|
||||
// Extension Operations
|
||||
`ALU_EXTBZ,
|
||||
|
|
|
@ -44,7 +44,7 @@ module riscv_compressed_decoder
|
|||
always_comb
|
||||
begin
|
||||
illegal_instr_o = 1'b0;
|
||||
instr_o = 'X;
|
||||
instr_o = 'x;
|
||||
|
||||
unique case (instr_i[1:0])
|
||||
// C0
|
||||
|
@ -126,30 +126,34 @@ module riscv_compressed_decoder
|
|||
|
||||
2'b11: begin
|
||||
unique case ({instr_i[12], instr_i[6:5]})
|
||||
3'b001,
|
||||
3'b000: begin
|
||||
// c.sub -> sub rd', rd', rs2'
|
||||
instr_o = {2'b01, 5'b0, 2'b01, instr_i[4:2], 2'b01, instr_i[9:7], 3'b000, 2'b01, instr_i[9:7], `OPCODE_OP};
|
||||
end
|
||||
|
||||
3'b001: begin
|
||||
// c.xor -> xor rd', rd', rs2'
|
||||
instr_o = {7'b0, 2'b01, instr_i[4:2], 2'b01, instr_i[9:7], 3'b100, 2'b01, instr_i[9:7], `OPCODE_OP};
|
||||
end
|
||||
|
||||
3'b010: begin
|
||||
// c.or -> or rd', rd', rs2'
|
||||
instr_o = {7'b0, 2'b01, instr_i[4:2], 2'b01, instr_i[9:7], 3'b110, 2'b01, instr_i[9:7], `OPCODE_OP};
|
||||
end
|
||||
|
||||
3'b011: begin
|
||||
// c.and -> and rd', rd', rs2'
|
||||
instr_o = {7'b0, 2'b01, instr_i[4:2], 2'b01, instr_i[9:7], 3'b111, 2'b01, instr_i[9:7], `OPCODE_OP};
|
||||
end
|
||||
|
||||
3'b100,
|
||||
3'b101,
|
||||
3'b110,
|
||||
3'b111: begin
|
||||
// 001: c.sll -> sll rd', rd', rs2'
|
||||
// 100: c.xor -> xor rd', rd', rs2'
|
||||
// 101: c.srl -> srl rd', rd', rs2'
|
||||
// 110: c.or -> or rd', rd', rs2'
|
||||
// 111: c.and -> and rd', rd', rs2'
|
||||
instr_o = {7'b0, 2'b01, instr_i[4:2], 2'b01, instr_i[9:7], instr_i[12], instr_i[6:5], 2'b01, instr_i[9:7], `OPCODE_OP};
|
||||
end
|
||||
|
||||
3'b000,
|
||||
3'b010: begin
|
||||
// 000: c.addw
|
||||
// 010: c.subw
|
||||
// 100: c.subw
|
||||
// 101: c.addw
|
||||
illegal_instr_o = 1'b1;
|
||||
end
|
||||
|
||||
3'b011: begin
|
||||
// c.sub -> sub rd', rd', rs2'
|
||||
instr_o = {2'b01, 5'b0, 2'b01, instr_i[4:2], 2'b01, instr_i[9:7], 3'b000, 2'b01, instr_i[9:7], `OPCODE_OP};
|
||||
end
|
||||
endcase
|
||||
end
|
||||
endcase
|
||||
|
|
|
@ -127,7 +127,7 @@ module riscv_controller
|
|||
enum logic [3:0] { RESET, BOOT_SET, SLEEP, FIRST_FETCH,
|
||||
DECODE, BRANCH_DELAY,
|
||||
FLUSH_EX, FLUSH_WB,
|
||||
DBG_SIGNAL, DBG_WAIT } ctrl_fsm_cs, ctrl_fsm_ns;
|
||||
DBG_WAIT_BRANCH, DBG_SIGNAL, DBG_WAIT } ctrl_fsm_cs, ctrl_fsm_ns;
|
||||
|
||||
logic reg_d_ex_is_reg_a_id;
|
||||
logic reg_d_ex_is_reg_b_id;
|
||||
|
@ -319,17 +319,19 @@ module riscv_controller
|
|||
|
||||
// take care of debug
|
||||
// branch conditional will be handled in next state
|
||||
if(trap_hit_i && jump_in_dec_i != `BRANCH_COND)
|
||||
if (trap_hit_i)
|
||||
begin
|
||||
// halt pipeline immediately
|
||||
halt_if_o = 1'b1;
|
||||
halt_id_o = 1'b1;
|
||||
|
||||
// TODO: take a second look at this
|
||||
// make sure the current instruction has been executed
|
||||
// before changing state to non-decode
|
||||
//if (~stall_ex_o)
|
||||
ctrl_fsm_ns = DBG_SIGNAL;
|
||||
if (id_valid_i) begin
|
||||
if (jump_in_id_i == `BRANCH_COND)
|
||||
ctrl_fsm_ns = DBG_WAIT_BRANCH;
|
||||
else
|
||||
ctrl_fsm_ns = DBG_SIGNAL;
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
|
@ -367,13 +369,26 @@ module riscv_controller
|
|||
ctrl_fsm_ns = DECODE;
|
||||
end
|
||||
|
||||
// a branch was in ID when a debug trap is hit
|
||||
DBG_WAIT_BRANCH:
|
||||
begin
|
||||
halt_if_o = 1'b1;
|
||||
|
||||
if (branch_decision_i) begin
|
||||
// there is a branch in the EX stage that is taken
|
||||
pc_mux_sel_o = `PC_BRANCH;
|
||||
pc_set_o = 1'b1;
|
||||
end
|
||||
|
||||
ctrl_fsm_ns = DBG_SIGNAL;
|
||||
end
|
||||
|
||||
// now we can signal to the debugger that our pipeline is empty and it
|
||||
// can examine our current state
|
||||
DBG_SIGNAL:
|
||||
begin
|
||||
dbg_trap_o = 1'b1;
|
||||
halt_if_o = 1'b1;
|
||||
halt_id_o = 1'b1;
|
||||
|
||||
ctrl_fsm_ns = DBG_WAIT;
|
||||
end
|
||||
|
@ -383,19 +398,15 @@ module riscv_controller
|
|||
DBG_WAIT:
|
||||
begin
|
||||
halt_if_o = 1'b1;
|
||||
halt_id_o = 1'b1;
|
||||
|
||||
if(dbg_set_npc_i == 1'b1) begin
|
||||
halt_id_o = 1'b0;
|
||||
pc_mux_sel_o = `PC_DBG_NPC;
|
||||
pc_set_o = 1'b1;
|
||||
ctrl_fsm_ns = DBG_WAIT;
|
||||
end
|
||||
|
||||
if(dbg_stall_i == 1'b0) begin
|
||||
halt_if_o = 1'b0;
|
||||
halt_id_o = 1'b0;
|
||||
ctrl_fsm_ns = DECODE;
|
||||
ctrl_fsm_ns = BRANCH_DELAY;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -403,7 +414,6 @@ module riscv_controller
|
|||
FLUSH_EX:
|
||||
begin
|
||||
halt_if_o = 1'b1;
|
||||
halt_id_o = 1'b1;
|
||||
|
||||
if(ex_valid_i)
|
||||
ctrl_fsm_ns = FLUSH_WB;
|
||||
|
@ -413,7 +423,6 @@ module riscv_controller
|
|||
FLUSH_WB:
|
||||
begin
|
||||
halt_if_o = 1'b1;
|
||||
halt_id_o = 1'b1;
|
||||
|
||||
if (~fetch_enable_i) begin
|
||||
// we are requested to go to sleep
|
||||
|
@ -422,7 +431,6 @@ module riscv_controller
|
|||
end else begin
|
||||
// unstall pipeline and continue operation
|
||||
halt_if_o = 1'b0;
|
||||
halt_id_o = 1'b0;
|
||||
|
||||
if (id_valid_i)
|
||||
ctrl_fsm_ns = DECODE;
|
||||
|
|
|
@ -31,17 +31,18 @@ module riscv_cs_registers
|
|||
)
|
||||
(
|
||||
// Clock and Reset
|
||||
input logic clk,
|
||||
input logic rst_n,
|
||||
input logic clk,
|
||||
input logic rst_n,
|
||||
|
||||
// Core and Cluster ID
|
||||
input logic [4:0] core_id_i,
|
||||
input logic [4:0] cluster_id_i,
|
||||
input logic [4:0] core_id_i,
|
||||
input logic [4:0] cluster_id_i,
|
||||
|
||||
// Interface to registers (SRAM like)
|
||||
input logic [11:0] csr_addr_i,
|
||||
input logic [31:0] csr_wdata_i,
|
||||
input logic [1:0] csr_op_i,
|
||||
input logic csr_access_i,
|
||||
input logic [11:0] csr_addr_i,
|
||||
input logic [31:0] csr_wdata_i,
|
||||
input logic [1:0] csr_op_i,
|
||||
output logic [31:0] csr_rdata_o,
|
||||
|
||||
// Interrupts
|
||||
|
@ -270,29 +271,32 @@ module riscv_cs_registers
|
|||
pccr_index = '0;
|
||||
perf_rdata = '0;
|
||||
|
||||
unique case (csr_addr_i)
|
||||
12'h7A0: begin
|
||||
is_pcer = 1'b1;
|
||||
perf_rdata[N_PERF_COUNTERS-1:0] = PCER_q;
|
||||
end
|
||||
12'h7A1: begin
|
||||
is_pcmr = 1'b1;
|
||||
perf_rdata[1:0] = PCMR_q;
|
||||
end
|
||||
12'h79F: begin
|
||||
is_pccr = 1'b1;
|
||||
pccr_all_sel = 1'b1;
|
||||
end
|
||||
default:;
|
||||
endcase
|
||||
// only perform csr access if we actually care about the read data
|
||||
if (csr_access_i) begin
|
||||
unique case (csr_addr_i)
|
||||
12'h7A0: begin
|
||||
is_pcer = 1'b1;
|
||||
perf_rdata[N_PERF_COUNTERS-1:0] = PCER_q;
|
||||
end
|
||||
12'h7A1: begin
|
||||
is_pcmr = 1'b1;
|
||||
perf_rdata[1:0] = PCMR_q;
|
||||
end
|
||||
12'h79F: begin
|
||||
is_pccr = 1'b1;
|
||||
pccr_all_sel = 1'b1;
|
||||
end
|
||||
default:;
|
||||
endcase
|
||||
|
||||
// look for 780 to 79F, Performance Counter Counter Registers
|
||||
if (csr_addr_i[11:5] == 7'b0111100) begin
|
||||
is_pccr = 1'b1;
|
||||
// look for 780 to 79F, Performance Counter Counter Registers
|
||||
if (csr_addr_i[11:5] == 7'b0111100) begin
|
||||
is_pccr = 1'b1;
|
||||
|
||||
pccr_index = csr_addr_i[4:0];
|
||||
pccr_index = csr_addr_i[4:0];
|
||||
|
||||
perf_rdata = PCCR_q[csr_addr_i[4:0]];
|
||||
perf_rdata = PCCR_q[csr_addr_i[4:0]];
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
164
debug_unit.sv
164
debug_unit.sv
|
@ -5,15 +5,16 @@
|
|||
// //
|
||||
// Additional contributions by: //
|
||||
// Andreas Traber - atraber@student.ethz.ch //
|
||||
// Sven Stucki - svstucki@student.ethz.ch //
|
||||
// //
|
||||
// //
|
||||
// Create Date: 11/07/2014 //
|
||||
// Design Name: Pipelined OpenRISC Processor //
|
||||
// Design Name: RISC-V processor core //
|
||||
// Module Name: debug_unit.sv //
|
||||
// Project Name: OR10N //
|
||||
// Project Name: RI5CY //
|
||||
// Language: SystemVerilog //
|
||||
// //
|
||||
// Description: Debug Controller for the pipelined processor //
|
||||
// Description: Debug controller //
|
||||
// //
|
||||
// //
|
||||
// Revision: //
|
||||
|
@ -22,9 +23,6 @@
|
|||
// changed port and signal names //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
@ -32,59 +30,68 @@
|
|||
|
||||
module riscv_debug_unit
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst_n,
|
||||
input logic clk,
|
||||
input logic rst_n,
|
||||
|
||||
// signals to Debug Interface
|
||||
input logic dbginf_stall_i,
|
||||
output logic dbginf_bp_o,
|
||||
input logic dbginf_strobe_i,
|
||||
output logic dbginf_ack_o,
|
||||
input logic dbginf_we_i,
|
||||
input logic [15:0] dbginf_addr_i,
|
||||
input logic [31:0] dbginf_data_i,
|
||||
output logic [31:0] dbginf_data_o,
|
||||
input logic dbginf_stall_i,
|
||||
output logic dbginf_bp_o,
|
||||
input logic dbginf_strobe_i,
|
||||
output logic dbginf_ack_o,
|
||||
input logic dbginf_we_i,
|
||||
input logic [15:0] dbginf_addr_i,
|
||||
input logic [31:0] dbginf_data_i,
|
||||
output logic [31:0] dbginf_data_o,
|
||||
|
||||
// signals to core
|
||||
output logic dbg_st_en_o, // Single-step trace mode enabled
|
||||
output logic [1:0] dbg_dsr_o, // debug stop register
|
||||
output logic dbg_st_en_o, // Single-step trace mode enabled
|
||||
output logic [1:0] dbg_dsr_o, // debug stop register
|
||||
|
||||
output logic stall_core_o,
|
||||
output logic flush_pipe_o,
|
||||
input logic trap_i,
|
||||
output logic stall_core_o,
|
||||
output logic flush_pipe_o,
|
||||
input logic trap_i,
|
||||
|
||||
output logic sp_mux_o,
|
||||
output logic regfile_mux_o,
|
||||
output logic regfile_we_o,
|
||||
output logic [11:0] regfile_addr_o,
|
||||
output logic [31:0] regfile_wdata_o,
|
||||
input logic [31:0] regfile_rdata_i,
|
||||
output logic sp_mux_o,
|
||||
output logic regfile_mux_o,
|
||||
output logic regfile_we_o,
|
||||
output logic [11:0] regfile_addr_o,
|
||||
output logic [31:0] regfile_wdata_o,
|
||||
input logic [31:0] regfile_rdata_i,
|
||||
|
||||
// Signals for PPC & NPC register
|
||||
input logic [31:0] curr_pc_if_i,
|
||||
input logic [31:0] curr_pc_id_i,
|
||||
input logic [31:0] curr_pc_if_i,
|
||||
input logic [31:0] curr_pc_id_i,
|
||||
input logic [31:0] branch_pc_i,
|
||||
|
||||
input logic [1:0] jump_in_ex_i,
|
||||
input logic branch_taken_i,
|
||||
|
||||
output logic [31:0] npc_o,
|
||||
output logic set_npc_o
|
||||
);
|
||||
|
||||
);
|
||||
|
||||
// registers for debug control
|
||||
logic [1:0] DSR_DP, DSR_DN; // Debug Stop Register: IIE, INTE
|
||||
logic [1:0] DMR1_DP, DMR1_DN; // only single step trace and branch trace bits
|
||||
logic [1:0] DSR_DP, DSR_DN; // Debug Stop Register: IIE, INTE
|
||||
logic [1:0] DMR1_DP, DMR1_DN; // only single step trace and branch trace bits
|
||||
|
||||
// BP control FSM
|
||||
enum logic [2:0] {Idle, Trap, DebugStall, StallCore} BP_State_SN, BP_State_SP;
|
||||
enum logic [2:0] {Idle, Trap, DebugStall, StallCore} BP_State_SN, BP_State_SP;
|
||||
|
||||
// ppc/npc tracking
|
||||
enum logic [1:0] {IFID, IFEX, IDEX} pc_tracking_fsm_cs, pc_tracking_fsm_ns;
|
||||
logic [31:0] ppc_int, npc_int;
|
||||
|
||||
// ack to debug interface
|
||||
assign dbginf_ack_o = dbginf_strobe_i && ((BP_State_SP == StallCore) || (dbginf_addr_i[15:11] == 5'b00110));
|
||||
|
||||
|
||||
always_comb
|
||||
begin
|
||||
BP_State_SN = BP_State_SP;
|
||||
stall_core_o = 1'b0;
|
||||
dbginf_bp_o = 1'b0;
|
||||
flush_pipe_o = 1'b0;
|
||||
BP_State_SN = BP_State_SP;
|
||||
stall_core_o = 1'b0;
|
||||
dbginf_bp_o = 1'b0;
|
||||
flush_pipe_o = 1'b0;
|
||||
|
||||
case (BP_State_SP)
|
||||
Idle:
|
||||
|
@ -152,15 +159,15 @@ module riscv_debug_unit
|
|||
// address decoding, first stage: evaluate higher 5 Bits to detect if debug regs are accessed
|
||||
if(dbginf_addr_i[15:11] == 5'b00110) begin
|
||||
// second stage: evaluate Bits 10:0 to detect which part of debug registers is accessed
|
||||
casex(dbginf_addr_i[10:0])
|
||||
case (dbginf_addr_i[10:0])
|
||||
11'd0: begin // NPC
|
||||
set_npc_o = dbginf_we_i;
|
||||
|
||||
dbginf_data_o = curr_pc_if_i;
|
||||
dbginf_data_o = npc_int;
|
||||
end
|
||||
|
||||
11'd1: begin // PPC
|
||||
dbginf_data_o = curr_pc_id_i;
|
||||
dbginf_data_o = ppc_int;
|
||||
end
|
||||
|
||||
11'd16: begin // SP_DMR1
|
||||
|
@ -169,6 +176,7 @@ module riscv_debug_unit
|
|||
else
|
||||
dbginf_data_o[`DMR1_ST+1:`DMR1_ST] = DMR1_DP;
|
||||
end
|
||||
|
||||
11'd20: begin // SP_DSR
|
||||
// currently we only handle IIE and INTE
|
||||
if(dbginf_we_i == 1'b1)
|
||||
|
@ -176,8 +184,9 @@ module riscv_debug_unit
|
|||
else
|
||||
dbginf_data_o[7:6] = DSR_DP[1:0];
|
||||
end
|
||||
|
||||
default: ;
|
||||
endcase // casex [10:0]
|
||||
endcase
|
||||
end
|
||||
// check if internal registers (GPR or SPR) are accessed
|
||||
else if(BP_State_SP == StallCore)
|
||||
|
@ -196,8 +205,8 @@ module riscv_debug_unit
|
|||
// some other SPR is accessed
|
||||
else
|
||||
begin
|
||||
sp_mux_o = 1'b1;
|
||||
regfile_addr_o = dbginf_addr_i[11:0];
|
||||
sp_mux_o = 1'b1;
|
||||
regfile_addr_o = dbginf_addr_i[11:0];
|
||||
|
||||
if(dbginf_we_i == 1'b1)
|
||||
regfile_we_o = 1'b1;
|
||||
|
@ -208,18 +217,67 @@ module riscv_debug_unit
|
|||
end
|
||||
end
|
||||
|
||||
// normal FF setup
|
||||
always_ff@(posedge clk or negedge rst_n) begin
|
||||
if (~rst_n) begin
|
||||
DMR1_DP <= 2'b0;
|
||||
DSR_DP <= 'b0;
|
||||
BP_State_SP <= Idle;
|
||||
|
||||
always_comb
|
||||
begin
|
||||
pc_tracking_fsm_ns = pc_tracking_fsm_cs;
|
||||
|
||||
ppc_int = curr_pc_id_i;
|
||||
npc_int = curr_pc_if_i;
|
||||
|
||||
// PPC/NPC mux
|
||||
unique case (pc_tracking_fsm_cs)
|
||||
IFID: begin
|
||||
ppc_int = curr_pc_id_i;
|
||||
npc_int = curr_pc_if_i;
|
||||
end
|
||||
|
||||
IFEX: begin
|
||||
ppc_int = branch_pc_i;
|
||||
npc_int = curr_pc_if_i;
|
||||
end
|
||||
|
||||
IDEX: begin
|
||||
ppc_int = branch_pc_i;
|
||||
npc_int = curr_pc_id_i;
|
||||
|
||||
if (set_npc_o)
|
||||
pc_tracking_fsm_ns = IFEX;
|
||||
end
|
||||
|
||||
default: begin
|
||||
pc_tracking_fsm_ns = IFID;
|
||||
end
|
||||
endcase
|
||||
|
||||
// set state if trap is encountered
|
||||
if (stall_core_o && (BP_State_SP != StallCore)) begin
|
||||
pc_tracking_fsm_ns = IFID;
|
||||
|
||||
if (jump_in_ex_i == `BRANCH_COND) begin
|
||||
if (branch_taken_i)
|
||||
pc_tracking_fsm_ns = IFEX;
|
||||
else
|
||||
pc_tracking_fsm_ns = IDEX;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
always_ff@(posedge clk, negedge rst_n)
|
||||
begin
|
||||
if (rst_n == 1'b0) begin
|
||||
DMR1_DP <= 2'b0;
|
||||
DSR_DP <= 'b0;
|
||||
BP_State_SP <= Idle;
|
||||
pc_tracking_fsm_cs <= IFID;
|
||||
end
|
||||
else begin
|
||||
DMR1_DP <= DMR1_DN;
|
||||
DSR_DP <= DSR_DN;
|
||||
BP_State_SP <= BP_State_SN;
|
||||
DMR1_DP <= DMR1_DN;
|
||||
DSR_DP <= DSR_DN;
|
||||
BP_State_SP <= BP_State_SN;
|
||||
pc_tracking_fsm_cs <= pc_tracking_fsm_ns;
|
||||
end
|
||||
end // always_ff@ (posedge clk or negedge rst_n)
|
||||
end
|
||||
|
||||
endmodule // debug_unit
|
||||
|
|
23
decoder.sv
23
decoder.sv
|
@ -81,8 +81,8 @@ module riscv_decoder
|
|||
|
||||
// hwloop signals
|
||||
output logic [2:0] hwloop_we_o, // write enable for hwloop regs
|
||||
output logic hwloop_target_mux_sel_o, // selects immediate for hwloop target
|
||||
output logic hwloop_start_mux_sel_o, // selects hwloop start address input
|
||||
output logic hwloop_end_mux_sel_o, // selects hwloop end address input
|
||||
output logic hwloop_cnt_mux_sel_o, // selects hwloop counter input
|
||||
|
||||
// jump/branches
|
||||
|
@ -144,8 +144,8 @@ module riscv_decoder
|
|||
prepost_useincr_o = 1'b1;
|
||||
|
||||
hwloop_we = 3'b0;
|
||||
hwloop_target_mux_sel_o = 1'b0;
|
||||
hwloop_start_mux_sel_o = 1'b0;
|
||||
hwloop_end_mux_sel_o = 1'b0;
|
||||
hwloop_cnt_mux_sel_o = 1'b0;
|
||||
|
||||
csr_access_o = 1'b0;
|
||||
|
@ -577,7 +577,7 @@ module riscv_decoder
|
|||
///////////////////////////////////////////////
|
||||
|
||||
`OPCODE_HWLOOP: begin
|
||||
jump_target_mux_sel_o = `JT_HWLP; // get PC + I imm from jump target adder
|
||||
hwloop_target_mux_sel_o = 1'b0;
|
||||
|
||||
unique case (instr_rdata_i[14:12])
|
||||
3'b000: begin
|
||||
|
@ -585,31 +585,44 @@ module riscv_decoder
|
|||
hwloop_we[0] = 1'b1;
|
||||
hwloop_start_mux_sel_o = 1'b0;
|
||||
end
|
||||
|
||||
3'b001: begin
|
||||
// lp.endi: set end address to PC + I-type immediate
|
||||
hwloop_we[1] = 1'b1;
|
||||
hwloop_end_mux_sel_o = 1'b0; // jump target
|
||||
end
|
||||
|
||||
3'b010: begin
|
||||
// lp.count: initialize counter from rs1
|
||||
hwloop_we[2] = 1'b1;
|
||||
hwloop_cnt_mux_sel_o = 1'b1;
|
||||
rega_used_o = 1'b1;
|
||||
end
|
||||
|
||||
3'b011: begin
|
||||
// lp.counti: initialize counter from I-type immediate
|
||||
hwloop_we[2] = 1'b1;
|
||||
hwloop_cnt_mux_sel_o = 1'b0;
|
||||
end
|
||||
|
||||
3'b100: begin
|
||||
// lp.setup: initialize counter from rs1, set start address to
|
||||
// next instruction and end address to PC + I-type immediate
|
||||
hwloop_we = 3'b111;
|
||||
hwloop_start_mux_sel_o = 1'b1;
|
||||
hwloop_end_mux_sel_o = 1'b0;
|
||||
hwloop_cnt_mux_sel_o = 1'b1;
|
||||
rega_used_o = 1'b1;
|
||||
end
|
||||
|
||||
3'b101: begin
|
||||
// lp.setupi: initialize counter from rs1, set start address to
|
||||
// next instruction and end address to PC + I-type immediate
|
||||
hwloop_we = 3'b111;
|
||||
hwloop_target_mux_sel_o = 1'b1;
|
||||
hwloop_start_mux_sel_o = 1'b1;
|
||||
hwloop_cnt_mux_sel_o = 1'b1;
|
||||
rega_used_o = 1'b1;
|
||||
end
|
||||
|
||||
default: begin
|
||||
illegal_insn_o = 1'b1;
|
||||
end
|
||||
|
|
52
id_stage.sv
52
id_stage.sv
|
@ -38,7 +38,9 @@ module riscv_id_stage
|
|||
input logic clk,
|
||||
input logic rst_n,
|
||||
|
||||
input logic fetch_enable_i,
|
||||
input logic test_en_i,
|
||||
|
||||
input logic fetch_enable_i,
|
||||
output logic core_busy_o,
|
||||
output logic is_decoding_o,
|
||||
|
||||
|
@ -81,7 +83,9 @@ module riscv_id_stage
|
|||
input logic ex_valid_i, // EX stage is done
|
||||
input logic wb_valid_i, // WB stage is done
|
||||
|
||||
// To the Pipeline ID/EX
|
||||
// Pipeline ID/EX
|
||||
output logic [31:0] branch_pc_ex_o,
|
||||
|
||||
output logic [31:0] alu_operand_a_ex_o,
|
||||
output logic [31:0] alu_operand_b_ex_o,
|
||||
output logic [31:0] alu_operand_c_ex_o,
|
||||
|
@ -253,10 +257,11 @@ module riscv_id_stage
|
|||
logic [1:0] hwloop_regid;
|
||||
logic [2:0] hwloop_we;
|
||||
logic hwloop_jump;
|
||||
logic hwloop_target_mux_sel;
|
||||
logic hwloop_start_mux_sel;
|
||||
logic hwloop_end_mux_sel;
|
||||
logic hwloop_cnt_mux_sel;
|
||||
|
||||
logic [31:0] hwloop_target;
|
||||
logic [31:0] hwloop_start;
|
||||
logic [31:0] hwloop_end;
|
||||
logic [31:0] hwloop_cnt;
|
||||
|
@ -332,23 +337,26 @@ module riscv_id_stage
|
|||
// hwloop register id
|
||||
assign hwloop_regid = instr[8:7]; // rd contains hwloop register id
|
||||
|
||||
// hwloop target mux
|
||||
always_comb
|
||||
begin
|
||||
unique case (hwloop_target_mux_sel)
|
||||
1'b0: hwloop_target = current_pc_id_i + imm_i_type;
|
||||
1'b1: hwloop_target = current_pc_id_i + {imm_z_type[30:0], 1'b0};
|
||||
endcase
|
||||
end
|
||||
|
||||
// hwloop start mux
|
||||
always_comb
|
||||
begin
|
||||
unique case (hwloop_start_mux_sel)
|
||||
1'b0: hwloop_start = jump_target; // for PC + I imm
|
||||
1'b0: hwloop_start = hwloop_target; // for PC + I imm
|
||||
1'b1: hwloop_start = current_pc_if_i; // for next PC
|
||||
endcase
|
||||
end
|
||||
|
||||
// hwloop end mux
|
||||
always_comb
|
||||
begin
|
||||
unique case (hwloop_end_mux_sel)
|
||||
1'b0: hwloop_end = jump_target; // for PC + I imm
|
||||
1'b1: hwloop_end = jump_target; // TODO: PC + (Z imm << 1) for lp.setupi
|
||||
endcase
|
||||
end
|
||||
assign hwloop_end = hwloop_target;
|
||||
|
||||
// hwloop cnt mux
|
||||
always_comb
|
||||
|
@ -373,9 +381,11 @@ module riscv_id_stage
|
|||
begin : jump_target_mux
|
||||
unique case (jump_target_mux_sel)
|
||||
`JT_JAL: jump_target = current_pc_id_i + imm_uj_type;
|
||||
`JT_JALR: jump_target = regfile_data_ra_id + imm_i_type; // cannot forward rs1 as path is too long
|
||||
`JT_COND: jump_target = current_pc_id_i + imm_sb_type;
|
||||
`JT_HWLP: jump_target = current_pc_id_i + imm_i_type;
|
||||
|
||||
// JALR: Cannot forward RS1, since the path is too long
|
||||
`JT_JALR: jump_target = regfile_data_ra_id + imm_i_type;
|
||||
default: jump_target = regfile_data_ra_id + imm_i_type;
|
||||
endcase
|
||||
end
|
||||
|
||||
|
@ -503,6 +513,8 @@ module riscv_id_stage
|
|||
.clk ( clk ),
|
||||
.rst_n ( rst_n ),
|
||||
|
||||
.test_en_i ( test_en_i ),
|
||||
|
||||
// Read port a
|
||||
.raddr_a_i ( regfile_addr_ra_id ),
|
||||
.rdata_a_o ( regfile_data_ra_id ),
|
||||
|
@ -592,8 +604,8 @@ module riscv_id_stage
|
|||
|
||||
// hwloop signals
|
||||
.hwloop_we_o ( hwloop_we ),
|
||||
.hwloop_target_mux_sel_o ( hwloop_target_mux_sel ),
|
||||
.hwloop_start_mux_sel_o ( hwloop_start_mux_sel ),
|
||||
.hwloop_end_mux_sel_o ( hwloop_end_mux_sel ),
|
||||
.hwloop_cnt_mux_sel_o ( hwloop_cnt_mux_sel ),
|
||||
|
||||
// jump/branches
|
||||
|
@ -804,6 +816,18 @@ module riscv_id_stage
|
|||
// |___|____/ |_____/_/\_\ |_| |___|_| |_____|_____|___|_| \_|_____| //
|
||||
// //
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
always_ff @(posedge clk, negedge rst_n)
|
||||
begin
|
||||
if (rst_n == 1'b0)
|
||||
begin
|
||||
branch_pc_ex_o <= '0;
|
||||
end
|
||||
else begin
|
||||
if (jump_in_id_o == `BRANCH_COND && id_valid_o)
|
||||
branch_pc_ex_o <= current_pc_id_i;
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge clk, negedge rst_n)
|
||||
begin : ID_EX_PIPE_REGISTERS
|
||||
if (rst_n == 1'b0)
|
||||
|
|
|
@ -85,6 +85,7 @@ module riscv_if_stage
|
|||
|
||||
// from debug unit
|
||||
input logic [31:0] dbg_npc_i,
|
||||
input logic dbg_set_npc_i,
|
||||
|
||||
// pipeline stall
|
||||
input logic halt_if_i,
|
||||
|
@ -353,7 +354,7 @@ module riscv_if_stage
|
|||
|
||||
// take care of jumps and branches
|
||||
// only send one branch request per jump/branch
|
||||
if (branch_req_Q == 1'b0) begin
|
||||
if (dbg_set_npc_i || (branch_req_Q == 1'b0)) begin
|
||||
if (pc_set_i) begin
|
||||
valid = 1'b0;
|
||||
|
||||
|
|
|
@ -56,10 +56,10 @@
|
|||
`define OPCODE_CUST1 7'h2b
|
||||
|
||||
// PULP custom
|
||||
`define OPCODE_STORE_POST 7'h27
|
||||
`define OPCODE_LOAD_POST 7'h07
|
||||
`define OPCODE_HWLOOP 7'h6b
|
||||
`define OPCODE_PULP_OP 7'h57
|
||||
`define OPCODE_LOAD_POST 7'h0b
|
||||
`define OPCODE_STORE_POST 7'h2b
|
||||
`define OPCODE_PULP_OP 7'h5b
|
||||
`define OPCODE_HWLOOP 7'h7b
|
||||
|
||||
|
||||
// instruction masks (for tracer)
|
||||
|
@ -280,7 +280,6 @@
|
|||
`define BRANCH_COND 2'b11 // conditional branches
|
||||
|
||||
// jump target mux
|
||||
`define JT_HWLP 2'b00
|
||||
`define JT_JAL 2'b01
|
||||
`define JT_JALR 2'b10
|
||||
`define JT_COND 2'b11
|
||||
|
|
310
register_file.sv
310
register_file.sv
|
@ -1,154 +1,156 @@
|
|||
module riscv_register_file
|
||||
#(
|
||||
parameter ADDR_WIDTH = 5,
|
||||
parameter DATA_WIDTH = 32
|
||||
)
|
||||
(
|
||||
// Clock and Reset
|
||||
input logic clk,
|
||||
input logic rst_n,
|
||||
|
||||
//Read port R1
|
||||
input logic [ADDR_WIDTH-1:0] raddr_a_i,
|
||||
output logic [DATA_WIDTH-1:0] rdata_a_o,
|
||||
|
||||
//Read port R2
|
||||
input logic [ADDR_WIDTH-1:0] raddr_b_i,
|
||||
output logic [DATA_WIDTH-1:0] rdata_b_o,
|
||||
|
||||
//Read port R3
|
||||
input logic [ADDR_WIDTH-1:0] raddr_c_i,
|
||||
output logic [DATA_WIDTH-1:0] rdata_c_o,
|
||||
|
||||
// Write port W1
|
||||
input logic [ADDR_WIDTH-1:0] waddr_a_i,
|
||||
input logic [DATA_WIDTH-1:0] wdata_a_i,
|
||||
input logic we_a_i,
|
||||
|
||||
// Write port W2
|
||||
input logic [ADDR_WIDTH-1:0] waddr_b_i,
|
||||
input logic [DATA_WIDTH-1:0] wdata_b_i,
|
||||
input logic we_b_i
|
||||
);
|
||||
|
||||
localparam NUM_WORDS = 2**ADDR_WIDTH;
|
||||
|
||||
logic [DATA_WIDTH-1:0] MemContentxDP[NUM_WORDS];
|
||||
|
||||
logic [NUM_WORDS-1:1] WAddrOneHotxDa;
|
||||
logic [NUM_WORDS-1:1] WAddrOneHotxDb;
|
||||
logic [NUM_WORDS-1:1] WAddrOneHotxDb_reg;
|
||||
|
||||
logic [NUM_WORDS-1:1] ClocksxC;
|
||||
logic [DATA_WIDTH-1:0] WDataIntxDa;
|
||||
logic [DATA_WIDTH-1:0] WDataIntxDb;
|
||||
|
||||
logic clk_int;
|
||||
|
||||
logic we_int;
|
||||
|
||||
int unsigned i;
|
||||
int unsigned j;
|
||||
int unsigned k;
|
||||
|
||||
genvar x;
|
||||
genvar y;
|
||||
|
||||
assign we_int = we_a_i | we_b_i;
|
||||
|
||||
cluster_clock_gating CG_WE_GLOBAL
|
||||
(
|
||||
.clk_o(clk_int),
|
||||
.en_i(we_int),
|
||||
.test_en_i(1'b0),
|
||||
.clk_i(clk)
|
||||
);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-- READ : Read address decoder RAD
|
||||
//-----------------------------------------------------------------------------
|
||||
assign rdata_a_o = MemContentxDP[raddr_a_i];
|
||||
assign rdata_b_o = MemContentxDP[raddr_b_i];
|
||||
assign rdata_c_o = MemContentxDP[raddr_c_i];
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-- WRITE : Write Address Decoder (WAD), combinatorial process
|
||||
//-----------------------------------------------------------------------------
|
||||
always_comb
|
||||
begin : p_WADa
|
||||
for(i=1; i<NUM_WORDS; i++)
|
||||
begin : p_WordItera
|
||||
if ( (we_a_i == 1'b1 ) && (waddr_a_i == i) )
|
||||
WAddrOneHotxDa[i] = 1'b1;
|
||||
else
|
||||
WAddrOneHotxDa[i] = 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
always_comb
|
||||
begin : p_WADb
|
||||
for(j=1; j<NUM_WORDS; j++)
|
||||
begin : p_WordIterb
|
||||
if ( (we_b_i == 1'b1 ) && (waddr_b_i == j) )
|
||||
WAddrOneHotxDb[j] = 1'b1;
|
||||
else
|
||||
WAddrOneHotxDb[j] = 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge clk_int)
|
||||
begin
|
||||
if(we_a_i | we_b_i)
|
||||
WAddrOneHotxDb_reg <= WAddrOneHotxDb;
|
||||
end
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-- WRITE : Clock gating (if integrated clock-gating cells are available)
|
||||
//-----------------------------------------------------------------------------
|
||||
generate
|
||||
for(x=1; x<NUM_WORDS; x++)
|
||||
begin : CG_CELL_WORD_ITER
|
||||
cluster_clock_gating CG_Inst
|
||||
(
|
||||
.clk_o(ClocksxC[x]),
|
||||
.en_i(WAddrOneHotxDa[x] | WAddrOneHotxDb[x]),
|
||||
.test_en_i(1'b0),
|
||||
.clk_i(clk_int)
|
||||
);
|
||||
end
|
||||
endgenerate
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// WRITE : SAMPLE INPUT DATA
|
||||
//---------------------------------------------------------------------------
|
||||
always_ff @(posedge clk)
|
||||
begin : sample_waddr
|
||||
if(we_a_i)
|
||||
WDataIntxDa <= wdata_a_i;
|
||||
if(we_b_i)
|
||||
WDataIntxDb <= wdata_b_i;
|
||||
end
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-- WRITE : Write operation
|
||||
//-----------------------------------------------------------------------------
|
||||
//-- Generate M = WORDS sequential processes, each of which describes one
|
||||
//-- word of the memory. The processes are synchronized with the clocks
|
||||
//-- ClocksxC(i), i = 0, 1, ..., M-1
|
||||
//-- Use active low, i.e. transparent on low latches as storage elements
|
||||
//-- Data is sampled on rising clock edge
|
||||
|
||||
always_latch
|
||||
begin : latch_wdata
|
||||
// Note: The assignment has to be done inside this process or Modelsim complains about it
|
||||
MemContentxDP[0] = 32'b0;
|
||||
|
||||
for(k=1; k<NUM_WORDS; k++)
|
||||
begin : w_WordIter
|
||||
if(ClocksxC[k] == 1'b1)
|
||||
MemContentxDP[k] = WAddrOneHotxDb_reg[k] ? WDataIntxDb : WDataIntxDa;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
endmodule
|
||||
module riscv_register_file
|
||||
#(
|
||||
parameter ADDR_WIDTH = 5,
|
||||
parameter DATA_WIDTH = 32
|
||||
)
|
||||
(
|
||||
// Clock and Reset
|
||||
input logic clk,
|
||||
input logic rst_n,
|
||||
|
||||
input logic test_en_i,
|
||||
|
||||
//Read port R1
|
||||
input logic [ADDR_WIDTH-1:0] raddr_a_i,
|
||||
output logic [DATA_WIDTH-1:0] rdata_a_o,
|
||||
|
||||
//Read port R2
|
||||
input logic [ADDR_WIDTH-1:0] raddr_b_i,
|
||||
output logic [DATA_WIDTH-1:0] rdata_b_o,
|
||||
|
||||
//Read port R3
|
||||
input logic [ADDR_WIDTH-1:0] raddr_c_i,
|
||||
output logic [DATA_WIDTH-1:0] rdata_c_o,
|
||||
|
||||
// Write port W1
|
||||
input logic [ADDR_WIDTH-1:0] waddr_a_i,
|
||||
input logic [DATA_WIDTH-1:0] wdata_a_i,
|
||||
input logic we_a_i,
|
||||
|
||||
// Write port W2
|
||||
input logic [ADDR_WIDTH-1:0] waddr_b_i,
|
||||
input logic [DATA_WIDTH-1:0] wdata_b_i,
|
||||
input logic we_b_i
|
||||
);
|
||||
|
||||
localparam NUM_WORDS = 2**ADDR_WIDTH;
|
||||
|
||||
logic [DATA_WIDTH-1:0] MemContentxDP[NUM_WORDS];
|
||||
|
||||
logic [NUM_WORDS-1:1] WAddrOneHotxDa;
|
||||
logic [NUM_WORDS-1:1] WAddrOneHotxDb;
|
||||
logic [NUM_WORDS-1:1] WAddrOneHotxDb_reg;
|
||||
|
||||
logic [NUM_WORDS-1:1] ClocksxC;
|
||||
logic [DATA_WIDTH-1:0] WDataIntxDa;
|
||||
logic [DATA_WIDTH-1:0] WDataIntxDb;
|
||||
|
||||
logic clk_int;
|
||||
|
||||
logic we_int;
|
||||
|
||||
int unsigned i;
|
||||
int unsigned j;
|
||||
int unsigned k;
|
||||
|
||||
genvar x;
|
||||
genvar y;
|
||||
|
||||
assign we_int = we_a_i | we_b_i;
|
||||
|
||||
cluster_clock_gating CG_WE_GLOBAL
|
||||
(
|
||||
.clk_i ( clk ),
|
||||
.en_i ( we_int ),
|
||||
.test_en_i ( test_en_i ),
|
||||
.clk_o ( clk_int )
|
||||
);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-- READ : Read address decoder RAD
|
||||
//-----------------------------------------------------------------------------
|
||||
assign rdata_a_o = MemContentxDP[raddr_a_i];
|
||||
assign rdata_b_o = MemContentxDP[raddr_b_i];
|
||||
assign rdata_c_o = MemContentxDP[raddr_c_i];
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-- WRITE : Write Address Decoder (WAD), combinatorial process
|
||||
//-----------------------------------------------------------------------------
|
||||
always_comb
|
||||
begin : p_WADa
|
||||
for(i=1; i<NUM_WORDS; i++)
|
||||
begin : p_WordItera
|
||||
if ( (we_a_i == 1'b1 ) && (waddr_a_i == i) )
|
||||
WAddrOneHotxDa[i] = 1'b1;
|
||||
else
|
||||
WAddrOneHotxDa[i] = 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
always_comb
|
||||
begin : p_WADb
|
||||
for(j=1; j<NUM_WORDS; j++)
|
||||
begin : p_WordIterb
|
||||
if ( (we_b_i == 1'b1 ) && (waddr_b_i == j) )
|
||||
WAddrOneHotxDb[j] = 1'b1;
|
||||
else
|
||||
WAddrOneHotxDb[j] = 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge clk_int)
|
||||
begin
|
||||
if(we_a_i | we_b_i)
|
||||
WAddrOneHotxDb_reg <= WAddrOneHotxDb;
|
||||
end
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-- WRITE : Clock gating (if integrated clock-gating cells are available)
|
||||
//-----------------------------------------------------------------------------
|
||||
generate
|
||||
for(x=1; x<NUM_WORDS; x++)
|
||||
begin : CG_CELL_WORD_ITER
|
||||
cluster_clock_gating CG_Inst
|
||||
(
|
||||
.clk_i ( clk_int ),
|
||||
.en_i ( WAddrOneHotxDa[x] | WAddrOneHotxDb[x] ),
|
||||
.test_en_i ( test_en_i ),
|
||||
.clk_o ( ClocksxC[x] )
|
||||
);
|
||||
end
|
||||
endgenerate
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// WRITE : SAMPLE INPUT DATA
|
||||
//---------------------------------------------------------------------------
|
||||
always_ff @(posedge clk)
|
||||
begin : sample_waddr
|
||||
if(we_a_i)
|
||||
WDataIntxDa <= wdata_a_i;
|
||||
if(we_b_i)
|
||||
WDataIntxDb <= wdata_b_i;
|
||||
end
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-- WRITE : Write operation
|
||||
//-----------------------------------------------------------------------------
|
||||
//-- Generate M = WORDS sequential processes, each of which describes one
|
||||
//-- word of the memory. The processes are synchronized with the clocks
|
||||
//-- ClocksxC(i), i = 0, 1, ..., M-1
|
||||
//-- Use active low, i.e. transparent on low latches as storage elements
|
||||
//-- Data is sampled on rising clock edge
|
||||
|
||||
always_latch
|
||||
begin : latch_wdata
|
||||
// Note: The assignment has to be done inside this process or Modelsim complains about it
|
||||
MemContentxDP[0] = 32'b0;
|
||||
|
||||
for(k=1; k<NUM_WORDS; k++)
|
||||
begin : w_WordIter
|
||||
if(ClocksxC[k] == 1'b1)
|
||||
MemContentxDP[k] = WAddrOneHotxDb_reg[k] ? WDataIntxDb : WDataIntxDa;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
endmodule
|
||||
|
|
|
@ -38,6 +38,8 @@ module riscv_core
|
|||
input logic clk,
|
||||
input logic rst_n,
|
||||
|
||||
input logic test_en_i, // enable all clock gates for testing
|
||||
|
||||
// Core ID, Cluster ID and boot address are considered more or less static
|
||||
input logic [31:0] boot_addr_i,
|
||||
input logic [4:0] core_id_i,
|
||||
|
@ -117,6 +119,8 @@ module riscv_core
|
|||
logic if_busy;
|
||||
|
||||
|
||||
logic [31:0] branch_pc_ex; // PC of last executed branch
|
||||
|
||||
// ALU Control
|
||||
logic [`ALU_OP_WIDTH-1:0] alu_operator_ex;
|
||||
logic [31:0] alu_operand_a_ex;
|
||||
|
@ -148,6 +152,7 @@ module riscv_core
|
|||
logic csr_access_ex;
|
||||
logic [1:0] csr_op_ex;
|
||||
|
||||
logic csr_access;
|
||||
logic [1:0] csr_op;
|
||||
logic [11:0] csr_addr;
|
||||
logic [31:0] csr_rdata;
|
||||
|
@ -276,6 +281,7 @@ module riscv_core
|
|||
|
||||
// from debug unit
|
||||
.dbg_npc_i ( dbg_npc ),
|
||||
.dbg_set_npc_i ( dbg_set_npc ),
|
||||
|
||||
// Jump and branch target and decision
|
||||
.jump_in_id_i ( jump_in_id ),
|
||||
|
@ -308,6 +314,8 @@ module riscv_core
|
|||
.clk ( clk ),
|
||||
.rst_n ( rst_n ),
|
||||
|
||||
.test_en_i ( test_en_i ),
|
||||
|
||||
// Processor Enable
|
||||
.fetch_enable_i ( fetch_enable_i ),
|
||||
.core_busy_o ( core_busy ),
|
||||
|
@ -353,6 +361,7 @@ module riscv_core
|
|||
.wb_valid_i ( wb_valid ),
|
||||
|
||||
// From the Pipeline ID/EX
|
||||
.branch_pc_ex_o ( branch_pc_ex ),
|
||||
.alu_operand_a_ex_o ( alu_operand_a_ex ),
|
||||
.alu_operand_b_ex_o ( alu_operand_b_ex ),
|
||||
.alu_operand_c_ex_o ( alu_operand_c_ex ),
|
||||
|
@ -573,6 +582,7 @@ module riscv_core
|
|||
.cluster_id_i ( cluster_id_i ),
|
||||
|
||||
// Interface to CSRs (SRAM like)
|
||||
.csr_access_i ( csr_access_ex ),
|
||||
.csr_addr_i ( csr_addr ),
|
||||
.csr_wdata_i ( csr_wdata ),
|
||||
.csr_op_i ( csr_op ),
|
||||
|
@ -608,11 +618,13 @@ module riscv_core
|
|||
);
|
||||
|
||||
// Mux for CSR access through Debug Unit
|
||||
assign csr_addr = (dbg_sp_mux == 1'b0) ? alu_operand_b_ex[11:0] : dbg_reg_addr;
|
||||
assign csr_wdata = (dbg_sp_mux == 1'b0) ? alu_operand_a_ex : dbg_reg_wdata;
|
||||
assign csr_op = (dbg_sp_mux == 1'b0) ? csr_op_ex
|
||||
: (dbg_reg_we == 1'b1 ? `CSR_OP_WRITE : `CSR_OP_NONE);
|
||||
assign dbg_rdata = (dbg_sp_mux == 1'b0) ? dbg_reg_rdata : csr_rdata;
|
||||
assign csr_access = (dbg_sp_mux == 1'b0) ? csr_access_ex : 1'b1;
|
||||
assign csr_addr = (dbg_sp_mux == 1'b0) ? alu_operand_b_ex[11:0] : dbg_reg_addr;
|
||||
assign csr_wdata = (dbg_sp_mux == 1'b0) ? alu_operand_a_ex : dbg_reg_wdata;
|
||||
assign csr_op = (dbg_sp_mux == 1'b0) ? csr_op_ex
|
||||
: (dbg_reg_we == 1'b1 ? `CSR_OP_WRITE
|
||||
: `CSR_OP_NONE );
|
||||
assign dbg_rdata = (dbg_sp_mux == 1'b0) ? dbg_reg_rdata : csr_rdata;
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
|
@ -642,13 +654,14 @@ module riscv_core
|
|||
// To/From Core
|
||||
.dbg_st_en_o ( dbg_st_en ),
|
||||
.dbg_dsr_o ( dbg_dsr ),
|
||||
|
||||
.stall_core_o ( dbg_stall ),
|
||||
.flush_pipe_o ( dbg_flush_pipe ),
|
||||
.trap_i ( dbg_trap ),
|
||||
|
||||
// register file access
|
||||
.regfile_mux_o ( dbg_reg_mux ),
|
||||
.sp_mux_o ( dbg_sp_mux ),
|
||||
.regfile_mux_o ( dbg_reg_mux ),
|
||||
.regfile_we_o ( dbg_reg_we ),
|
||||
.regfile_addr_o ( dbg_reg_addr ),
|
||||
.regfile_wdata_o ( dbg_reg_wdata ),
|
||||
|
@ -657,6 +670,11 @@ module riscv_core
|
|||
// signals for PPC and NPC
|
||||
.curr_pc_if_i ( current_pc_if ), // from IF stage
|
||||
.curr_pc_id_i ( current_pc_id ), // from IF stage
|
||||
.branch_pc_i ( branch_pc_ex ), // PC of last executed branch (in EX stage)
|
||||
|
||||
.jump_in_ex_i ( jump_in_ex ),
|
||||
.branch_taken_i ( branch_decision ),
|
||||
|
||||
.npc_o ( dbg_npc ), // PC from debug unit
|
||||
.set_npc_o ( dbg_set_npc ) // set PC to new value
|
||||
);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue