This commit is contained in:
Olof Kindgren 2018-10-28 23:54:04 +01:00
parent c2030a95fd
commit 66000a77f5
6 changed files with 209 additions and 48 deletions

15
rtl/ser_eq.v Normal file
View file

@ -0,0 +1,15 @@
module ser_eq
(
input clk,
input a,
input b,
input clr,
output q);
reg eq = 1'b1;
assign q = eq & (a == b);
always @(posedge clk)
eq <= q | clr;
endmodule

View file

@ -6,6 +6,8 @@ module serv_alu
input [2:0] i_funct3,
input i_rs1,
input i_op_b,
input i_cmp_en,
output o_cmp,
output o_rd);
localparam [2:0]
@ -16,7 +18,11 @@ module serv_alu
ORI = 3'b110,
ANDI = 3'b111;
localparam[2:0]
BEQ = 3'b000;
wire result_add;
wire result_eq;
ser_add ser_add
(
@ -26,7 +32,19 @@ module serv_alu
.clr (!i_en),
.q (result_add));
reg eq;
ser_eq ser_eq
(
.clk (clk),
.a (i_rs1),
.b (i_op_b),
.clr (!i_cmp_en),
.q (result_eq));
assign o_cmp = (i_funct3 == BEQ) ? result_eq : 1'bx;
assign o_rd = (i_funct3 == ADDI) ? result_add : 1'b0;
endmodule
endmodule

View file

@ -6,16 +6,19 @@ module serv_decode
output reg o_i_rd_rdy = 1'b1,
output o_ctrl_en,
output o_ctrl_jump,
output [2:0] o_funct3,
output o_rf_rd_en,
output [4:0] o_rf_rd_addr,
output o_rf_rs_en,
output [4:0] o_rf_rs1_addr,
output [4:0] o_rf_rs2_addr,
output o_alu_cmp_en,
input i_alu_cmp,
output o_mem_en,
output o_mem_cmd,
output o_mem_init,
output o_mem_dat_valid,
input i_mem_busy,
output [2:0] o_funct3,
output reg o_imm,
output o_offset_source,
output o_op_b_source,
@ -24,35 +27,43 @@ module serv_decode
`include "serv_params.vh"
localparam [1:0]
IDLE = 2'd0,
MEM_INIT = 2'd1,
MEM_WAIT = 2'd2,
RUN = 2'd3;
localparam [2:0]
IDLE = 3'd0,
COMPARE = 3'd1,
MEM_INIT = 3'd2,
MEM_WAIT = 3'd3,
RUN = 3'd4;
localparam [4:0]
OP_LOAD = 5'b00000,
OP_OPIMM = 5'b00100,
OP_LUI = 5'b01101,
OP_JAL = 5'b11011;
OP_LOAD = 5'b00000,
OP_STORE = 5'b01000,
OP_OPIMM = 5'b00100,
OP_LUI = 5'b01101,
OP_BRANCH = 5'b11000,
OP_JAL = 5'b11011;
reg [2:0] state = 3'd0;
reg [1:0] state = 2'd0;
reg [4:0] cnt = 5'd0;
wire running;
wire mem_op;
assign mem_op = (opcode == OP_LOAD);
assign mem_op = (opcode == OP_LOAD) | (opcode == OP_STORE);
assign o_ctrl_en = running;
assign o_ctrl_jump = (opcode == OP_JAL);
assign o_ctrl_jump = (opcode == OP_JAL) |
((opcode == OP_BRANCH) & i_alu_cmp);
assign o_rf_rd_en = running & ((opcode == OP_JAL) |
(opcode == OP_OPIMM) |
(opcode == OP_LUI));
assign o_rf_rs_en = (running & (opcode == OP_OPIMM)) |
(state == MEM_INIT);
assign o_alu_cmp_en = (state == COMPARE);
assign o_mem_en = mem_op & cnt_en;
assign o_mem_cmd = (opcode == OP_STORE);
assign o_mem_init = (state == MEM_INIT);
assign o_rf_rd_addr = i_i_rd_dat[11:7];
@ -61,7 +72,8 @@ module serv_decode
assign o_rf_rs2_addr = i_i_rd_dat[24:20];
assign o_offset_source = (opcode == OP_JAL) ? OFFSET_SOURCE_IMM : 1'b0;
assign o_op_b_source = (opcode == OP_OPIMM) ? OP_B_SOURCE_IMM : 1'b0;
assign o_op_b_source = (opcode == OP_OPIMM) ? OP_B_SOURCE_IMM :
(opcode == OP_BRANCH) ? OP_B_SOURCE_RS2 : 1'bx;
assign o_mem_dat_valid = (o_funct3[1:0] == 2'b00) ? cnt < 8 :
(o_funct3[1:0] == 2'b01) ? cnt < 16 : 1'b1;
@ -90,11 +102,24 @@ module serv_decode
else if (opcode == OP_LOAD)
if (cnt > 10) o_imm = i_i_rd_dat[31];
else o_imm = i_i_rd_dat[cnt+20];
else if (opcode == OP_BRANCH)
if (cnt > 11) o_imm = i_i_rd_dat[31];
else if (cnt > 10) o_imm = i_i_rd_dat[7];
else if (cnt > 4) o_imm = i_i_rd_dat[cnt+20];
else if (cnt > 0) o_imm = i_i_rd_dat[cnt+7];
else o_imm = 1'b0;
else if (opcode == OP_STORE)
if (cnt > 10) o_imm = i_i_rd_dat[31];
else if (cnt > 4) o_imm = i_i_rd_dat[cnt+20];
else o_imm = i_i_rd_dat[cnt+7];
end
wire go = i_i_rd_vld & o_i_rd_rdy;
wire cnt_en = (state == RUN) | (state == MEM_INIT);
wire cnt_en =
(state == RUN) |
(state == COMPARE) |
(state == MEM_INIT);
wire cnt_done = cnt == 31;
assign running = (state == RUN);
@ -104,7 +129,12 @@ module serv_decode
case (state)
IDLE : begin
if (go)
state <= mem_op ? MEM_INIT : RUN;
state <= (opcode == OP_BRANCH) ? COMPARE :
mem_op ? MEM_INIT : RUN;
end
COMPARE : begin
if (cnt_done)
state <= RUN;
end
MEM_INIT :
if (cnt_done)

View file

@ -19,12 +19,16 @@ module serv_mem_if
input i_d_ca_rdy,
output [31:0] o_d_dm_dat,
output [3:0] o_d_dm_msk,
output o_d_dm_vld,
output reg o_d_dm_vld = 1'b0,
input i_d_dm_rdy,
input [31:0] i_d_rd_dat,
input i_d_rd_vld,
output o_d_rd_rdy);
wire ca_en = o_d_ca_vld & i_d_ca_rdy;
wire dm_en = o_d_dm_vld & i_d_dm_rdy;
wire rd_en = i_d_rd_vld & o_d_rd_rdy;
reg en_r;
wire adr;
reg [31:0] dat = 32'd0;
@ -54,17 +58,26 @@ module serv_mem_if
assign o_d_rd_rdy = !i_en; //Likely bug, but probably doesn't matter
wire is_half = i_funct3[1];
wire is_word = i_funct3[1];
wire is_half = i_funct3[0];
wire is_byte = !(|i_funct3[1:0]);
wire [1:0] bytepos = o_d_ca_adr[3:2];
wire upper_half = bytepos[1];
assign o_d_dm_dat = dat;
assign o_d_dm_msk = is_word ? 4'b1111 :
is_half ? {{2{upper_half}}, ~{2{upper_half}}} :
1'b1 << bytepos;
always @(posedge i_clk) begin
signbit <= dat[0];
if (i_en & i_init)
o_busy <= 1'b1;
else if (i_d_rd_vld & o_d_rd_rdy) begin
else if (rd_en | dm_en)
o_busy <= 1'b0;
if (rd_en) begin
dat[31:16] <= i_d_rd_dat[31:16];
dat[15:8] <= (is_half & upper_half) ? i_d_rd_dat[31:24] : i_d_rd_dat[15:8];
dat[7:0] <= (is_byte & (bytepos == 2'b11)) ? i_d_rd_dat[31:24] :
@ -72,15 +85,20 @@ module serv_mem_if
(is_half & upper_half) ? i_d_rd_dat[23:16] :
(is_byte & (bytepos == 2'b01)) ? i_d_rd_dat[15:8] :
i_d_rd_dat[7:0];
o_busy <= 1'b0;
end
en_r <= i_en;
if (o_d_ca_vld & i_d_ca_rdy)
if (ca_en)
o_d_ca_vld <= 1'b0;
else if (en_r & !i_en)
o_d_ca_vld <= 1'b1;
else if (en_r & !i_en) begin
o_d_ca_vld <= 1'b1;
end
if (dm_en)
o_d_dm_vld <= 1'b0;
else if (en_r & !i_en)
o_d_dm_vld <= i_cmd;
if (i_en)
dat <= {i_rs2,dat[31:1]};
end

View file

@ -1,24 +1,54 @@
`default_nettype none
`define RISCV_FORMAL
`define RISCV_FORMAL_NRET 1
`define RISCV_FORMAL_XLEN 32
`define RISCV_FORMAL_ILEN 32
//`define RISCV_FORMAL_COMPRESSED
`define RISCV_FORMAL_ALIGNED_MEM
module serv_top
(
input clk,
output [31:0] o_i_ca_adr,
output o_i_ca_vld,
input i_i_ca_rdy,
input [31:0] i_i_rd_dat,
input i_i_rd_vld,
output o_i_rd_rdy,
output o_d_ca_cmd,
output [31:0] o_d_ca_adr,
output o_d_ca_vld,
input i_d_ca_rdy,
output [31:0] o_d_dm_dat,
output [3:0] o_d_dm_msk,
output o_d_dm_vld,
input i_d_dm_rdy,
input [31:0] i_d_rd_dat,
input i_d_rd_vld,
output o_d_rd_rdy);
input clk,
`ifdef RISCV_FORMAL
output reg rvfi_valid = 1'b0,
output reg [63:0] rvfi_order = 64'd0,
output reg [31:0] rvfi_insn = 32'd0,
output reg rvfi_trap = 1'b0,
output reg rvfi_halt = 1'b0,
output reg rvfi_intr = 1'b0,
output reg [1:0] rvfi_mode = 2'b11,
output reg [4:0] rvfi_rs1_addr,
output reg [4:0] rvfi_rs2_addr,
output reg [31:0] rvfi_rs1_rdata,
output reg [31:0] rvfi_rs2_rdata,
output reg [4:0] rvfi_rd_addr,
output reg [31:0] rvfi_rd_wdata,
output reg [31:0] rvfi_pc_rdata,
output reg [31:0] rvfi_pc_wdata,
output reg [31:0] rvfi_mem_addr,
output reg [3:0] rvfi_mem_rmask,
output reg [3:0] rvfi_mem_wmask,
output reg [31:0] rvfi_mem_rdata,
output reg [31:0] rvfi_mem_wdata,
`endif
output [31:0] o_i_ca_adr,
output o_i_ca_vld,
input i_i_ca_rdy,
input [31:0] i_i_rd_dat,
input i_i_rd_vld,
output o_i_rd_rdy,
output o_d_ca_cmd,
output [31:0] o_d_ca_adr,
output o_d_ca_vld,
input i_d_ca_rdy,
output [31:0] o_d_dm_dat,
output [3:0] o_d_dm_msk,
output o_d_dm_vld,
input i_d_dm_rdy,
input [31:0] i_d_rd_dat,
input i_d_rd_vld,
output o_d_rd_rdy);
`include "serv_params.vh"
@ -39,6 +69,9 @@ module serv_top
wire imm;
wire [2:0] funct3;
wire alu_cmp_en;
wire alu_cmp;
wire rs1;
wire rs2;
@ -50,7 +83,7 @@ module serv_top
wire mem_en;
wire mem_cmd = 1'b0 /*FIXME*/;
wire mem_cmd;
wire mem_dat_valid;
wire mem_init;
@ -67,12 +100,15 @@ module serv_top
.o_ctrl_en (ctrl_en),
.o_ctrl_jump (jump),
.o_funct3 (funct3),
.o_alu_cmp_en (alu_cmp_en),
.i_alu_cmp (alu_cmp),
.o_rf_rd_en (rd_en),
.o_rf_rd_addr (rd_addr),
.o_rf_rs_en (rs_en),
.o_rf_rs1_addr (rs1_addr),
.o_rf_rs2_addr (rs2_addr),
.o_mem_en (mem_en),
.o_mem_cmd (mem_cmd),
.o_mem_init (mem_init),
.o_mem_dat_valid (mem_dat_valid),
.i_mem_busy (mem_busy),
@ -108,8 +144,10 @@ module serv_top
serv_alu alu
(
.clk (clk),
.i_en (ctrl_en), /*FIXME: Is this true?*/
.i_en (ctrl_en),
.i_funct3 (funct3),
.i_cmp_en (alu_cmp_en),
.o_cmp (alu_cmp),
.i_rs1 (rs1),
.i_op_b (op_b),
.o_rd (alu_rd));
@ -139,7 +177,7 @@ module serv_top
.i_imm (imm),
.o_rd (mem_rd),
.o_busy (mem_busy),
//External interface
//External interface
.o_d_ca_cmd (o_d_ca_cmd),
.o_d_ca_adr (o_d_ca_adr),
.o_d_ca_vld (o_d_ca_vld),
@ -152,4 +190,45 @@ module serv_top
.i_d_rd_vld (i_d_rd_vld),
.o_d_rd_rdy (o_d_rd_rdy));
`ifdef RISCV_FORMAL
reg [31:0] rs1_fv, rs2_fv, rd_fv;
reg [31:0] pc = RESET_PC;
reg ctrl_en_r = 1'b0;
always @(posedge clk) begin
ctrl_en_r <= ctrl_en;
if (rs_en) begin
rs1_fv <= {rs1,rs1_fv[31:1]};
rs2_fv <= {rs2,rs2_fv[31:1]};
end
if (rd_en) begin
rd_fv <= {rd,rd_fv[31:1]};
end
rvfi_valid <= 1'b0;
if (ctrl_en_r & !ctrl_en) begin
pc <= o_i_ca_adr;
rvfi_valid <= 1'b1;
rvfi_order <= rvfi_order + 1;
rvfi_insn <= i_i_rd_dat;
rvfi_trap <= 1'b0;
rvfi_halt <= 1'b0;
rvfi_intr <= 1'b0;
rvfi_mode <= 2'd3;
rvfi_rs1_addr <= rs1_addr;
rvfi_rs2_addr <= rs2_addr;
rvfi_rs1_rdata <= rs1_fv;
rvfi_rs2_rdata <= rs2_fv;
rvfi_rd_addr <= rd_addr;
rvfi_rd_wdata <= rd_fv;
rvfi_pc_rdata <= pc;
rvfi_pc_wdata <= o_i_ca_adr;
rvfi_mem_addr <= o_d_ca_adr;
rvfi_mem_rmask <= 4'bxxxx;
rvfi_mem_wmask <= o_d_dm_msk;
rvfi_mem_rdata <= i_d_rd_dat;
rvfi_mem_wdata <= o_d_dm_dat;
end
end
`endif
endmodule

View file

@ -9,6 +9,7 @@ filesets:
- rtl/serv_params.vh : {is_include_file : true}
- rtl/shift_reg.v
- rtl/ser_add.v
- rtl/ser_eq.v
- rtl/serv_alu.v
- rtl/serv_ctrl.v
- rtl/serv_decode.v
@ -16,7 +17,7 @@ filesets:
- rtl/serv_regfile.v
- rtl/serv_top.v
file_type : verilogSource
depend : [wb_ram]
depend : [wb_ram, "yosys:techlibs:ice40"]
ser_add_tb:
files: