mirror of
https://github.com/lowRISC/ibex.git
synced 2025-04-22 04:47:25 -04:00
Intermediate commit, trying out some things
This commit is contained in:
parent
8e26797549
commit
80ca650893
1 changed files with 247 additions and 132 deletions
379
if_stage.sv
379
if_stage.sv
|
@ -24,8 +24,8 @@
|
|||
// comments //
|
||||
// Revision v0.3 - (December 1th 2014) Merged debug unit and added more //
|
||||
// exceptions //
|
||||
// Revision v0.4 - (July 30th 2015) Removed instr_core_interface, handling //
|
||||
// the cache interface in IF now //
|
||||
// Revision v0.4 - (July 30th 2015) Moved instr_core_interface into IF, //
|
||||
// handling compressed instructions with FSM //
|
||||
// //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -90,18 +90,21 @@ module if_stage
|
|||
logic [31:0] exc_pc; // PC from exception
|
||||
|
||||
|
||||
enum logic [2:0] {IDLE, WAIT_BRANCH, FETCH_STALLED, FETCH_UNSTALLED, WAIT_IF_STALL} CS, NS;
|
||||
//enum logic [2:0] {IDLE, WAIT_BRANCH, FETCH_STALLED, FETCH_UNSTALLED, WAIT_IF_STALL} CS, NS;
|
||||
|
||||
|
||||
// PC generation FSM
|
||||
enum logic [0:0] {REGULAR, HANDLE_BRANCH} CS_PCGEN, NS_PCGEN;
|
||||
|
||||
// instruction cache interface signals
|
||||
//enum logic [1:0] {IDLE, WAIT_GNT, WAIT_RVALID, WAIT_IF_STALL} CS_FETCH, NS_FETCH;
|
||||
logic sample_addr;
|
||||
logic [31:0] fetch_addr, fetch_addr_n;
|
||||
logic [31:0] fetch_data, fetch_data_n;
|
||||
|
||||
logic [31:0] instr_addr_o_n;
|
||||
always_ff @(posedge clk, negedge rst_n)
|
||||
begin
|
||||
if (rst_n == 1'b0) begin
|
||||
fetch_addr <= '0;
|
||||
end else begin
|
||||
if (sample_addr)
|
||||
fetch_addr <= fetch_addr_n;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
logic [31:0] last_fetch_addr;
|
||||
|
@ -110,23 +113,233 @@ module if_stage
|
|||
// instr_core_interface
|
||||
logic req_int;
|
||||
logic ack_int;
|
||||
logic [31:0] addr_int;
|
||||
logic [31:0] rdata_int;
|
||||
|
||||
|
||||
// local cache
|
||||
logic [31:0] data_tag;
|
||||
logic [1:0][31:0] data_arr;
|
||||
|
||||
|
||||
logic bypass_data_reg; // use data from instr_core_if, not from data_arr
|
||||
logic pc_if_offset, pc_if_offset_n;
|
||||
|
||||
|
||||
|
||||
enum logic[3:0] {INVALID, VALID, FETCH, FETCH_NEXT, SERVE_OFFSET} fetch_fsm_cs, fetch_fsm_ns;
|
||||
|
||||
always_ff @(posedge clk, negedge rst_n)
|
||||
begin
|
||||
if (rst_n == 1'b0) begin
|
||||
fetch_fsm_cs <= INVALID;
|
||||
|
||||
pc_if_offset <= '0;
|
||||
end else begin
|
||||
fetch_fsm_cs <= fetch_fsm_ns;
|
||||
|
||||
pc_if_offset <= pc_if_offset_n;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
logic force_nop_int;
|
||||
logic handle_branch;
|
||||
logic do_fetch;
|
||||
logic [31:0] instr_rdata_int;
|
||||
assign instr_rdata_int = (force_nop_int == 1'b0)? rdata_int : {25'b0, `OPCODE_OPIMM};
|
||||
|
||||
|
||||
// increased PC calculation
|
||||
logic fetch_unaligned;
|
||||
logic fetch_hit;
|
||||
|
||||
logic [1:0] is_compressed;
|
||||
|
||||
|
||||
assign compressed_instr = instr_rdata_int[1:0] != 2'b11;
|
||||
|
||||
assign do_fetch = req_i;
|
||||
|
||||
always_comb
|
||||
begin
|
||||
if (rdata_int[1:0] != 2'b11) begin
|
||||
// compressed instruction
|
||||
incr_pc = current_pc_if_o + 32'd2;
|
||||
if (pc_if_offset) begin
|
||||
incr_pc = fetch_addr + (is_compressed[1] ? 32'd2 : 32'd4);
|
||||
end else begin
|
||||
incr_pc = current_pc_if_o + 32'd4;
|
||||
incr_pc = fetch_addr + (is_compressed[0] ? 32'd2 : 32'd4);
|
||||
end
|
||||
end
|
||||
//assign incr_pc = current_pc_if_o + (instr_rdata_int[1:0] != 2'b11 ? 32'd2 : 32'd4);
|
||||
|
||||
|
||||
// store instr_core_if data in local cache
|
||||
always_ff @(posedge clk, negedge rst_n)
|
||||
begin
|
||||
if (rst_n == 1'b0) begin
|
||||
data_tag <= '0;
|
||||
data_arr <= '0;
|
||||
end else begin
|
||||
if (ack_int) begin
|
||||
data_tag <= last_fetch_addr;
|
||||
data_arr[1] <= data_arr[0];
|
||||
data_arr[0] <= rdata_int;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// cache data output muxes
|
||||
always_comb
|
||||
begin
|
||||
if (bypass_data_reg) begin
|
||||
// bypass cache and get data directly from instr_core_if
|
||||
if (pc_if_offset)
|
||||
instr_rdata_int = {rdata_int[15:0], data_arr[0][31:16]};
|
||||
else
|
||||
instr_rdata_int = rdata_int;
|
||||
end else begin
|
||||
// serve data from cache
|
||||
if (pc_if_offset)
|
||||
instr_rdata_int = {data_arr[0][15:0], data_arr[1][31:16]};
|
||||
else
|
||||
instr_rdata_int = data_arr[0];
|
||||
end
|
||||
|
||||
if (force_nop_int)
|
||||
instr_rdata_int = {25'b0, `OPCODE_OPIMM};
|
||||
end
|
||||
|
||||
assign is_compressed[0] = instr_rdata_int[1:0] != 2'b11;
|
||||
assign is_compressed[1] = instr_rdata_int[17:16] != 2'b11;
|
||||
|
||||
|
||||
assign current_pc_if_o = pc_if_offset ? {fetch_addr[31:2], 2'b10} : fetch_addr;
|
||||
|
||||
|
||||
always_comb
|
||||
begin
|
||||
fetch_unaligned = next_pc[1:0] != 2'b0;
|
||||
//fetch_hit = (next_pc[31:2] == data_tag[31:2]);
|
||||
fetch_hit = (fetch_addr[31:2] == data_tag[31:2]);
|
||||
end
|
||||
|
||||
|
||||
always_comb
|
||||
begin
|
||||
fetch_fsm_ns = fetch_fsm_cs;
|
||||
|
||||
fetch_addr_n = {next_pc[31:2], 2'b0};
|
||||
sample_addr = 1'b0;
|
||||
|
||||
pc_if_offset_n = pc_if_offset; //1'b0;
|
||||
//sample_offset = 1'b0;
|
||||
ack_o = 1'b0;
|
||||
req_int = 1'b0;
|
||||
force_nop_int = 1'b0;
|
||||
|
||||
bypass_data_reg = 1'b0;
|
||||
|
||||
|
||||
unique case (fetch_fsm_cs)
|
||||
INVALID:
|
||||
begin
|
||||
if (do_fetch) begin
|
||||
if (force_nop_i) begin
|
||||
force_nop_int = 1'b1;
|
||||
ack_o = 1'b1;
|
||||
end else begin
|
||||
fetch_fsm_ns = FETCH;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
VALID:
|
||||
begin
|
||||
if (do_fetch) begin
|
||||
if (force_nop_i) begin
|
||||
force_nop_int = 1'b1;
|
||||
ack_o = 1'b1;
|
||||
end else begin
|
||||
if (fetch_hit) begin
|
||||
if (pc_if_offset) begin
|
||||
fetch_addr_n = last_fetch_addr + 4;
|
||||
sample_addr = 1'b1;
|
||||
if (is_compressed[1]) begin
|
||||
pc_if_offset_n = 1'b0;
|
||||
ack_o = 1'b1;
|
||||
end else begin
|
||||
fetch_fsm_ns = FETCH_NEXT;
|
||||
end
|
||||
end else begin
|
||||
ack_o = 1'b1;
|
||||
if (is_compressed[0]) begin
|
||||
pc_if_offset_n = 1'b1;
|
||||
end else begin
|
||||
fetch_addr_n = last_fetch_addr + 4;
|
||||
sample_addr = 1'b1;
|
||||
end
|
||||
end
|
||||
end else begin
|
||||
// fetch single requested word
|
||||
sample_addr = 1'b1;
|
||||
fetch_fsm_ns = FETCH;
|
||||
end
|
||||
// check if request can be served from local cache
|
||||
if (fetch_unaligned && fetch_hit) begin
|
||||
//if (is_compressed[1]) begin
|
||||
// // instruction is compressed and can be served from cache
|
||||
// pc_if_offset_n = 1'b1;
|
||||
// fetch_fsm_ns = SERVE_OFFSET;
|
||||
//end else begin
|
||||
// // fetch next instruction
|
||||
// fetch_addr_n = last_fetch_addr + 4;
|
||||
// sample_addr = 1'b1;
|
||||
// fetch_fsm_ns = FETCH_NEXT;
|
||||
//end
|
||||
end else if (fetch_unaligned) begin
|
||||
// fetch two words
|
||||
//sample_addr = 1'b1;
|
||||
//fetch_fsm_ns = FETCH;
|
||||
end else begin
|
||||
//// fetch single requested word
|
||||
//sample_addr = 1'b1;
|
||||
//fetch_fsm_ns = FETCH;
|
||||
end
|
||||
//fetch_fsm_ns = FETCH;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
SERVE_OFFSET:
|
||||
begin
|
||||
ack_o = 1'b1;
|
||||
fetch_fsm_ns = VALID;
|
||||
end
|
||||
|
||||
FETCH:
|
||||
begin
|
||||
req_int = 1'b1;
|
||||
if (ack_int) begin
|
||||
req_int = 1'b0; // TODO: Maybe only assert req_int before going into FETCH state
|
||||
bypass_data_reg = 1'b1;
|
||||
//ack_o = 1'b1;
|
||||
fetch_fsm_ns = VALID;
|
||||
end
|
||||
end
|
||||
|
||||
FETCH_NEXT:
|
||||
begin
|
||||
req_int = 1'b1;
|
||||
if (ack_int) begin
|
||||
req_int = 1'b0; // TODO: Maybe only assert req_int before going into FETCH state
|
||||
bypass_data_reg = 1'b1;
|
||||
ack_o = 1'b1;
|
||||
fetch_fsm_ns = VALID;
|
||||
|
||||
sample_addr = 1'b1;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
|
||||
if (pc_mux_boot_i) begin
|
||||
sample_addr = 1'b1;
|
||||
fetch_fsm_ns = INVALID;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -153,7 +366,7 @@ module if_stage
|
|||
`PC_HWLOOP: next_pc = pc_from_hwloop_i; // PC is taken from hwloop start addr
|
||||
default:
|
||||
begin
|
||||
next_pc = current_pc_if_o;
|
||||
next_pc = {boot_addr_i[31:5], `EXC_OFF_RST};
|
||||
// synopsys translate_off
|
||||
$display("%t: Illegal pc_mux_sel value (%0d)!", $time, pc_mux_sel_i);
|
||||
// synopsys translate_on
|
||||
|
@ -169,7 +382,6 @@ module if_stage
|
|||
next_pc = jump_target_i;
|
||||
else
|
||||
next_pc = incr_pc;
|
||||
//next_pc = current_pc_if_o;
|
||||
end
|
||||
|
||||
if (pc_mux_boot_i)
|
||||
|
@ -177,103 +389,6 @@ module if_stage
|
|||
end
|
||||
|
||||
|
||||
always_comb
|
||||
begin
|
||||
NS = CS;
|
||||
|
||||
req_int = 1'b0;
|
||||
addr_int = '0;
|
||||
|
||||
ack_o = 1'b0;
|
||||
|
||||
force_nop_int = 1'b0;
|
||||
|
||||
unique case (CS)
|
||||
IDLE:
|
||||
begin
|
||||
if (req_i) begin
|
||||
if (jump_in_id_i == 2'b0) begin
|
||||
if (force_nop_i) begin
|
||||
force_nop_int = 1'b1;
|
||||
ack_o = 1'b1;
|
||||
end else begin
|
||||
// no branch, do normal fetch
|
||||
req_int = 1'b1;
|
||||
addr_int = next_pc;
|
||||
if (stall_if_i) begin
|
||||
NS = FETCH_STALLED;
|
||||
end else begin
|
||||
NS = FETCH_UNSTALLED;
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
begin
|
||||
// wait for branch decision / jump target
|
||||
force_nop_int = 1'b1;
|
||||
ack_o = 1'b1;
|
||||
NS = WAIT_BRANCH;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
WAIT_BRANCH:
|
||||
begin
|
||||
if (jump_in_ex_i != 2'b0) begin
|
||||
req_int = 1'b1;
|
||||
addr_int = next_pc;
|
||||
if (stall_if_i) begin
|
||||
NS = FETCH_STALLED;
|
||||
end else begin
|
||||
NS = FETCH_UNSTALLED;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
FETCH_STALLED,
|
||||
FETCH_UNSTALLED:
|
||||
begin
|
||||
if (ack_int) begin
|
||||
NS = IDLE;
|
||||
ack_o = 1'b1;
|
||||
if (stall_if_i) begin
|
||||
if (CS == FETCH_STALLED) begin
|
||||
// already fetched instruction for after stall
|
||||
NS = WAIT_IF_STALL;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
WAIT_IF_STALL:
|
||||
begin
|
||||
NS = IDLE;
|
||||
ack_o = 1'b1;
|
||||
|
||||
if (stall_if_i)
|
||||
NS = WAIT_IF_STALL;
|
||||
end
|
||||
|
||||
default:
|
||||
begin
|
||||
$display("%t: invalid state", $time);
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
always_ff @(posedge clk, negedge rst_n)
|
||||
begin
|
||||
if (rst_n == 1'b0)
|
||||
begin
|
||||
CS <= IDLE;
|
||||
end
|
||||
else
|
||||
begin
|
||||
CS <= NS;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
// cache fetch interface
|
||||
instr_core_interface instr_core_if_i
|
||||
(
|
||||
|
@ -282,7 +397,7 @@ module if_stage
|
|||
|
||||
.req_i ( req_int ),
|
||||
.ack_o ( ack_int ),
|
||||
.addr_i ( addr_int ),
|
||||
.addr_i ( fetch_addr ),
|
||||
.rdata_o ( rdata_int ),
|
||||
|
||||
.instr_req_o ( instr_req_o ),
|
||||
|
@ -304,23 +419,24 @@ module if_stage
|
|||
begin : IF_PIPELINE
|
||||
if (rst_n == 1'b0)
|
||||
begin
|
||||
current_pc_if_o <= 32'h0;
|
||||
//current_pc_if_o <= 32'h0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if (pc_mux_boot_i == 1'b1)
|
||||
//if (pc_mux_boot_i == 1'b1)
|
||||
//begin
|
||||
// // set PC to reset vector
|
||||
// current_pc_if_o <= {boot_addr_i[31:5], `EXC_OFF_RST};
|
||||
//end
|
||||
//else if (dbg_set_npc == 1'b1)
|
||||
//begin
|
||||
// // debug units sets NPC, PC_MUX_SEL holds this value
|
||||
// current_pc_if_o <= dbg_pc_from_npc;
|
||||
//end
|
||||
//else if (stall_if_i == 1'b0)
|
||||
if (stall_if_i == 1'b0)
|
||||
begin
|
||||
// set PC to reset vector
|
||||
current_pc_if_o <= {boot_addr_i[31:5], `EXC_OFF_RST};
|
||||
end
|
||||
else if (dbg_set_npc == 1'b1)
|
||||
begin
|
||||
// debug units sets NPC, PC_MUX_SEL holds this value
|
||||
current_pc_if_o <= dbg_pc_from_npc;
|
||||
end
|
||||
else if (stall_if_i == 1'b0)
|
||||
begin
|
||||
current_pc_if_o <= last_fetch_addr;
|
||||
//current_pc_if_o <= last_fetch_addr;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -338,8 +454,7 @@ module if_stage
|
|||
if (stall_id_i == 1'b0)
|
||||
begin : ENABLED_PIPE
|
||||
instr_rdata_id_o <= instr_rdata_int;
|
||||
//current_pc_id_o <= current_pc_if_o;
|
||||
current_pc_id_o <= last_fetch_addr;
|
||||
current_pc_id_o <= current_pc_if_o;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue