pre/post works. mem broken

This commit is contained in:
Olof Kindgren 2021-10-12 23:28:08 +02:00
parent e59fe5346a
commit 2b7bddbb08
7 changed files with 1605 additions and 305 deletions

View file

@ -3,65 +3,26 @@ module serv_decode
#(parameter [0:0] PRE_REGISTER = 1,
parameter [0:0] MDU = 0)
(
input wire clk,
input wire clk,
//Input
input wire [31:2] i_wb_rdt,
input wire i_wb_en,
input wire i_wb_en,
//To state
output reg o_sh_right,
output reg o_bne_or_bge,
output reg o_cond_branch,
output reg o_e_op,
output reg o_ebreak,
output reg o_branch_op,
output reg o_shift_op,
output reg o_slt_or_branch,
output reg o_rd_op,
output reg o_two_stage_op,
output reg o_dbus_en,
//MDU
output reg o_mdu_op,
//Extension
output reg [2:0] o_ext_funct3,
//To bufreg
output reg o_bufreg_rs1_en,
output reg o_bufreg_imm_en,
output reg o_bufreg_clr_lsb,
output reg o_bufreg_sh_signed,
output reg o_e_op,//xx
output reg o_ebreak,//xx
//To ctrl
output reg o_ctrl_jal_or_jalr,
output reg o_ctrl_utype,
output reg o_ctrl_pc_rel,
output reg o_ctrl_mret,
//To alu
output reg o_alu_sub,
output reg [1:0] o_alu_bool_op,
output reg o_alu_cmp_eq,
output reg o_alu_cmp_sig,
output reg [2:0] o_alu_rd_sel,
//To mem IF
output reg o_mem_signed,
output reg o_mem_word,
output reg o_mem_half,
output reg o_mem_cmd,
output reg o_ctrl_mret,//xx
//To CSR
output reg o_csr_en,
output reg [1:0] o_csr_addr,
output reg o_csr_mstatus_en,
output reg o_csr_mie_en,
output reg o_csr_mcause_en,
output reg [1:0] o_csr_source,
output reg o_csr_d_sel,
output reg o_csr_imm_en,
output reg o_mtval_pc,
//To top
output reg [3:0] o_immdec_ctrl,
output reg [3:0] o_immdec_en,
output reg o_op_b_source,
output reg o_csr_en,//xx
output reg [1:0] o_csr_addr,//xx
output reg o_csr_mstatus_en,//xx
output reg o_csr_mie_en,//xx
output reg o_csr_mcause_en,//xx
output reg [1:0] o_csr_source,//xx
output reg o_csr_d_sel,//xx
output reg o_csr_imm_en,//xx
//To RF IF
output reg o_rd_mem_en,
output reg o_rd_csr_en,
output reg o_rd_alu_en);
output reg o_rd_csr_en);//xx
reg [4:0] opcode;
reg [2:0] funct3;
@ -73,91 +34,14 @@ module serv_decode
reg imm25;
reg imm30;
wire co_mdu_op = MDU & (opcode == 5'b01100) & imm25;
wire co_two_stage_op =
~opcode[2] | (funct3[0] & ~funct3[1] & ~opcode[0] & ~opcode[4]) |
(funct3[1] & ~funct3[2] & ~opcode[0] & ~opcode[4]) | co_mdu_op;
wire co_shift_op = (opcode[2] & ~funct3[1]) & !co_mdu_op;
wire co_slt_or_branch = (opcode[4] | (funct3[1] & opcode[2]) | (imm30 & opcode[2] & opcode[3] & ~funct3[2])) & !co_mdu_op;
wire co_branch_op = opcode[4];
wire co_dbus_en = ~opcode[2] & ~opcode[4];
wire co_mtval_pc = opcode[4];
wire co_mem_word = funct3[1];
wire co_rd_alu_en = !opcode[0] & opcode[2] & !opcode[4] & !co_mdu_op;
wire co_rd_mem_en = (!opcode[2] & !opcode[0]) | co_mdu_op;
wire [2:0] co_ext_funct3 = funct3;
//jal,branch = imm
//jalr = rs1+imm
//mem = rs1+imm
//shift = rs1
wire co_bufreg_rs1_en = !opcode[4] | (!opcode[1] & opcode[0]);
wire co_bufreg_imm_en = !opcode[2];
//Clear LSB of immediate for BRANCH and JAL ops
//True for BRANCH and JAL
//False for JALR/LOAD/STORE/OP/OPIMM?
wire co_bufreg_clr_lsb = opcode[4] & ((opcode[1:0] == 2'b00) | (opcode[1:0] == 2'b11));
//Conditional branch
//True for BRANCH
//False for JAL/JALR
wire co_cond_branch = !opcode[0];
wire co_ctrl_utype = !opcode[4] & opcode[2] & opcode[0];
wire co_ctrl_jal_or_jalr = opcode[4] & opcode[0];
//PC-relative operations
//True for jal, b* auipc
//False for jalr, lui
wire co_ctrl_pc_rel = (opcode[2:0] == 3'b000) |
(opcode[1:0] == 2'b11) |
(opcode[4:3] == 2'b00);
//Write to RD
//True for OP-IMM, AUIPC, OP, LUI, SYSTEM, JALR, JAL, LOAD
//False for STORE, BRANCH, MISC-MEM
wire co_rd_op = (opcode[2] |
(!opcode[2] & opcode[4] & opcode[0]) |
(!opcode[2] & !opcode[3] & !opcode[0]));
//
//funct3
//
wire co_sh_right = funct3[2];
wire co_bne_or_bge = funct3[0];
//Matches system ops except eceall/ebreak/mret
wire csr_op = opcode[4] & opcode[2] & (|funct3);
//op20
wire co_ebreak = op20;
//opcode & funct3 & op21
wire co_ctrl_mret = opcode[4] & opcode[2] & op21 & !(|funct3);
//Matches system opcodes except CSR accesses (funct3 == 0)
//and mret (!op21)
wire co_e_op = opcode[4] & opcode[2] & !op21 & !(|funct3);
//opcode & funct3 & imm30
wire co_bufreg_sh_signed = imm30;
/*
True for sub, b*, slt*
False for add*
op opcode f3 i30
b* 11000 xxx x t
addi 00100 000 x f
slt* 0x100 01x x t
add 01100 000 0 f
sub 01100 000 1 t
*/
wire co_alu_sub = funct3[1] | funct3[0] | (opcode[3] & imm30) | opcode[4];
//csr_op matches system ops except eceall/ebreak/mret
//e_op matches system opcodes except CSR accesses (funct3 == 0) and mret (!op21)
wire co_rd_csr_en = opcode[4] & opcode[2] & (|funct3);
wire co_ctrl_mret = opcode[4] & opcode[2] & !(|funct3) & op21;
wire co_e_op = opcode[4] & opcode[2] & !(|funct3) & !op21;
/*
Bits 26, 22, 21 and 20 are enough to uniquely identify the eight supported CSR regs
@ -182,55 +66,17 @@ module serv_decode
//true for mtvec,mscratch,mepc and mtval
//false for mstatus, mie, mcause
wire csr_valid = op20 | (op26 & !op21);
wire co_csr_en = op20 | (op26 & !op21);
wire co_rd_csr_en = csr_op;
wire co_csr_en = csr_op & csr_valid;
wire co_csr_mstatus_en = csr_op & !op26 & !op22;
wire co_csr_mie_en = csr_op & !op26 & op22 & !op20;
wire co_csr_mcause_en = csr_op & op21 & !op20;
wire co_csr_mstatus_en = !op26 & !op22;
wire co_csr_mie_en = !op26 & op22 & !op20;
wire co_csr_mcause_en = op21 & !op20;
wire [1:0] co_csr_source = funct3[1:0];
wire co_csr_d_sel = funct3[2];
wire co_csr_imm_en = opcode[4] & opcode[2] & funct3[2];
wire [1:0] co_csr_addr = {op26 & op20, !op26 | op21};
wire co_alu_cmp_eq = funct3[2:1] == 2'b00;
wire co_alu_cmp_sig = ~((funct3[0] & funct3[1]) | (funct3[1] & funct3[2]));
wire co_mem_cmd = opcode[3];
wire co_mem_signed = ~funct3[2];
wire co_mem_half = funct3[0];
wire [1:0] co_alu_bool_op = funct3[1:0];
wire [3:0] co_immdec_ctrl;
//True for S (STORE) or B (BRANCH) type instructions
//False for J type instructions
assign co_immdec_ctrl[0] = opcode[3:0] == 4'b1000;
//True for OP-IMM, LOAD, STORE, JALR (I S)
//False for LUI, AUIPC, JAL (U J)
assign co_immdec_ctrl[1] = (opcode[1:0] == 2'b00) | (opcode[2:1] == 2'b00);
assign co_immdec_ctrl[2] = opcode[4] & !opcode[0];
assign co_immdec_ctrl[3] = opcode[4];
wire [3:0] co_immdec_en;
assign co_immdec_en[3] = opcode[4] | opcode[3] | opcode[2] | !opcode[0]; //B I J S U
assign co_immdec_en[2] = (opcode[4] & opcode[2]) | !opcode[3] | opcode[0]; // I J U
assign co_immdec_en[1] = (opcode[2:1] == 2'b01) | (opcode[2] & opcode[0]) | co_csr_imm_en;// J U
assign co_immdec_en[0] = ~co_rd_op; //B S
wire [2:0] co_alu_rd_sel;
assign co_alu_rd_sel[0] = (funct3 == 3'b000); // Add/sub
assign co_alu_rd_sel[1] = (funct3[2:1] == 2'b01); //SLT*
assign co_alu_rd_sel[2] = funct3[2]; //Bool
//0 (OP_B_SOURCE_IMM) when OPIMM
//1 (OP_B_SOURCE_RS2) when BRANCH or OP
wire co_op_b_source = opcode[3];
generate
if (PRE_REGISTER) begin
@ -248,37 +94,9 @@ module serv_decode
end
always @(*) begin
o_sh_right = co_sh_right;
o_bne_or_bge = co_bne_or_bge;
o_cond_branch = co_cond_branch;
o_dbus_en = co_dbus_en;
o_mtval_pc = co_mtval_pc;
o_two_stage_op = co_two_stage_op;
o_e_op = co_e_op;
o_ebreak = co_ebreak;
o_branch_op = co_branch_op;
o_shift_op = co_shift_op;
o_slt_or_branch = co_slt_or_branch;
o_rd_op = co_rd_op;
o_mdu_op = co_mdu_op;
o_ext_funct3 = co_ext_funct3;
o_bufreg_rs1_en = co_bufreg_rs1_en;
o_bufreg_imm_en = co_bufreg_imm_en;
o_bufreg_clr_lsb = co_bufreg_clr_lsb;
o_bufreg_sh_signed = co_bufreg_sh_signed;
o_ctrl_jal_or_jalr = co_ctrl_jal_or_jalr;
o_ctrl_utype = co_ctrl_utype;
o_ctrl_pc_rel = co_ctrl_pc_rel;
o_ctrl_mret = co_ctrl_mret;
o_alu_sub = co_alu_sub;
o_alu_bool_op = co_alu_bool_op;
o_alu_cmp_eq = co_alu_cmp_eq;
o_alu_cmp_sig = co_alu_cmp_sig;
o_alu_rd_sel = co_alu_rd_sel;
o_mem_signed = co_mem_signed;
o_mem_word = co_mem_word;
o_mem_half = co_mem_half;
o_mem_cmd = co_mem_cmd;
o_csr_en = co_csr_en;
o_csr_addr = co_csr_addr;
o_csr_mstatus_en = co_csr_mstatus_en;
@ -287,12 +105,7 @@ module serv_decode
o_csr_source = co_csr_source;
o_csr_d_sel = co_csr_d_sel;
o_csr_imm_en = co_csr_imm_en;
o_immdec_ctrl = co_immdec_ctrl;
o_immdec_en = co_immdec_en;
o_op_b_source = co_op_b_source;
o_rd_csr_en = co_rd_csr_en;
o_rd_alu_en = co_rd_alu_en;
o_rd_mem_en = co_rd_mem_en;
end
end else begin
@ -310,37 +123,9 @@ module serv_decode
always @(posedge clk) begin
if (i_wb_en) begin
o_sh_right <= co_sh_right;
o_bne_or_bge <= co_bne_or_bge;
o_cond_branch <= co_cond_branch;
o_e_op <= co_e_op;
o_ebreak <= co_ebreak;
o_two_stage_op <= co_two_stage_op;
o_dbus_en <= co_dbus_en;
o_mtval_pc <= co_mtval_pc;
o_branch_op <= co_branch_op;
o_shift_op <= co_shift_op;
o_slt_or_branch <= co_slt_or_branch;
o_rd_op <= co_rd_op;
o_mdu_op <= co_mdu_op;
o_ext_funct3 <= co_ext_funct3;
o_bufreg_rs1_en <= co_bufreg_rs1_en;
o_bufreg_imm_en <= co_bufreg_imm_en;
o_bufreg_clr_lsb <= co_bufreg_clr_lsb;
o_bufreg_sh_signed <= co_bufreg_sh_signed;
o_ctrl_jal_or_jalr <= co_ctrl_jal_or_jalr;
o_ctrl_utype <= co_ctrl_utype;
o_ctrl_pc_rel <= co_ctrl_pc_rel;
o_ctrl_mret <= co_ctrl_mret;
o_alu_sub <= co_alu_sub;
o_alu_bool_op <= co_alu_bool_op;
o_alu_cmp_eq <= co_alu_cmp_eq;
o_alu_cmp_sig <= co_alu_cmp_sig;
o_alu_rd_sel <= co_alu_rd_sel;
o_mem_signed <= co_mem_signed;
o_mem_word <= co_mem_word;
o_mem_half <= co_mem_half;
o_mem_cmd <= co_mem_cmd;
o_csr_en <= co_csr_en;
o_csr_addr <= co_csr_addr;
o_csr_mstatus_en <= co_csr_mstatus_en;
@ -349,12 +134,7 @@ module serv_decode
o_csr_source <= co_csr_source;
o_csr_d_sel <= co_csr_d_sel;
o_csr_imm_en <= co_csr_imm_en;
o_immdec_ctrl <= co_immdec_ctrl;
o_immdec_en <= co_immdec_en;
o_op_b_source <= co_op_b_source;
o_rd_csr_en <= co_rd_csr_en;
o_rd_alu_en <= co_rd_alu_en;
o_rd_mem_en <= co_rd_mem_en;
end
end

658
rtl/serv_mem_decode.v Normal file
View file

@ -0,0 +1,658 @@
module serv_auto_decode
#(parameter [0:0] MDU = 1'b0,
parameter [0:0] CSR = 1'b0)
(
input wire i_clk,
//Input
input wire i_en,
input wire i_imm30,
input wire [2:0] i_funct3,
input wire [4:0] i_opcode,
//MDU/Ext/CSR
input wire i_imm25,
output reg [2:0] o_ext_funct3,
output reg o_mdu_op,
input wire i_op20,
input wire i_op21,
input wire i_op22,
input wire i_op26,
output reg o_e_op,
output reg o_ebreak,
output reg o_ctrl_mret,
output reg o_csr_en,
output reg o_csr_addr1,
output reg o_csr_addr0,
output reg o_csr_mstatus_en,
output reg o_csr_mie_en,
output reg o_csr_mcause_en,
output reg o_csr_source1,
output reg o_csr_source0,
output reg o_csr_d_sel,
output reg o_csr_imm_en,
output reg o_rd_csr_en,
//Output
output wire o_branch_op,
output wire o_ctrl_jal_or_jalr,
output wire o_slt_or_branch,
output wire o_alu_sub,
output wire o_alu_bool_op1,
output wire o_op_b_source,
output wire o_mem_cmd,
output wire o_immdec_ctrl0,
output wire o_immdec_en0,
output wire o_immdec_ctrl1,
output wire o_bufreg_rs1_en,
output wire o_immdec_ctrl2,
output wire o_cond_branch,
output wire o_immdec_ctrl3,
output wire o_two_stage_op,
output wire o_immdec_en1,
output wire o_immdec_en2,
output wire o_immdec_en3,
output wire o_bne_or_bge,
output wire o_rd_alu_en,
output wire o_sh_right,
output wire o_alu_cmp_sig,
output wire o_mem_signed,
output wire o_shift_op,
output wire o_alu_bool_op0,
output wire o_rd_mem_en,
output wire o_dbus_en,
output wire o_bufreg_imm_en,
output wire o_alu_rd_sel0,
output wire o_bufreg_clr_lsb,
output wire o_ctrl_pc_rel,
output wire o_alu_rd_sel1,
output wire o_bufreg_sh_signed,
output wire o_alu_cmp_eq,
output wire o_mem_half,
output wire o_ctrl_utype,
output wire o_rd_op,
output wire o_alu_rd_sel2,
output wire o_mem_word);
(* ram_style = "block" *) reg [19:0] mem [0:511];
reg [19:0] d;
initial begin
mem[0] = 20'h46b50;
mem[1] = 20'h00000;
mem[2] = 20'h00000;
mem[3] = 20'h00000;
mem[4] = 20'h44710;
mem[5] = 20'h68380;
mem[6] = 20'h00000;
mem[7] = 20'h00000;
mem[8] = 20'h0625c;
mem[9] = 20'h00000;
mem[10] = 20'h00000;
mem[11] = 20'h00000;
mem[12] = 20'h44404;
mem[13] = 20'h60380;
mem[14] = 20'h00000;
mem[15] = 20'h00000;
mem[16] = 20'h00000;
mem[17] = 20'h00000;
mem[18] = 20'h00000;
mem[19] = 20'h00000;
mem[20] = 20'h00000;
mem[21] = 20'h00000;
mem[22] = 20'h00000;
mem[23] = 20'h00000;
mem[24] = 20'h1c26f;
mem[25] = 20'h44157;
mem[26] = 20'h00000;
mem[27] = 20'h4c3c7;
mem[28] = 20'h00000;
mem[29] = 20'h00000;
mem[30] = 20'h00000;
mem[31] = 20'h00000;
mem[32] = 20'h56b50;
mem[33] = 20'h00000;
mem[34] = 20'h00000;
mem[35] = 20'h00000;
mem[36] = 20'h41750;
mem[37] = 20'h68380;
mem[38] = 20'h00000;
mem[39] = 20'h00000;
mem[40] = 20'h1625c;
mem[41] = 20'h00000;
mem[42] = 20'h00000;
mem[43] = 20'h00000;
mem[44] = 20'h41454;
mem[45] = 20'h60380;
mem[46] = 20'h00000;
mem[47] = 20'h00000;
mem[48] = 20'h00000;
mem[49] = 20'h00000;
mem[50] = 20'h00000;
mem[51] = 20'h00000;
mem[52] = 20'h00000;
mem[53] = 20'h00000;
mem[54] = 20'h00000;
mem[55] = 20'h00000;
mem[56] = 20'h1c66f;
mem[57] = 20'h44157;
mem[58] = 20'h00000;
mem[59] = 20'h4c3c7;
mem[60] = 20'h00000;
mem[61] = 20'h00000;
mem[62] = 20'h00000;
mem[63] = 20'h00000;
mem[64] = 20'hc6350;
mem[65] = 20'h00000;
mem[66] = 20'h00000;
mem[67] = 20'h00000;
mem[68] = 20'h48f52;
mem[69] = 20'h68380;
mem[70] = 20'h00000;
mem[71] = 20'h00000;
mem[72] = 20'h8625c;
mem[73] = 20'h00000;
mem[74] = 20'h00000;
mem[75] = 20'h00000;
mem[76] = 20'h48c46;
mem[77] = 20'h60380;
mem[78] = 20'h00000;
mem[79] = 20'h00000;
mem[80] = 20'h00000;
mem[81] = 20'h00000;
mem[82] = 20'h00000;
mem[83] = 20'h00000;
mem[84] = 20'h00000;
mem[85] = 20'h00000;
mem[86] = 20'h00000;
mem[87] = 20'h00000;
mem[88] = 20'h00000;
mem[89] = 20'h44157;
mem[90] = 20'h00000;
mem[91] = 20'h4c3c7;
mem[92] = 20'h00000;
mem[93] = 20'h00000;
mem[94] = 20'h00000;
mem[95] = 20'h00000;
mem[96] = 20'h00000;
mem[97] = 20'h00000;
mem[98] = 20'h00000;
mem[99] = 20'h00000;
mem[100] = 20'h48752;
mem[101] = 20'h68380;
mem[102] = 20'h00000;
mem[103] = 20'h00000;
mem[104] = 20'h00000;
mem[105] = 20'h00000;
mem[106] = 20'h00000;
mem[107] = 20'h00000;
mem[108] = 20'h48446;
mem[109] = 20'h60380;
mem[110] = 20'h00000;
mem[111] = 20'h00000;
mem[112] = 20'h00000;
mem[113] = 20'h00000;
mem[114] = 20'h00000;
mem[115] = 20'h00000;
mem[116] = 20'h00000;
mem[117] = 20'h00000;
mem[118] = 20'h00000;
mem[119] = 20'h00000;
mem[120] = 20'h00000;
mem[121] = 20'h44157;
mem[122] = 20'h00000;
mem[123] = 20'h4c3c7;
mem[124] = 20'h00000;
mem[125] = 20'h00000;
mem[126] = 20'h00000;
mem[127] = 20'h00000;
mem[128] = 20'h46350;
mem[129] = 20'h00000;
mem[130] = 20'h00000;
mem[131] = 20'h00000;
mem[132] = 20'hc0710;
mem[133] = 20'h68380;
mem[134] = 20'h00000;
mem[135] = 20'h00000;
mem[136] = 20'h00000;
mem[137] = 20'h00000;
mem[138] = 20'h00000;
mem[139] = 20'h00000;
mem[140] = 20'hc0404;
mem[141] = 20'h60380;
mem[142] = 20'h00000;
mem[143] = 20'h00000;
mem[144] = 20'h00000;
mem[145] = 20'h00000;
mem[146] = 20'h00000;
mem[147] = 20'h00000;
mem[148] = 20'h00000;
mem[149] = 20'h00000;
mem[150] = 20'h00000;
mem[151] = 20'h00000;
mem[152] = 20'h0ca6f;
mem[153] = 20'h44157;
mem[154] = 20'h00000;
mem[155] = 20'h4c3c7;
mem[156] = 20'h00000;
mem[157] = 20'h00000;
mem[158] = 20'h00000;
mem[159] = 20'h00000;
mem[160] = 20'h56350;
mem[161] = 20'h00000;
mem[162] = 20'h00000;
mem[163] = 20'h00000;
mem[164] = 20'h41f50;
mem[165] = 20'h68380;
mem[166] = 20'h00000;
mem[167] = 20'h00000;
mem[168] = 20'h00000;
mem[169] = 20'h00000;
mem[170] = 20'h00000;
mem[171] = 20'h00000;
mem[172] = 20'h41c54;
mem[173] = 20'h60380;
mem[174] = 20'h00000;
mem[175] = 20'h00000;
mem[176] = 20'h00000;
mem[177] = 20'h00000;
mem[178] = 20'h00000;
mem[179] = 20'h00000;
mem[180] = 20'h00000;
mem[181] = 20'h00000;
mem[182] = 20'h00000;
mem[183] = 20'h00000;
mem[184] = 20'h0ce6f;
mem[185] = 20'h44157;
mem[186] = 20'h00000;
mem[187] = 20'h4c3c7;
mem[188] = 20'h00000;
mem[189] = 20'h00000;
mem[190] = 20'h00000;
mem[191] = 20'h00000;
mem[192] = 20'h00000;
mem[193] = 20'h00000;
mem[194] = 20'h00000;
mem[195] = 20'h00000;
mem[196] = 20'hc0712;
mem[197] = 20'h68380;
mem[198] = 20'h00000;
mem[199] = 20'h00000;
mem[200] = 20'h00000;
mem[201] = 20'h00000;
mem[202] = 20'h00000;
mem[203] = 20'h00000;
mem[204] = 20'hc0406;
mem[205] = 20'h60380;
mem[206] = 20'h00000;
mem[207] = 20'h00000;
mem[208] = 20'h00000;
mem[209] = 20'h00000;
mem[210] = 20'h00000;
mem[211] = 20'h00000;
mem[212] = 20'h00000;
mem[213] = 20'h00000;
mem[214] = 20'h00000;
mem[215] = 20'h00000;
mem[216] = 20'h0c26f;
mem[217] = 20'h44157;
mem[218] = 20'h00000;
mem[219] = 20'h4c3c7;
mem[220] = 20'h00000;
mem[221] = 20'h00000;
mem[222] = 20'h00000;
mem[223] = 20'h00000;
mem[224] = 20'h00000;
mem[225] = 20'h00000;
mem[226] = 20'h00000;
mem[227] = 20'h00000;
mem[228] = 20'hc1712;
mem[229] = 20'h68380;
mem[230] = 20'h00000;
mem[231] = 20'h00000;
mem[232] = 20'h00000;
mem[233] = 20'h00000;
mem[234] = 20'h00000;
mem[235] = 20'h00000;
mem[236] = 20'hc1406;
mem[237] = 20'h60380;
mem[238] = 20'h00000;
mem[239] = 20'h00000;
mem[240] = 20'h00000;
mem[241] = 20'h00000;
mem[242] = 20'h00000;
mem[243] = 20'h00000;
mem[244] = 20'h00000;
mem[245] = 20'h00000;
mem[246] = 20'h00000;
mem[247] = 20'h00000;
mem[248] = 20'h0c66f;
mem[249] = 20'h44157;
mem[250] = 20'h00000;
mem[251] = 20'h4c3c7;
mem[252] = 20'h00000;
mem[253] = 20'h00000;
mem[254] = 20'h00000;
mem[255] = 20'h00000;
mem[256] = 20'h46b50;
mem[257] = 20'h00000;
mem[258] = 20'h00000;
mem[259] = 20'h00000;
mem[260] = 20'h44710;
mem[261] = 20'h68380;
mem[262] = 20'h00000;
mem[263] = 20'h00000;
mem[264] = 20'h0625c;
mem[265] = 20'h00000;
mem[266] = 20'h00000;
mem[267] = 20'h00000;
mem[268] = 20'h44406;
mem[269] = 20'h60380;
mem[270] = 20'h00000;
mem[271] = 20'h00000;
mem[272] = 20'h00000;
mem[273] = 20'h00000;
mem[274] = 20'h00000;
mem[275] = 20'h00000;
mem[276] = 20'h00000;
mem[277] = 20'h00000;
mem[278] = 20'h00000;
mem[279] = 20'h00000;
mem[280] = 20'h1c26f;
mem[281] = 20'h44157;
mem[282] = 20'h00000;
mem[283] = 20'h4c3c7;
mem[284] = 20'h00000;
mem[285] = 20'h00000;
mem[286] = 20'h00000;
mem[287] = 20'h00000;
mem[288] = 20'h56b50;
mem[289] = 20'h00000;
mem[290] = 20'h00000;
mem[291] = 20'h00000;
mem[292] = 20'h00000;
mem[293] = 20'h68380;
mem[294] = 20'h00000;
mem[295] = 20'h00000;
mem[296] = 20'h1625c;
mem[297] = 20'h00000;
mem[298] = 20'h00000;
mem[299] = 20'h00000;
mem[300] = 20'h00000;
mem[301] = 20'h60380;
mem[302] = 20'h00000;
mem[303] = 20'h00000;
mem[304] = 20'h00000;
mem[305] = 20'h00000;
mem[306] = 20'h00000;
mem[307] = 20'h00000;
mem[308] = 20'h00000;
mem[309] = 20'h00000;
mem[310] = 20'h00000;
mem[311] = 20'h00000;
mem[312] = 20'h1c66f;
mem[313] = 20'h44157;
mem[314] = 20'h00000;
mem[315] = 20'h4c3c7;
mem[316] = 20'h00000;
mem[317] = 20'h00000;
mem[318] = 20'h00000;
mem[319] = 20'h00000;
mem[320] = 20'hc6350;
mem[321] = 20'h00000;
mem[322] = 20'h00000;
mem[323] = 20'h00000;
mem[324] = 20'h48f52;
mem[325] = 20'h68380;
mem[326] = 20'h00000;
mem[327] = 20'h00000;
mem[328] = 20'h8625c;
mem[329] = 20'h00000;
mem[330] = 20'h00000;
mem[331] = 20'h00000;
mem[332] = 20'h00000;
mem[333] = 20'h60380;
mem[334] = 20'h00000;
mem[335] = 20'h00000;
mem[336] = 20'h00000;
mem[337] = 20'h00000;
mem[338] = 20'h00000;
mem[339] = 20'h00000;
mem[340] = 20'h00000;
mem[341] = 20'h00000;
mem[342] = 20'h00000;
mem[343] = 20'h00000;
mem[344] = 20'h00000;
mem[345] = 20'h44157;
mem[346] = 20'h00000;
mem[347] = 20'h4c3c7;
mem[348] = 20'h00000;
mem[349] = 20'h00000;
mem[350] = 20'h00000;
mem[351] = 20'h00000;
mem[352] = 20'h00000;
mem[353] = 20'h00000;
mem[354] = 20'h00000;
mem[355] = 20'h00000;
mem[356] = 20'h48752;
mem[357] = 20'h68380;
mem[358] = 20'h00000;
mem[359] = 20'h00000;
mem[360] = 20'h00000;
mem[361] = 20'h00000;
mem[362] = 20'h00000;
mem[363] = 20'h00000;
mem[364] = 20'h00000;
mem[365] = 20'h60380;
mem[366] = 20'h00000;
mem[367] = 20'h00000;
mem[368] = 20'h00000;
mem[369] = 20'h00000;
mem[370] = 20'h00000;
mem[371] = 20'h00000;
mem[372] = 20'h00000;
mem[373] = 20'h00000;
mem[374] = 20'h00000;
mem[375] = 20'h00000;
mem[376] = 20'h00000;
mem[377] = 20'h44157;
mem[378] = 20'h00000;
mem[379] = 20'h4c3c7;
mem[380] = 20'h00000;
mem[381] = 20'h00000;
mem[382] = 20'h00000;
mem[383] = 20'h00000;
mem[384] = 20'h46350;
mem[385] = 20'h00000;
mem[386] = 20'h00000;
mem[387] = 20'h00000;
mem[388] = 20'hc0710;
mem[389] = 20'h68380;
mem[390] = 20'h00000;
mem[391] = 20'h00000;
mem[392] = 20'h00000;
mem[393] = 20'h00000;
mem[394] = 20'h00000;
mem[395] = 20'h00000;
mem[396] = 20'h00000;
mem[397] = 20'h60380;
mem[398] = 20'h00000;
mem[399] = 20'h00000;
mem[400] = 20'h00000;
mem[401] = 20'h00000;
mem[402] = 20'h00000;
mem[403] = 20'h00000;
mem[404] = 20'h00000;
mem[405] = 20'h00000;
mem[406] = 20'h00000;
mem[407] = 20'h00000;
mem[408] = 20'h0ca6f;
mem[409] = 20'h44157;
mem[410] = 20'h00000;
mem[411] = 20'h4c3c7;
mem[412] = 20'h00000;
mem[413] = 20'h00000;
mem[414] = 20'h00000;
mem[415] = 20'h00000;
mem[416] = 20'h56350;
mem[417] = 20'h00000;
mem[418] = 20'h00000;
mem[419] = 20'h00000;
mem[420] = 20'h51f50;
mem[421] = 20'h68380;
mem[422] = 20'h00000;
mem[423] = 20'h00000;
mem[424] = 20'h00000;
mem[425] = 20'h00000;
mem[426] = 20'h00000;
mem[427] = 20'h00000;
mem[428] = 20'h51c54;
mem[429] = 20'h60380;
mem[430] = 20'h00000;
mem[431] = 20'h00000;
mem[432] = 20'h00000;
mem[433] = 20'h00000;
mem[434] = 20'h00000;
mem[435] = 20'h00000;
mem[436] = 20'h00000;
mem[437] = 20'h00000;
mem[438] = 20'h00000;
mem[439] = 20'h00000;
mem[440] = 20'h0ce6f;
mem[441] = 20'h44157;
mem[442] = 20'h00000;
mem[443] = 20'h4c3c7;
mem[444] = 20'h00000;
mem[445] = 20'h00000;
mem[446] = 20'h00000;
mem[447] = 20'h00000;
mem[448] = 20'h00000;
mem[449] = 20'h00000;
mem[450] = 20'h00000;
mem[451] = 20'h00000;
mem[452] = 20'hc0712;
mem[453] = 20'h68380;
mem[454] = 20'h00000;
mem[455] = 20'h00000;
mem[456] = 20'h00000;
mem[457] = 20'h00000;
mem[458] = 20'h00000;
mem[459] = 20'h00000;
mem[460] = 20'h00000;
mem[461] = 20'h60380;
mem[462] = 20'h00000;
mem[463] = 20'h00000;
mem[464] = 20'h00000;
mem[465] = 20'h00000;
mem[466] = 20'h00000;
mem[467] = 20'h00000;
mem[468] = 20'h00000;
mem[469] = 20'h00000;
mem[470] = 20'h00000;
mem[471] = 20'h00000;
mem[472] = 20'h0c26f;
mem[473] = 20'h44157;
mem[474] = 20'h00000;
mem[475] = 20'h4c3c7;
mem[476] = 20'h00000;
mem[477] = 20'h00000;
mem[478] = 20'h00000;
mem[479] = 20'h00000;
mem[480] = 20'h00000;
mem[481] = 20'h00000;
mem[482] = 20'h00000;
mem[483] = 20'h00000;
mem[484] = 20'hc1712;
mem[485] = 20'h68380;
mem[486] = 20'h00000;
mem[487] = 20'h00000;
mem[488] = 20'h00000;
mem[489] = 20'h00000;
mem[490] = 20'h00000;
mem[491] = 20'h00000;
mem[492] = 20'h00000;
mem[493] = 20'h60380;
mem[494] = 20'h00000;
mem[495] = 20'h00000;
mem[496] = 20'h00000;
mem[497] = 20'h00000;
mem[498] = 20'h00000;
mem[499] = 20'h00000;
mem[500] = 20'h00000;
mem[501] = 20'h00000;
mem[502] = 20'h00000;
mem[503] = 20'h00000;
mem[504] = 20'h0c66f;
mem[505] = 20'h44157;
mem[506] = 20'h00000;
mem[507] = 20'h4c3c7;
mem[508] = 20'h00000;
mem[509] = 20'h00000;
mem[510] = 20'h00000;
mem[511] = 20'h00000;
end
always @(posedge i_clk)
if (i_en)
d <= mem[{i_imm30,i_funct3,i_opcode}];
assign o_branch_op = d[0];
assign o_ctrl_jal_or_jalr = o_branch_op;
assign o_slt_or_branch = d[1];
assign o_alu_sub = o_slt_or_branch;
assign o_alu_bool_op1 = o_slt_or_branch;
assign o_op_b_source = d[2];
assign o_mem_cmd = o_op_b_source;
assign o_immdec_ctrl0 = d[3];
assign o_immdec_en0 = o_immdec_ctrl0;
assign o_immdec_ctrl1 = d[4];
assign o_bufreg_rs1_en = o_immdec_ctrl1;
assign o_immdec_ctrl2 = d[5];
assign o_cond_branch = o_immdec_ctrl2;
assign o_immdec_ctrl3 = d[6];
assign o_two_stage_op = o_immdec_ctrl3;
assign o_immdec_en1 = d[7];
assign o_immdec_en2 = d[8];
assign o_immdec_en3 = d[9];
assign o_bne_or_bge = d[10];
assign o_rd_alu_en = o_bne_or_bge;
assign o_sh_right = d[11];
assign o_alu_cmp_sig = o_sh_right;
assign o_mem_signed = o_sh_right;
assign o_shift_op = d[12];
assign o_alu_bool_op0 = o_shift_op;
assign o_rd_mem_en = d[13];
assign o_dbus_en = o_rd_mem_en;
assign o_bufreg_imm_en = d[14];
assign o_alu_rd_sel0 = o_bufreg_imm_en;
assign o_bufreg_clr_lsb = d[15];
assign o_ctrl_pc_rel = o_bufreg_clr_lsb;
assign o_alu_rd_sel1 = o_bufreg_clr_lsb;
assign o_bufreg_sh_signed = d[16];
assign o_alu_cmp_eq = o_bufreg_sh_signed;
assign o_mem_half = o_bufreg_sh_signed;
assign o_ctrl_utype = d[17];
assign o_rd_op = d[18];
assign o_alu_rd_sel2 = d[19];
assign o_mem_word = o_alu_rd_sel2;
always @(posedge i_clk) begin
if (i_en) begin
//MDU/CSR/Ext
o_mdu_op <= MDU & (i_opcode == 5'b01100) & i_imm25;
o_ext_funct3 <= MDU ? i_funct3 : 3'b000;
o_ebreak <= CSR & (i_op20);
o_rd_csr_en <= CSR & (i_opcode[4] & i_opcode[2] & (|i_funct3));
o_ctrl_mret <= CSR & (i_opcode[4] & i_opcode[2] & !(|i_funct3) & i_op21);
o_e_op <= CSR & (i_opcode[4] & i_opcode[2] & !(|i_funct3) & !i_op21);
o_csr_en <= CSR & (i_op20 | (i_op26 & !i_op21));
o_csr_mstatus_en <= CSR & (!i_op26 & !i_op22);
o_csr_mie_en <= CSR & (!i_op26 & i_op22 & !i_op20);
o_csr_mcause_en <= CSR & ( i_op21 & !i_op20);
o_csr_source1 <= CSR & (i_funct3[1]);
o_csr_source0 <= CSR & (i_funct3[0]);
o_csr_d_sel <= CSR & (i_funct3[2]);
o_csr_imm_en <= CSR & (i_opcode[4] & i_opcode[2] & i_funct3[2]);
o_csr_addr1 <= CSR & (i_op26 & i_op20);
o_csr_addr0 <= CSR & (!i_op26 | i_op21);
end
end
endmodule

177
rtl/serv_post_reg_decode.v Normal file
View file

@ -0,0 +1,177 @@
module serv_auto_decode
#(parameter [0:0] MDU = 1'b0)
(
input wire i_clk,
//Input
input wire i_en,
input wire i_imm30,
input wire [2:0] i_funct3,
input wire [4:0] i_opcode,
//MDU/Ext/CSR
input wire i_imm25,
output reg [2:0] o_ext_funct3,
output reg o_mdu_op,
input wire i_op20,
input wire i_op21,
input wire i_op22,
input wire i_op26,
output reg o_e_op,
output reg o_ebreak,
output reg o_ctrl_mret,
output reg o_csr_en,
output reg o_csr_addr1,
output reg o_csr_addr0,
output reg o_csr_mstatus_en,
output reg o_csr_mie_en,
output reg o_csr_mcause_en,
output reg o_csr_source1,
output reg o_csr_source0,
output reg o_csr_d_sel,
output reg o_csr_imm_en,
output reg o_rd_csr_en,
//Output
output reg o_branch_op,
output wire o_ctrl_jal_or_jalr,
output reg o_slt_or_branch,
output wire o_alu_rd_sel1,
output reg o_op_b_source,
output wire o_immdec_ctrl3,
output reg o_immdec_ctrl0,
output wire o_immdec_en0,
output reg o_immdec_ctrl1,
output wire o_bufreg_rs1_en,
output reg o_immdec_ctrl2,
output wire o_cond_branch,
output reg o_immdec_en1,
output reg o_immdec_en2,
output reg o_immdec_en3,
output reg o_bne_or_bge,
output wire o_rd_alu_en,
output reg o_sh_right,
output wire o_alu_cmp_sig,
output wire o_mem_signed,
output reg o_shift_op,
output wire o_alu_bool_op0,
output reg o_two_stage_op,
output reg o_rd_mem_en,
output wire o_dbus_en,
output reg o_bufreg_imm_en,
output wire o_alu_rd_sel0,
output reg o_bufreg_clr_lsb,
output wire o_ctrl_pc_rel,
output wire o_alu_sub,
output wire o_alu_bool_op1,
output reg o_bufreg_sh_signed,
output wire o_alu_cmp_eq,
output wire o_mem_word,
output reg o_ctrl_utype,
output wire o_mem_cmd,
output reg o_rd_op,
output reg o_alu_rd_sel2,
output wire o_mem_half);
// lajjbbbbbblllllsssassxoasssassssxssoa
// uuaaenlglgbhwbhbhwdllornlrrdulllorrrn
// iillqetete uu dttridlladblttrla d
// p r uu iiii iiii u
// c u
//branch_op |0011111111000000000000000000000000000|
//slt_or_branch | 11111111000000000110000000001100000|
//op_b_source |0011111111000001110000000001111111111|
//immdec_ctrl0 |0000111111000001110000000000000000000|
//immdec_ctrl1 |000100000011111111111111111 1 11 |
//immdec_ctrl2 |000011111100000000000000000 |
//immdec_en1 |1110000000000000000000000000000000000|
//immdec_en2 |1111000000111110001111111110000000000|
//immdec_en3 |1110111111111111111111111110000000000|
//bne_or_bge |000001010100000 1111111111111111111|
//sh_right | 110011 00 10 011 010 11 |
//shift_op | 0000000000000000 00001111 10001101|
//two_stage_op |0011111111111111110110001110011101100|
//rd_mem_en |0000000000111111110000000000000000000|
//bufreg_imm_en | 11111111111111111000000001100000000|
//bufreg_clr_lsb |0110111111000000000110110000101100011|
//bufreg_sh_signed | 11000000100001 00 01 00 01 |
//ctrl_utype |1100000000000001110000000000000000000|
//rd_op |1111000000111110001111111111111111111|
//alu_rd_sel2 | 010010100001110000000010011|
//20 signals
//
always @(posedge i_clk)
if (i_en) begin
o_branch_op <= i_opcode[4];
o_slt_or_branch <= i_opcode[4] | (i_funct3[1] & i_opcode[2] & ~i_funct3[2]);
o_op_b_source <= i_opcode[4] | (i_opcode[3] & ~i_opcode[0]);
o_immdec_ctrl0 <= i_opcode[3] & ~i_opcode[0] & ~i_opcode[2];
o_immdec_ctrl1 <= (~i_opcode[0] & ~i_opcode[4]) | (i_opcode[0] & ~i_opcode[1] & ~i_opcode[2]);
o_immdec_ctrl2 <= i_opcode[4] & ~i_opcode[0];
o_immdec_en1 <= i_opcode[1] | (i_opcode[0] & ~i_opcode[4]);
o_immdec_en2 <= i_opcode[0] | ~i_opcode[3];
o_immdec_en3 <= i_opcode[1] | ~i_opcode[3] | (i_opcode[0] & ~i_opcode[4]) | (~i_opcode[0] & ~i_opcode[2]);
o_bne_or_bge <= (i_opcode[2] & ~i_opcode[0]) | (i_funct3[0] & i_opcode[3] & ~i_opcode[0]);
o_sh_right <= (i_funct3[2] & i_opcode[2]) | (i_opcode[4] & ~i_funct3[1]) | (~i_funct3[0] & ~i_funct3[2]) | (~i_funct3[2] & ~i_opcode[2]);
o_shift_op <= (i_funct3[0] & i_funct3[2] & i_opcode[2]) | (i_funct3[0] & i_opcode[2] & ~i_funct3[1]);
o_two_stage_op <= ~i_opcode[2] | (i_funct3[0] & ~i_funct3[1] & ~i_opcode[0]) | (i_funct3[1] & ~i_funct3[2] & ~i_opcode[0]);
o_rd_mem_en <= ~i_opcode[2] & ~i_opcode[4];
o_bufreg_imm_en <= ~i_opcode[2] | (~i_funct3[0] & ~i_funct3[1] & ~i_funct3[2]);
o_bufreg_clr_lsb <= i_opcode[1] | (i_opcode[0] & ~i_opcode[3]) | (i_opcode[4] & ~i_opcode[0]) | (i_funct3[1] & i_opcode[2] & ~i_opcode[0]) | (i_imm30 & i_opcode[2] & i_opcode[3] & ~i_funct3[2] & ~i_opcode[0]);
o_bufreg_sh_signed <= (i_opcode[4] & ~i_funct3[2]) | (i_imm30 & i_opcode[2] & ~i_funct3[1]) | (i_funct3[1] & ~i_funct3[2] & ~i_opcode[2]);
o_ctrl_utype <= (i_opcode[0] & ~i_opcode[4]) | (i_opcode[3] & ~i_opcode[2] & ~i_opcode[4]);
o_rd_op <= i_opcode[0] | i_opcode[2] | ~i_opcode[3];
o_alu_rd_sel2 <= (i_funct3[1] & i_funct3[2]) | (i_funct3[0] & ~i_opcode[2]) | (i_funct3[2] & i_opcode[2] & ~i_funct3[0]);
//MDU/CSR/Ext
o_mdu_op <= MDU & (i_opcode == 5'b01100) & i_imm25;
// o_ext_funct3 <= i_funct3;
o_ebreak <= i_op20;
o_ctrl_mret <= i_opcode[4] & i_opcode[2] & !(|i_funct3) & i_op21;
o_e_op <= i_opcode[4] & i_opcode[2] & !(|i_funct3) & !i_op21;
/*
o_rd_csr_en <= i_opcode[4] & i_opcode[2] & (|i_funct3);
o_csr_en <= i_op20 | (i_op26 & !i_op21);
o_csr_mstatus_en <= !i_op26 & !i_op22;
o_csr_mie_en <= !i_op26 & i_op22 & !i_op20;
o_csr_mcause_en <= i_op21 & !i_op20;
o_csr_source1 <= i_funct3[1];
o_csr_source0 <= i_funct3[0];
o_csr_d_sel <= i_funct3[2];
o_csr_imm_en <= i_opcode[4] & i_opcode[2] & i_funct3[2];
o_csr_addr1 <= i_op26 & i_op20;
o_csr_addr0 <= !i_op26 | i_op21;
*/end
always @(*) begin
o_ext_funct3 <= 3'd0;
o_rd_csr_en <= 1'b0;
o_csr_en <= 1'b0;
o_csr_mstatus_en <= 1'b0;
o_csr_mie_en <= 1'b0;
o_csr_mcause_en <= 1'b0;
o_csr_source1 <= 1'b0;
o_csr_source0 <= 1'b0;
o_csr_d_sel <= 1'b0;
o_csr_imm_en <= 1'b0;
o_csr_addr1 <= 1'b0;
o_csr_addr0 <= 1'b0;
end
assign o_ctrl_jal_or_jalr = o_branch_op;
assign o_alu_rd_sel1 = o_slt_or_branch;
assign o_immdec_ctrl3 = o_op_b_source;
assign o_immdec_en0 = o_immdec_ctrl0;
assign o_bufreg_rs1_en = o_immdec_ctrl1;
assign o_cond_branch = o_immdec_ctrl2;
assign o_rd_alu_en = o_bne_or_bge;
assign o_alu_cmp_sig = o_sh_right;
assign o_mem_signed = o_sh_right;
assign o_alu_bool_op0 = o_shift_op;
assign o_dbus_en = o_rd_mem_en;
assign o_alu_rd_sel0 = o_bufreg_imm_en;
assign o_ctrl_pc_rel = o_bufreg_clr_lsb;
assign o_alu_sub = o_bufreg_clr_lsb;
assign o_alu_bool_op1 = o_bufreg_clr_lsb;
assign o_alu_cmp_eq = o_bufreg_sh_signed;
assign o_mem_word = o_bufreg_sh_signed;
assign o_mem_cmd = o_ctrl_utype;
assign o_mem_half = o_alu_rd_sel2;
endmodule

152
rtl/serv_pre_reg_decode.v Normal file
View file

@ -0,0 +1,152 @@
module serv_auto_decode
#(parameter [0:0] MDU = 1'b0)
(
input wire i_clk,
//Input
input wire i_en,
input wire i_imm30,
input wire [2:0] i_funct3,
input wire [4:0] i_opcode,
//MDU/Ext/CSR
input wire i_imm25,
output reg [2:0] o_ext_funct3,
output reg o_mdu_op,
input wire i_op20,
input wire i_op21,
input wire i_op22,
input wire i_op26,
output reg o_e_op,
output reg o_ebreak,
output reg o_ctrl_mret,
output reg o_csr_en,
output reg o_csr_addr1,
output reg o_csr_addr0,
output reg o_csr_mstatus_en,
output reg o_csr_mie_en,
output reg o_csr_mcause_en,
output reg o_csr_source1,
output reg o_csr_source0,
output reg o_csr_d_sel,
output reg o_csr_imm_en,
output reg o_rd_csr_en,
//Output
output wire o_branch_op,
output wire o_ctrl_jal_or_jalr,
output wire o_slt_or_branch,
output wire o_alu_rd_sel1,
output wire o_op_b_source,
output wire o_immdec_ctrl3,
output wire o_immdec_ctrl0,
output wire o_immdec_en0,
output wire o_immdec_ctrl1,
output wire o_bufreg_rs1_en,
output wire o_immdec_ctrl2,
output wire o_cond_branch,
output wire o_immdec_en1,
output wire o_immdec_en2,
output wire o_immdec_en3,
output wire o_bne_or_bge,
output wire o_rd_alu_en,
output wire o_sh_right,
output wire o_alu_cmp_sig,
output wire o_mem_signed,
output wire o_shift_op,
output wire o_alu_bool_op0,
output wire o_two_stage_op,
output wire o_rd_mem_en,
output wire o_dbus_en,
output wire o_bufreg_imm_en,
output wire o_alu_rd_sel0,
output wire o_bufreg_clr_lsb,
output wire o_ctrl_pc_rel,
output wire o_alu_sub,
output wire o_alu_bool_op1,
output wire o_bufreg_sh_signed,
output wire o_alu_cmp_eq,
output wire o_mem_word,
output wire o_ctrl_utype,
output wire o_mem_cmd,
output wire o_rd_op,
output wire o_alu_rd_sel2,
output wire o_mem_half);
reg imm30;
reg [2:0] funct3;
reg [4:0] opcode;
always @(posedge i_clk)
if (i_en) begin
imm30 <= i_imm30;
funct3 <= i_funct3;
opcode <= i_opcode;
end
assign o_branch_op = opcode[4];
assign o_ctrl_jal_or_jalr = o_branch_op; assign o_slt_or_branch = opcode[4] | (funct3[1] & opcode[2] & ~funct3[2]);
assign o_alu_rd_sel1 = o_slt_or_branch; assign o_op_b_source = opcode[4] | (opcode[3] & ~opcode[0]);
assign o_immdec_ctrl3 = o_op_b_source; assign o_immdec_ctrl0 = opcode[3] & ~opcode[0] & ~opcode[2];
assign o_immdec_en0 = o_immdec_ctrl0; assign o_immdec_ctrl1 = (~opcode[0] & ~opcode[4]) | (opcode[0] & ~opcode[1] & ~opcode[2]);
assign o_bufreg_rs1_en = o_immdec_ctrl1; assign o_immdec_ctrl2 = opcode[4] & ~opcode[0];
assign o_cond_branch = o_immdec_ctrl2; assign o_immdec_en1 = opcode[1] | (opcode[0] & ~opcode[4]);
assign o_immdec_en2 = opcode[0] | ~opcode[3];
assign o_immdec_en3 = opcode[1] | ~opcode[3] | (opcode[0] & ~opcode[4]) | (~opcode[0] & ~opcode[2]);
assign o_bne_or_bge = (opcode[2] & ~opcode[0]) | (funct3[0] & opcode[3] & ~opcode[0]);
assign o_rd_alu_en = o_bne_or_bge; assign o_sh_right = (funct3[2] & opcode[2]) | (opcode[4] & ~funct3[1]) | (~funct3[0] & ~funct3[2]) | (~funct3[2] & ~opcode[2]);
assign o_alu_cmp_sig = o_sh_right; assign o_mem_signed = o_sh_right; assign o_shift_op = (funct3[0] & funct3[2] & opcode[2]) | (funct3[0] & opcode[2] & ~funct3[1]);
assign o_alu_bool_op0 = o_shift_op; assign o_two_stage_op = ~opcode[2] | (funct3[0] & ~funct3[1] & ~opcode[0]) | (funct3[1] & ~funct3[2] & ~opcode[0]);
assign o_rd_mem_en = ~opcode[2] & ~opcode[4];
assign o_dbus_en = o_rd_mem_en; assign o_bufreg_imm_en = ~opcode[2] | (~funct3[0] & ~funct3[1] & ~funct3[2]);
assign o_alu_rd_sel0 = o_bufreg_imm_en; assign o_bufreg_clr_lsb = opcode[1] | (opcode[0] & ~opcode[3]) | (opcode[4] & ~opcode[0]) | (funct3[1] & opcode[2] & ~opcode[0]) | (imm30 & opcode[2] & opcode[3] & ~funct3[2] & ~opcode[0]);
assign o_ctrl_pc_rel = o_bufreg_clr_lsb; assign o_alu_sub = o_bufreg_clr_lsb; assign o_alu_bool_op1 = o_bufreg_clr_lsb; assign o_bufreg_sh_signed = (opcode[4] & ~funct3[2]) | (imm30 & opcode[2] & ~funct3[1]) | (funct3[1] & ~funct3[2] & ~opcode[2]);
assign o_alu_cmp_eq = o_bufreg_sh_signed; assign o_mem_word = o_bufreg_sh_signed; assign o_ctrl_utype = (opcode[0] & ~opcode[4]) | (opcode[3] & ~opcode[2] & ~opcode[4]);
assign o_mem_cmd = o_ctrl_utype; assign o_rd_op = opcode[0] | opcode[2] | ~opcode[3];
assign o_alu_rd_sel2 = (funct3[1] & funct3[2]) | (funct3[0] & ~opcode[2]) | (funct3[2] & opcode[2] & ~funct3[0]);
assign o_mem_half = o_alu_rd_sel2;
//MDU/CSR/Ext
reg imm25;
reg op20;
reg op21;
reg op22;
reg op26;
always @(posedge i_clk)
if (i_en) begin
imm25 <= i_imm25;
funct3 <= i_funct3;
opcode <= i_opcode;
op20 <= i_op20;
op21 <= i_op21;
op22 <= i_op22;
op26 <= i_op26;
end
assign o_mdu_op = MDU & (opcode == 5'b01100) & imm25;
assign o_ext_funct3 = funct3;
assign o_ebreak = op20;
assign o_ctrl_mret = opcode[4] & opcode[2] & !(|funct3) & op21;
assign o_e_op = opcode[4] & opcode[2] & !(|funct3) & !op21;
/* assign o_rd_csr_en = opcode[4] & opcode[2] & (|funct3);
assign o_csr_en = op20 | (op26 & !op21);
assign o_csr_mstatus_en = !op26 & !op22;
assign o_csr_mie_en = !op26 & op22 & !op20;
assign o_csr_mcause_en = op21 & !op20;
assign o_csr_source1 = funct3[1];
assign o_csr_source0 = funct3[0];
assign o_csr_d_sel = funct3[2];
assign o_csr_imm_en = opcode[4] & opcode[2] & funct3[2];
assign o_csr_addr1 = op26 & op20;
assign o_csr_addr0 = !op26 | op21;
*/
assign o_rd_csr_en = 1'b0;
assign o_csr_en = 1'b0;
assign o_csr_mstatus_en = 1'b0;
assign o_csr_mie_en = 1'b0;
assign o_csr_mcause_en = 1'b0;
assign o_csr_source1 = 1'b0;
assign o_csr_source0 = 1'b0;
assign o_csr_d_sel = 1'b0;
assign o_csr_imm_en = 1'b0;
assign o_csr_addr1 = 1'b0;
assign o_csr_addr0 = 1'b0;
endmodule

View file

@ -94,7 +94,6 @@ module serv_top
wire alu_rd;
wire mem_rd;
wire csr_rd;
wire mtval_pc;
wire ctrl_pc_en;
wire jump;
@ -229,71 +228,110 @@ module serv_top
.i_rf_ready (i_rf_ready),
.o_rf_rd_en (rd_en));
serv_decode
#(.PRE_REGISTER (PRE_REGISTER),
.MDU(MDU))
decode
wire pshift_op;
wire pslt_or_branch;
wire prd_op;
wire ptwo_stage_op;
wire pbufreg_rs1_en;
wire pbufreg_imm_en;
wire pdbus_en;
wire pimmdec_en1;
wire prd_alu_en;
wire pjal_or_jalr;
wire prd_mem_en;
wire timmdec_ctrl3;
assign shift_op = pshift_op & !mdu_op;
assign slt_or_branch = pslt_or_branch & !mdu_op;
assign rd_op = prd_op | rd_csr_en;
assign two_stage_op = ptwo_stage_op & !rd_csr_en | mdu_op;
assign bufreg_rs1_en = pbufreg_rs1_en | mdu_op;
assign bufreg_imm_en = pbufreg_imm_en & !mdu_op;
assign dbus_en = pdbus_en & !mdu_op;
assign immdec_en[1] = pimmdec_en1 | csr_imm_en;
assign rd_alu_en = prd_alu_en & !rd_csr_en & !mdu_op;
assign jal_or_jalr = pjal_or_jalr & !rd_csr_en;
assign rd_mem_en = prd_mem_en /*& !rd_csr_en*/ | mdu_op;
assign immdec_ctrl[3] = timmdec_ctrl3 | rd_csr_en;
serv_auto_decode #(.MDU (MDU)) autodec
(
.clk (clk),
.i_clk (clk),
//Input
.i_wb_rdt (i_ibus_rdt[31:2]),
.i_wb_en (i_ibus_ack),
//To state
.o_bne_or_bge (bne_or_bge),
.o_cond_branch (cond_branch),
.o_dbus_en (dbus_en),
.i_imm30 (i_ibus_rdt[30]),
.i_funct3 (i_ibus_rdt[14:12]),
.i_opcode (i_ibus_rdt[6:2]),
.i_en (i_ibus_ack),
//CSR/MDU
.i_imm25 (i_ibus_rdt[25]),
.o_ext_funct3 (o_ext_funct3),
.o_mdu_op (mdu_op),
.i_op20 (i_ibus_rdt[20]),
.i_op21 (i_ibus_rdt[21]),
.i_op22 (i_ibus_rdt[22]),
.i_op26 (i_ibus_rdt[26]),
.o_e_op (e_op),
.o_ebreak (ebreak),
.o_branch_op (branch_op),
.o_shift_op (shift_op),
.o_slt_or_branch (slt_or_branch),
.o_rd_op (rd_op),
.o_sh_right (sh_right),
.o_mdu_op (mdu_op),
.o_two_stage_op (two_stage_op),
//Extension
.o_ext_funct3 (o_ext_funct3),
//To bufreg
.o_bufreg_rs1_en (bufreg_rs1_en),
.o_bufreg_imm_en (bufreg_imm_en),
.o_bufreg_clr_lsb (bufreg_clr_lsb),
.o_bufreg_sh_signed (bufreg_sh_signed),
//To bufreg2
.o_op_b_source (op_b_sel),
//To ctrl
.o_ctrl_jal_or_jalr (jal_or_jalr),
.o_ctrl_utype (utype),
.o_ctrl_pc_rel (pc_rel),
.o_ctrl_mret (mret),
//To alu
.o_alu_sub (alu_sub),
.o_alu_bool_op (alu_bool_op),
.o_alu_cmp_eq (alu_cmp_eq),
.o_alu_cmp_sig (alu_cmp_sig),
.o_alu_rd_sel (alu_rd_sel),
//To mem IF
.o_mem_cmd (o_dbus_we),
.o_mem_signed (mem_signed),
.o_mem_word (mem_word),
.o_mem_half (mem_half),
//To CSR
.o_csr_en (csr_en),
.o_csr_addr (csr_addr),
.o_csr_en (csr_en ),
.o_csr_addr1 (csr_addr[1] ),
.o_csr_addr0 (csr_addr[0] ),
.o_csr_mstatus_en (csr_mstatus_en),
.o_csr_mie_en (csr_mie_en),
.o_csr_mcause_en (csr_mcause_en),
.o_csr_source (csr_source),
.o_csr_d_sel (csr_d_sel),
.o_csr_imm_en (csr_imm_en),
.o_mtval_pc (mtval_pc ),
//To top
.o_immdec_ctrl (immdec_ctrl),
.o_immdec_en (immdec_en),
.o_csr_mie_en (csr_mie_en ),
.o_csr_mcause_en (csr_mcause_en ),
.o_csr_source1 (csr_source[1] ),
.o_csr_source0 (csr_source[0] ),
.o_csr_d_sel (csr_d_sel ),
.o_csr_imm_en (csr_imm_en ),
//To RF IF
.o_rd_mem_en (rd_mem_en),
.o_rd_csr_en (rd_csr_en),
.o_rd_alu_en (rd_alu_en));
// .o_mtval_pc (),
//To alu
.o_op_b_source (op_b_sel),
.o_sh_right (sh_right ),
.o_bne_or_bge (bne_or_bge ),
.o_cond_branch (cond_branch ),
.o_branch_op (branch_op ),
.o_shift_op (pshift_op ),
.o_slt_or_branch (pslt_or_branch),
.o_rd_op (prd_op ),
.o_two_stage_op (ptwo_stage_op ),
.o_dbus_en (pdbus_en ),
.o_bufreg_rs1_en (pbufreg_rs1_en ),
.o_bufreg_imm_en (pbufreg_imm_en ),
.o_bufreg_clr_lsb (bufreg_clr_lsb ),
.o_bufreg_sh_signed (bufreg_sh_signed),
.o_ctrl_jal_or_jalr (pjal_or_jalr ),
.o_ctrl_utype (utype ),
.o_ctrl_pc_rel (pc_rel ),
.o_alu_sub (alu_sub ),
.o_alu_bool_op1 (alu_bool_op[1]),
.o_alu_bool_op0 (alu_bool_op[0]),
.o_alu_cmp_eq (alu_cmp_eq ),
.o_alu_cmp_sig (alu_cmp_sig ),
.o_alu_rd_sel2 (alu_rd_sel[2] ),
.o_alu_rd_sel1 (alu_rd_sel[1] ),
.o_alu_rd_sel0 (alu_rd_sel[0] ),
.o_mem_signed (mem_signed ),
.o_mem_word (mem_word ),
.o_mem_half (mem_half ),
.o_mem_cmd (o_dbus_we ),
.o_immdec_ctrl0 (immdec_ctrl[0]),
.o_immdec_ctrl1 (immdec_ctrl[1]),
.o_immdec_ctrl2 (immdec_ctrl[2]),
.o_immdec_ctrl3 (timmdec_ctrl3),
.o_immdec_en0 (immdec_en[0] ),
.o_immdec_en1 (pimmdec_en1 ),
.o_immdec_en2 (immdec_en[2] ),
.o_immdec_en3 (immdec_en[3] ),
.o_rd_mem_en (prd_mem_en),
.o_rd_alu_en (prd_alu_en ));
serv_immdec immdec
(
@ -431,12 +469,12 @@ module serv_top
.i_trap (trap),
.i_mret (mret),
.i_mepc (o_ibus_adr[0]),
.i_mtval_pc (mtval_pc),
.i_mtval_pc (branch_op),
.i_bufreg_q (bufreg_q),
.i_bad_pc (bad_pc),
.o_csr_pc (csr_pc),
//CSR write port
.i_csr_en (csr_en),
.i_csr_en (csr_en & rd_csr_en),
.i_csr_addr (csr_addr),
.i_csr (csr_in),
//RD write port
@ -496,7 +534,7 @@ module serv_top
.i_cnt3 (cnt3),
.i_cnt7 (cnt7),
.i_cnt_done (cnt_done),
.i_mem_op (!mtval_pc),
.i_mem_op (dbus_en),
.i_mtip (i_timer_irq),
.i_trap (trap),
.o_new_irq (new_irq),
@ -504,9 +542,9 @@ module serv_top
.i_e_op (e_op),
.i_ebreak (ebreak),
.i_mem_cmd (o_dbus_we),
.i_mstatus_en (csr_mstatus_en),
.i_mie_en (csr_mie_en ),
.i_mcause_en (csr_mcause_en ),
.i_mstatus_en (rd_csr_en & csr_mstatus_en),
.i_mie_en (rd_csr_en & csr_mie_en ),
.i_mcause_en (rd_csr_en & csr_mcause_en ),
.i_csr_source (csr_source),
.i_mret (mret),
.i_csr_d_sel (csr_d_sel),

View file

@ -11,6 +11,7 @@ filesets:
- rtl/serv_alu.v
- rtl/serv_csr.v
- rtl/serv_ctrl.v
- rtl/serv_mem_decode.v
- rtl/serv_decode.v
- rtl/serv_immdec.v
- rtl/serv_mem_if.v

494
sw/decodegen.py Normal file
View file

@ -0,0 +1,494 @@
from sympy.logic import SOPform
from sympy import symbols
from functools import partial, reduce
from itertools import product, combinations
import networkx as nx
import z3
HEADER = """module serv_auto_decode
#(parameter [0:0] MDU = 1'b0,
parameter [0:0] CSR = 1'b0)
(
input wire i_clk,
//Input
input wire i_en,
input wire i_imm30,
input wire [2:0] i_funct3,
input wire [4:0] i_opcode,
//MDU/Ext/CSR
input wire i_imm25,
output reg [2:0] o_ext_funct3,
output reg o_mdu_op,
input wire i_op20,
input wire i_op21,
input wire i_op22,
input wire i_op26,
output reg o_e_op,
output reg o_ebreak,
output reg o_ctrl_mret,
output reg o_csr_en,
output reg o_csr_addr1,
output reg o_csr_addr0,
output reg o_csr_mstatus_en,
output reg o_csr_mie_en,
output reg o_csr_mcause_en,
output reg o_csr_source1,
output reg o_csr_source0,
output reg o_csr_d_sel,
output reg o_csr_imm_en,
output reg o_rd_csr_en,
//Output
{ports});
{body}
endmodule
"""
def printmap(ctrlmap):
s = ""
l = max([len(x) for x in ctrlmap])
s+=' '*(l+2)+"lajjbbbbbblllllsssassxoasssassssxssoa\n"
s+=' '*(l+2)+"uuaaenlglgbhwbhbhwdllornlrrdulllorrrn\n"
s+=' '*(l+2)+"iillqetete uu dttridlladblttrla d\n"
s+=' '*(l+2)+" p r uu iiii iiii u \n"
s+=' '*(l+2)+" c u \n"
for k,v in ctrlmap.items():
s += f"{k:<{l}} |{v}|\n"
s += f"{len(ctrlmap)} signals\n"
return s
def merge(d, dst, src):
l = list(d[dst])
for i in range(len(l)):
if l[i] == ' ':
l[i] = d[src][i]
elif l[i] == '1' and d[src][i] == '0':
raise Exception
elif l[i] == '0' and d[src][i] == '1':
raise Exception
d[dst] = ''.join(l)
d.pop(src)
def merge_signals(ctrlmap):
#Merge control signals and keep track of which signals that have been combined
# We build a graph of signals as nodes and merge conflicts as edges. We use z3 to find
# an optimal coloring of the graph. All nodes of the same color will have no conflicts
# and can be merged
solver = z3.Optimize()
node_colors = {}
g = nx.Graph()
color_count = z3.Int('color_count')
# Create a node for every signal
for sig in ctrlmap:
g.add_node(sig)
node_colors[sig] = node_color = z3.Int('color_' + sig)
solver.add(node_color >= 0, node_color < color_count)
# Conflicting signals may not get the same color
for sig_i, sig_j in combinations(ctrlmap, 2):
collide = any(
i != j and ' ' not in (i, j)
for i, j in zip(ctrlmap[sig_i], ctrlmap[sig_j])
)
if collide:
g.add_edge(sig_i, sig_j)
solver.add(node_colors[sig_i] != node_colors[sig_j])
# We use networkx to find the largest clique. All nodes in that clique will have to get
# distinct colors. Since the numbering of colors is arbitrary, we can without loss of
# generality decide a fixed numbering of the colors of that clique. This kind of
# symmetry breaking is essential for performance here.
for i, sig in enumerate(max(nx.find_cliques(g), key=len)):
solver.add(node_colors[sig] == i)
solver.minimize(color_count)
if solver.check() != z3.sat:
raise Exception("optmization failed") # Shouldn't happen
model = solver.model()
print(f"Found coloring using {model[color_count]} colors")
merged_signals = {}
merge_by_color = {}
for signal in list(ctrlmap):
color = model[node_colors[signal]]
if color in merge_by_color:
other_signal = merge_by_color[color]
merge(ctrlmap, other_signal, signal)
merged_signals.setdefault(other_signal, []).append(signal)
else:
merge_by_color[color] = signal
if merged_signals:
for k,v in merged_signals.items():
print(f"Merged {', '.join(v)} into {k}")
return (ctrlmap, merged_signals)
def map2signals(ctrlmap):
for k,v in ctrlmap.items():
ctrl_signals = {}
t = []
f = []
for i,op in enumerate(ops):
#Only rv32i for now
if i > 36:
continue
if v[i] == '1':
t.append(op)
elif v[i] == '0':
f.append(op)
ctrl_signals[k] = (t,f)
return ctrl_signals
def minterms(s):
return list(map(partial(reduce, lambda x, y: 2*x + y), product(*([0, 1] if z == 'x' else [int(z)] for z in s))))
def map2minterms(bitmap):
m = []
falsies = []
for i,op in enumerate(ops):
#Only rv32i for now
if i > 36:
continue
if bitmap[i] == '1':
m += minterms(ops[op])
elif bitmap[i] == '0':
falsies += minterms(ops[op])
return (m, falsies)
def write_post_reg_logic_decoder(ctrlmap, merged_signals):
signames = [
'i_imm30',
'i_funct3[2]',
'i_funct3[1]',
'i_funct3[0]',
'i_opcode[4]',
'i_opcode[3]',
'i_opcode[2]',
'i_opcode[1]',
'i_opcode[0]',
]
syms = [*symbols(' '.join(signames))]
ports = []
body = '\n'.join('//'+x for x in printmap(ctrlmap).split('\n'))
body += "\nalways @(posedge i_clk)\n"
body += " if (i_en) begin\n"
body2 =" end\n\n"
for sig, bitmap in ctrlmap.items():
#Find all conditions signals must be true and false
(t, f) = map2minterms(bitmap)
#Use Quine-McCluskey to minimize the logic expressions needed for each
#control signal. Don't cares are the ones that are neither listed as
#true or false
dc = set(range(2**9))-set(t)-set(f)
s = SOPform(syms, t, dc)
ports.append(f"output reg o_{sig}")
#Output final control signal expression
body += f" o_{sig} <= {s};\n"
if sig in merged_signals:
for alias in merged_signals[sig]:
ports.append(f"output wire o_{alias}")
body2 += f" assign o_{alias} = o_{sig};\n"
#Some extra signals
body += " //MDU/CSR/Ext\n"
body += " o_mdu_op <= MDU & (i_opcode == 5'b01100) & i_imm25;\n"
body += " o_ext_funct3 <= i_funct3;\n"
body += " o_ebreak <= i_op20;\n"
body += " o_rd_csr_en <= i_opcode[4] & i_opcode[2] & (|i_funct3);\n"
body += " o_ctrl_mret <= i_opcode[4] & i_opcode[2] & !(|i_funct3) & i_op21;\n"
body += " o_e_op <= i_opcode[4] & i_opcode[2] & !(|i_funct3) & !i_op21;\n"
body += " o_csr_en <= i_op20 | (i_op26 & !i_op21);\n"
body += " o_csr_mstatus_en <= !i_op26 & !i_op22;\n"
body += " o_csr_mie_en <= !i_op26 & i_op22 & !i_op20;\n"
body += " o_csr_mcause_en <= i_op21 & !i_op20;\n"
body += " o_csr_source1 <= i_funct3[1];\n"
body += " o_csr_source0 <= i_funct3[0];\n"
body += " o_csr_d_sel <= i_funct3[2];\n"
body += " o_csr_imm_en <= i_opcode[4] & i_opcode[2] & i_funct3[2];\n"
body += " o_csr_addr1 <= i_op26 & i_op20;\n"
body += " o_csr_addr0 <= !i_op26 | i_op21;\n"
with open('serv_post_reg_decode.v', 'w') as f:
f.write(HEADER.format(ports=',\n '.join(ports), body=body+body2+'\n'))
def write_pre_reg_logic_decoder(ctrlmap, merged_signals):
signames = [
'imm30',
'funct3[2]',
'funct3[1]',
'funct3[0]',
'opcode[4]',
'opcode[3]',
'opcode[2]',
'opcode[1]',
'opcode[0]',
]
syms = [*symbols(' '.join(signames))]
ports = []
body = """ reg imm30;
reg [2:0] funct3;
reg [4:0] opcode;
always @(posedge i_clk)
if (i_en) begin
imm30 <= i_imm30;
funct3 <= i_funct3;
opcode <= i_opcode;
end
"""
for sig, bitmap in ctrlmap.items():
#Find all conditions signals must be true and false
(t, f) = map2minterms(bitmap)
#Use Quine-McCluskey to minimize the logic expressions needed for each
#control signal. Don't cares are the ones that are neither listed as
#true or false
dc = set(range(2**9))-set(t)-set(f)
s = SOPform(syms, t, dc)
ports.append(f"output wire o_{sig}")
#Output final control signal expression
body += f" assign o_{sig} = {s};\n"
if sig in merged_signals:
for alias in merged_signals[sig]:
ports.append(f"output wire o_{alias}")
body += f" assign o_{alias} = o_{sig};"
#Some extra signals
body += "\n"
body += " //MDU/CSR/Ext\n"
body += "always @(posedge i_clk)\n"
body += " if (i_en) begin\n"
body += " imm25 <= i_imm25;\n"
body += " funct3 <= i_funct3;\n"
body += " opcode <= i_opcode;\n"
body += " op20 <= i_op20;\n"
body += " op21 <= i_op21;\n"
body += " op22 <= i_op22;\n"
body += " op26 <= i_op26;\n"
body += " end\n"
body += " assign o_mdu_op = MDU & (opcode == 5'b01100) & imm25;\n"
body += " assign o_ext_funct3 = funct3;\n"
body += " assign o_ebreak = op20;\n"
body += " assign o_rd_csr_en = opcode[4] & opcode[2] & (|funct3);\n"
body += " assign o_ctrl_mret = opcode[4] & opcode[2] & !(|funct3) & op21;\n"
body += " assign o_e_op = opcode[4] & opcode[2] & !(|funct3) & !op21;\n"
body += " assign o_csr_en = op20 | (op26 & !op21);\n"
body += " assign o_csr_mstatus_en = !op26 & !op22;\n"
body += " assign o_csr_mie_en = !op26 & op22 & !op20;\n"
body += " assign o_csr_mcause_en = op21 & !op20;\n"
body += " assign o_csr_source1 = funct3[1];\n"
body += " assign o_csr_source0 = funct3[0];\n"
body += " assign o_csr_d_sel = funct3[2];\n"
body += " assign o_csr_imm_en = opcode[4] & opcode[2] & funct3[2];\n"
body += " assign o_csr_addr1 = op26 & op20;\n"
body += " assign o_csr_addr0 = !op26 | op21;\n"
with open('serv_pre_reg_decode.v', 'w') as f:
f.write(HEADER.format(ports=',\n '.join(ports), body=body))
def write_mem_decoder(ctrlmap, merged_signals):
ports = []
mem = [0]*512
width = len(ctrlmap)
body = """ (* ram_style = "block" *) reg [{msb}:0] mem [0:511];
reg [{msb}:0] d;
initial begin
{mem} end
always @(posedge i_clk)
if (i_en)
d <= mem[{{i_imm30,i_funct3,i_opcode}}];
"""
s = ""
for i, (sig, bitmap) in enumerate(ctrlmap.items()):
#Find all conditions signals must be true
#Rest can be zero
(t, _) = map2minterms(bitmap)
for x in t:
mem[x] += 2**i
body += f" assign o_{sig} = d[{i}];\n"
ports.append(f"output wire o_{sig}")
if sig in merged_signals:
for alias in merged_signals[sig]:
ports.append(f"output wire o_{alias}")
body += f" assign o_{alias} = o_{sig};\n"
for i, m in enumerate(mem):
s += f" mem[{i}] = {width}'h{m:0{(width+3)//4}x};\n"
body += "\nalways @(posedge i_clk) begin\n"
body += "if (i_en) begin\n"
body += " //MDU/CSR/Ext\n"
body += " o_mdu_op <= MDU & (i_opcode == 5'b01100) & i_imm25;\n"
body += " o_ext_funct3 <= MDU ? i_funct3 : 3'b000;\n"
body += " o_ebreak <= CSR & (i_op20);\n"
body += " o_rd_csr_en <= CSR & (i_opcode[4] & i_opcode[2] & (|i_funct3));\n"
body += " o_ctrl_mret <= CSR & (i_opcode[4] & i_opcode[2] & !(|i_funct3) & i_op21);\n"
body += " o_e_op <= CSR & (i_opcode[4] & i_opcode[2] & !(|i_funct3) & !i_op21);\n"
body += " o_csr_en <= CSR & (i_op20 | (i_op26 & !i_op21));\n"
body += " o_csr_mstatus_en <= CSR & (!i_op26 & !i_op22);\n"
body += " o_csr_mie_en <= CSR & (!i_op26 & i_op22 & !i_op20);\n"
body += " o_csr_mcause_en <= CSR & ( i_op21 & !i_op20);\n"
body += " o_csr_source1 <= CSR & (i_funct3[1]);\n"
body += " o_csr_source0 <= CSR & (i_funct3[0]);\n"
body += " o_csr_d_sel <= CSR & (i_funct3[2]);\n"
body += " o_csr_imm_en <= CSR & (i_opcode[4] & i_opcode[2] & i_funct3[2]);\n"
body += " o_csr_addr1 <= CSR & (i_op26 & i_op20);\n"
body += " o_csr_addr0 <= CSR & (!i_op26 | i_op21);\n"
body += "end\n"
body += "end\n"
with open('serv_mem_decode.v', 'w') as f:
f.write(HEADER.format(ports=',\n '.join(ports), body=body.format(msb=width-1, mem=s)))
#imm30, funct3, opcode
ops = {
'lui' : 'x' + 'xxx' + '01101',
'auipc' : 'x' + 'xxx' + '00101',
'jal' : 'x' + 'xxx' + '11011',
'jalr' : 'x' + 'xxx' + '11001',#funct3 = 000?
'beq' : 'x' + '000' + '11000',
'bne' : 'x' + '001' + '11000',
'blt' : 'x' + '100' + '11000',
'bge' : 'x' + '101' + '11000',
'bltu' : 'x' + '110' + '11000',
'bgeu' : 'x' + '111' + '11000',
'lb' : 'x' + '000' + '00000',
'lh' : 'x' + '001' + '00000',
'lw' : 'x' + '010' + '00000',
'lbu' : 'x' + '100' + '00000',
'lhu' : 'x' + '101' + '00000',
'sb' : 'x' + '000' + '01000',
'sh' : 'x' + '001' + '01000',
'sw' : 'x' + '010' + '01000',
'addi' : 'x' + '000' + '00100',
'slti' : 'x' + '010' + '00100',
'sltiu' : 'x' + '011' + '00100',
'xori' : 'x' + '100' + '00100',
'ori' : 'x' + '110' + '00100',
'andi' : 'x' + '111' + '00100',
'slli' : '0' + '001' + '00100',
'srli' : '0' + '101' + '00100',
'srai' : '1' + '101' + '00100',
'add' : '0' + '000' + '01100',
'sub' : '1' + '000' + '01100',
'sll' : '0' + '001' + '01100',
'slt' : '0' + '010' + '01100',
'sltu' : '0' + '011' + '01100',
'xor' : '0' + '100' + '01100',
'srl' : '0' + '101' + '01100',
'sra' : '1' + '101' + '01100',
'or' : '0' + '110' + '01100',
'and' : '0' + '111' + '01100',
'fence' : 'x' + 'xxx' + '00011',#funct3=000?
'ecall' : 'x' + '000' + '11100',#ebreak same but op20=1
'csrrw' : 'x' + '001' + '11100',
'csrrs' : 'x' + '010' + '11100',
'csrrc' : 'x' + '011' + '11100',
'csrrwi': 'x' + '101' + '11100',
'csrrsi': 'x' + '110' + '11100',
'csrrci': 'x' + '111' + '11100',
}
###################################
###################################
###################################
#Map of all required true/false conditions for each op.
#This should ideally be created automatically from riscv-formal runs
#TODO: Extend with optional ISA extensions (M, Zicsr, Zifencei..)
#ebreak = ecall with op20=1
ctrlmap = \
{
#UUJRBBBBBBIIIIISSSIIIIIIIIIRRRRRRRRRR
#lajjbbbbbblllllsssassxoasssassssxssoa
#uuaaenlglgbhwbhbhwdllornlrrdulllorrrn
#iillqetete uu dttridlladblttrla d
# p r uu iiii iiii u
# c u
'branch_op' : ' 1111111100000000 00 000 000 00 ',
'slt_or_branch' : ' 1111111100000000 11 000 011 00 ',
'op_b_source' : ' 11111111000001110000000001111111111',
'immdec_ctrl0' : ' 0 11111100000111000000000 ',
'immdec_ctrl1' : '000 11111111111111111 ',
'immdec_ctrl2' : '000 11111100000000000000000 ',
'immdec_ctrl3' : '001 ',
'immdec_en0' : '0000111111000001110000000000000000000',
'immdec_en1' : '1110000000000000000000000000000000000',
'immdec_en2' : '1111000000111110001111111110000000000',
'immdec_en3' : '1110111111111111111111111110000000000',
'bne_or_bge' : ' 010101 ',
'sh_right' : ' 011 0 11 ',
'cond_branch' : ' 00111111 ',
'shift_op' : ' 0000000000000000 00 111 100 11 ',
'two_stage_op' : '0011111111111111110110001110011101100',
'rd_alu_en' : '0000 00000 1111111111111111111',
'rd_mem_en' : '0000 11111 0000000000000000000',
'dbus_en' : ' 0000000011111111 00 000 000 00 ',
'bufreg_rs1_en' : ' 0100000011111111 111 1 11 ',
'bufreg_imm_en' : ' 1111111111111111 000 0 00 ',
'bufreg_clr_lsb' : ' 1011111100000000 000 0 00 ',
'bufreg_sh_signed': ' 01 01 ',
'ctrl_jal_or_jalr': '0011 00000 0000000000000000000',
'ctrl_utype' : '110000000000000 0000000000000000000',
'ctrl_pc_rel' : '0110111111 ',
'rd_op' : '1111000000111110001111111111111111111',
'alu_sub' : ' 111111 011 01 11 ',
'alu_bool_op1' : ' 011000 0 00011',
'alu_bool_op0' : ' 001111 1 01101',
'alu_cmp_eq' : ' 110000 00 00 ',
'alu_cmp_sig' : ' 1100 10 10 ',
'alu_rd_sel0' : ' 1000000001100000000',
'alu_rd_sel1' : ' 0110000000001100000',
'alu_rd_sel2' : ' 0001110000000010011',
'mem_signed' : ' 11 00 ',
'mem_word' : ' 00100001 ',
'mem_half' : ' 01001010 ',
'mem_cmd' : ' 00000111 ',
# 'mtval_pc' : ' 1111111100000000 ',
}
print(printmap(ctrlmap))
print("\nMerging control signals")
(ctrlmap, merged_signals) = merge_signals(ctrlmap)
print(printmap(ctrlmap))
#Create the various decoders
print("Creating mem decoder")
write_mem_decoder(ctrlmap, merged_signals)
#print("Writing post-registered logic decoder")
#write_post_reg_logic_decoder(ctrlmap, merged_signals)
#
#print("Writing pre-registered logic decoder")
#write_pre_reg_logic_decoder(ctrlmap, merged_signals)