1
0
mirror of https://github.com/olofk/serv.git synced 2026-01-13 15:17:25 +00:00

Rewrite RF and state machine

Big patch, but would take more work to split it up
This commit is contained in:
Olof Kindgren 2019-09-17 16:01:43 +02:00
parent 8481fb46a1
commit 126937f16a
4 changed files with 116 additions and 124 deletions

View File

@ -105,7 +105,7 @@ module serv_alu
assign o_rd = (i_rd_sel == ALU_RESULT_ADD) ? result_add :
(i_rd_sel == ALU_RESULT_SR) ? result_sh :
(i_rd_sel == ALU_RESULT_LT) ? result_lt_r :
(i_rd_sel == ALU_RESULT_LT) ? result_lt_r & plus_1:
(i_rd_sel == ALU_RESULT_BOOL) ? result_bool : 1'bx;
@ -117,8 +117,6 @@ module serv_alu
eq_r <= result_eq;
end else begin
eq_r <= 1'b1;
if (result_lt_r)
result_lt_r <= 1'b0;
end
en_r <= i_en;
end

View File

@ -6,6 +6,7 @@ module serv_mpram
input wire i_run,
//Trap interface
input wire i_trap,
input wire i_mret,
input wire i_mepc,
input wire i_mtval,
output wire o_csr_pc,
@ -19,6 +20,7 @@ module serv_mpram
input wire [4:0] i_rd_waddr,
input wire i_rd,
input wire i_wreq,
input wire i_rreq,
output reg o_rgnt,
//RS1 read port
@ -30,29 +32,24 @@ module serv_mpram
`include "serv_params.vh"
wire [8:0] waddr;
/*
********** Write side ***********
*/
reg [4:0] wdata0;
reg [5:0] wdata1;
reg [4:0] wcnt;
reg wgo;
wire [3:0] wdata;
wire [3:0] wslot = wcnt[4:1];
wire wport = wcnt[0];
wire wen;
reg [1:0] wen_r;
reg [3:0] wcnt_lo;
reg [2:0] wcnt_hi;
reg wgo_r;
reg trap_r;
reg trap_2r;
reg trap_3r;
assign wdata = wcnt_lo[0] ? wdata0[3:0] : wdata1[3:0];
assign wen = !wgo_r & |(wen_r & wcnt_lo[1:0]);
reg [4:0] rd_waddr;
wire wdata0 = i_trap ? i_mtval : i_rd;
wire wdata1 = i_trap ? i_mepc : i_csr;
reg wdata0_r;
reg wdata1_r;
reg wdata1_2r;
wire [1:0] wdata = !wport ?
{wdata0 , wdata0_r} :
{wdata1_r, wdata1_2r};
//port 0 rd mtval
//port 1 csr mepc
@ -60,105 +57,90 @@ module serv_mpram
//mtval 100011
//csr 1000xx
//rd 0xxxxx
wire [5:0] waddr0 = trap_3r ? {4'b1000,CSR_MTVAL} : {1'b0,rd_waddr};
wire [5:0] waddr1 = trap_3r ? {4'b1000,CSR_MEPC} : {4'b1000,i_csr_addr};
wire [5:0] wreg0 = i_trap ? {4'b1000,CSR_MTVAL} : {1'b0,i_rd_waddr};
wire [5:0] wreg1 = i_trap ? {4'b1000,CSR_MEPC} : {4'b1000,i_csr_addr};
wire [5:0] wreg = wport ? wreg1 : wreg0;
wire [9:0] waddr = {wreg, wslot};
assign waddr[8:3] = wcnt_lo[0] ? waddr0 : waddr1;
wire wen = wgo & (i_trap | (wport ? i_csr_en : i_rd_wen & run_r));
// assign waddr[8] = wcnt_lo[1] | i_trap;
// assign waddr[7:5] = (wcnt_lo[1] | i_trap) ? 3'b000 : rd_waddr[4:2];
// assign waddr[4:3] = wcnt_lo[0] ? (i_trap ? CSR_MTVAL : rd_waddr[1:0]) :
// (i_trap ? CSR_MEPC : i_csr_addr);
assign waddr[2:0] = wcnt_hi;
wire wgo = !(|wcnt_lo) & ((i_run & (i_rd_wen | i_csr_en)) | i_trap);
reg wreq_r;
reg run_r;
always @(posedge i_clk) begin
trap_r <= i_trap;
trap_2r <= trap_r;
trap_3r <= trap_2r;
wreq_r <= i_wreq | o_rgnt;
wdata0_r <= wdata0;
wdata1_r <= wdata1;
wdata1_2r <= wdata1_r;
run_r <= i_run;
if (wgo)
wcnt <= wcnt+5'd1;
if (wreq_r)
wgo <= 1'b1;
if (wcnt == 5'b11111)
wgo <= 1'b0;
if (wgo) begin
wgo_r <= 1'b1;
wen_r <= {(i_run & i_csr_en)|i_trap,(i_rd_wen & i_run)|i_trap};
rd_waddr <= i_rd_waddr;
end
wdata0 <= {i_trap ? i_mtval : i_rd ,wdata0[4:1]};
wdata1 <= {i_trap ? i_mepc : i_csr,wdata1[5:1]};
wcnt_lo <= {wcnt_lo[2:0],wcnt_lo[3] | wgo};
if (wcnt_lo[3]) begin
wcnt_hi <= wcnt_hi + 1;
if (wcnt_hi == 3'd7) begin
wgo_r <= !wgo_r;
wcnt_lo[0] <= wgo_r;
wcnt_hi <= wcnt_hi + {2'b00,wgo_r};
end
end
if (i_rst) begin
wgo_r <= 1'b0;
wcnt_lo <= 4'd0;
wcnt_hi <= 3'd7;
wcnt <= 5'd0;
end
end
/*
********** Read side ***********
*/
//0 : RS1
//1 : RS2
//2 : CSR
reg [2:0] rcnt_hi;
reg [3:0] rcnt_lo;
//1 : RS2 / CSR
wire [8:0] raddr;
reg [4:0] rcnt;
wire [3:0] rslot = rcnt[4:1];
wire rport = rcnt[0];
reg [3:0] rdata;
wire [5:0] rreg0 = {1'b0, i_rs1_raddr};
wire [5:0] rreg1 =
i_trap ? {4'b1000, CSR_MTVEC} :
(i_csr_en | i_mret) ? {4'b1000, i_csr_addr} :
{1'b0,i_rs2_raddr};
wire [5:0] rreg = rport ? rreg1 : rreg0;
wire [9:0] raddr = {rreg, rslot};
reg [5:0] rdata0;
reg [4:0] rdata1;
reg [3:0] rdata2;
//reg [3:0] rdata3;
reg [1:0] rdata;
reg [1:0] rdata0;
reg rdata1;
reg [2:0] rreq;
assign o_rs1 = !rport ? rdata0[0] : rdata0[1];
assign o_rs2 = rport ? rdata1 : rdata[0];
assign o_csr = o_rs2 & i_csr_en;
assign o_csr_pc = o_rs2;
reg rreq_r;
always @(posedge i_clk) begin
{o_rgnt,rreq} <= {rreq[2:0],i_rreq};
if (rcnt_lo[3])
rcnt_hi <= rcnt_hi + 1;
if (i_rreq) begin
rcnt_lo <= 4'd1;
rcnt_hi <= 3'd0;
end else
rcnt_lo <= {rcnt_lo[2:0],rcnt_lo[3]};
rcnt <= rcnt+5'd1;
if (i_rreq)
rcnt <= 5'd0;
rdata0[4:0] <= rdata0[5:1];
rdata1[3:0] <= rdata1[4:1];
rdata2[2:0] <= rdata2[3:1];
//rdata3[2:0] <= rdata3[3:1];
rreq_r <= i_rreq;
o_rgnt <= rreq_r;
if (rcnt_lo[1]) rdata0[5:2] <= rdata;
if (rcnt_lo[2]) rdata1[4:1] <= rdata;
if (rcnt_lo[3]) rdata2[3:0] <= rdata;
//if (rcnt_lo[0]) rdata3[3:0] <= rdata;
if (rport)
rdata0 <= rdata;
if (!rport)
rdata1 <= rdata[1];
if (i_rst) begin
o_rgnt <= 1'b0;
rreq <= 3'd0;
rreq_r <= 1'b0;
end
end
assign raddr[8] = rcnt_lo[2];
assign raddr[7:5] = rcnt_lo[0] ? i_rs1_raddr[4:2] :
rcnt_lo[1] ? i_rs2_raddr[4:2] : 3'd0;
assign raddr[4:3] = rcnt_lo[0] ? i_rs1_raddr[1:0] :
rcnt_lo[1] ? i_rs2_raddr[1:0] :
i_trap ? CSR_MTVEC : i_csr_addr;
assign raddr[2:0] = rcnt_hi;
assign o_rs1 = rdata0[0];
assign o_rs2 = rdata1[0];
assign o_csr = rdata2[0] & i_csr_en;
assign o_csr_pc = rdata2[0];
reg [3:0] memory [0:511];
reg [1:0] memory [0:1023];
always @(posedge i_clk) begin
if (wen)
@ -176,8 +158,8 @@ module serv_mpram
`ifdef SERV_CLEAR_RAM
integer i;
initial
for (i=0;i<256;i=i+1)
memory[i] = 4'd0;
for (i=0;i<512;i=i+1)
memory[i] = 2'd0;
`endif
endmodule

View File

@ -6,6 +6,7 @@ module serv_state
input wire i_dbus_ack,
input wire i_ibus_ack,
output wire o_rf_rreq,
output wire o_rf_wreq,
input wire i_rf_ready,
input wire i_take_branch,
input wire i_branch_op,
@ -32,7 +33,7 @@ module serv_state
input wire i_mem_misalign,
output reg [3:0] o_csr_mcause,
output wire o_cnt_done,
output reg o_bufreg_hold,
output wire o_bufreg_hold,
output wire o_csr_imm);
localparam [1:0]
@ -44,6 +45,7 @@ module serv_state
reg [1:0] state;
reg cnt_done;
reg stage_two_req;
wire cnt_en;
wire running;
@ -86,12 +88,22 @@ module serv_state
assign o_dbus_cyc = (state == IDLE) & stage_two_pending & i_mem_op & !mem_misalign;
assign o_rf_rreq = i_ibus_ack;
wire trap_pending = (o_ctrl_jump & i_ctrl_misalign) | mem_misalign;
//Prepare RF for reads when a new instruction is fetched
// or when stage one caused an exception (rreq implies a write request too)
assign o_rf_rreq = i_ibus_ack | (stage_two_req & trap_pending);
//Prepare RF for writes when everything is ready to enter stage two
assign o_rf_wreq = ((i_shift_op & i_alu_sh_done & stage_two_pending) | (i_mem_op & i_dbus_ack) | (stage_two_req & (i_slt_op | i_branch_op))) & !trap_pending;
//Shift operations require bufreg to hold for one cycle between INIT and RUN before shifting
assign o_bufreg_hold = !cnt_en & (stage_two_req | ~i_shift_op);
always @(posedge i_clk) begin
if (state == INIT)
o_ctrl_jump <= i_take_branch;
if (state == IDLE)
if (o_ctrl_pc_en & cnt_done)
o_ctrl_jump <= 1'b0;
if (cnt_en)
@ -102,41 +114,37 @@ module serv_state
cnt_done <= (o_cnt[4:2] == 3'b111) & o_cnt_r[2];
//Shift operations require bufreg to hold for one cycle before shifting
o_bufreg_hold <= i_shift_op & cnt_done;
//Need a strobe for the first cycle in the IDLE state after INIT
stage_two_req <= cnt_done & (state == INIT);
case (state)
IDLE : begin
if (i_rf_ready | i_dbus_ack) begin
state <= RUN;
if (two_stage_op & !stage_two_pending)
state <= INIT;
if (i_e_op | pending_irq)
if (stage_two_pending) begin
if (o_rf_wreq)
state <= RUN;
if (trap_pending & i_rf_ready)
state <= TRAP;
end else if (i_alu_sh_done & i_shift_op & stage_two_pending)
state <= RUN;
end
end else begin
if (i_rf_ready)
if (i_e_op | pending_irq)
state <= TRAP;
else if (two_stage_op)
state <= INIT;
else
state <= RUN;
end
end
INIT : begin
if (cnt_done)
if (mem_misalign | (i_take_branch & i_ctrl_misalign))
state <= TRAP;
else if (i_mem_op | i_shift_op )
state <= IDLE;
else
state <= RUN;
end
RUN : begin
if (cnt_done)
state <= IDLE;
end
TRAP : begin
pending_irq <= 1'b0;
if (cnt_done)
state <= IDLE;
end
default : state <= IDLE;
endcase
if (cnt_done)
state <= IDLE;
o_cnt <= o_cnt + {4'd0,cnt_en};
if (cnt_en)

View File

@ -99,6 +99,7 @@ module serv_top
wire [1:0] alu_rd_sel;
wire rf_rreq;
wire rf_wreq;
wire rf_ready;
wire rs1;
wire rs2;
@ -144,6 +145,7 @@ module serv_top
.i_dbus_ack (i_dbus_ack),
.i_ibus_ack (i_ibus_ack),
.o_rf_rreq (rf_rreq),
.o_rf_wreq (rf_wreq),
.i_rf_ready (rf_ready),
.i_take_branch (take_branch),
.i_branch_op (branch_op),
@ -240,7 +242,7 @@ module serv_top
.i_rst (i_rst),
.i_cnt (cnt[4:2]),
.i_cnt_r (cnt_r[1:0]),
.i_en (!(bufreg_hold | o_dbus_cyc)),
.i_en (!bufreg_hold),
.i_init (init),
.i_loop (bufreg_loop),
.i_rs1 (rs1),
@ -318,6 +320,7 @@ module serv_top
.i_run (run),
//Trap interface
.i_trap (trap),
.i_mret (mret),
.i_mepc (o_ibus_adr[0]),
.i_mtval ((mem_misalign & mem_op) ? bufreg_q : bad_pc),
.o_csr_pc (csr_pc),
@ -331,6 +334,7 @@ module serv_top
.i_rd (rd),
.i_rreq (rf_rreq),
.i_wreq (rf_wreq),
.o_rgnt (rf_ready),
//RS1 read port
.i_rs1_raddr (rs1_addr),