/* ** HDL4SE: 软件Verilog综合仿真平台 ** Copyright (C) 2021-2021, raoxianhong ** LCOM: 轻量级组件对象模型 ** Copyright (C) 2021-2021, raoxianhong ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are met: ** ** * Redistributions of source code must retain the above copyright notice, ** this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright notice, ** this list of conditions and the following disclaimer in the documentation ** and/or other materials provided with the distribution. ** * The name of the author may be used to endorse or promote products ** derived from this software without specific prior written permission. ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE ** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF ** THE POSSIBILITY OF SUCH DAMAGE. */ /* riscv_core_v5.v */ `define RISCVSTATE_READ_INST 1 `define RISCVSTATE_READ_REGS 2 `define RISCVSTATE_EXEC_INST 3 `define RISCVSTATE_WAIT_LD 4 `define RISCVSTATE_WAIT_LD2 5 `define RISCVSTATE_WAIT_ST 6 `define RISCVSTATE_WAIT_ST2 7 `define RISCVSTATE_WAIT_DIV 8 `define RISCVSTATE_WAIT_MUL 9 `define RAMSIZE 1024 `define CSROPCOUNTER_ `define CSRBASECOUNTER_ `define USE3MUL_ `define USEMUL32 `define USE1DIV `define USEDIV32 (* HDL4SE="LCOM", CLSID="638E8BC3-B0E0-41DC-9EDD-D35A39FD8051", softmodule="hdl4se" *) module riscv_core_v5( input wClk, input nwReset, output wWrite, output [31:0] bWriteAddr, output [31:0] bWriteData, output [3:0] bWriteMask, input wWriteReady, output reg wRead, output reg [31:0] bReadAddr, input [31:0] bReadData, input wReadReady, output reg [4:0] regno, output reg [3:0] regena, output reg [31:0] regwrdata, output reg regwren, input [31:0] regrddata, output reg [4:0] regno2, output reg [3:0] regena2, output reg [31:0] regwrdata2, output reg regwren2, input [31:0] regrddata2 ); reg [31:0] pc; //GREG(pc, 32, riscv_core_reg_gen_pc; reg [31:0] instr; //GREG(instr, 32, riscv_core_reg_gen_instr; reg write; //GREG(write, 1, riscv_core_gen_write; reg [31:0] writeaddr; //GREG(writeaddr, 32, riscv_core_gen_write; reg [31:0] writedata; //GREG(writedata, 32, riscv_core_gen_write; reg [3:0] writemask; //GREG(writemask, 4, riscv_core_gen_write; reg [4:0] readreg; //GREG(readreg, 5, riscv_core_reg_gen_readreg; reg [3:0] state; //GREG(state, 4, riscv_core_gen_state; reg [31:0] imm; //GREG(imm, 32, riscv_core_gen_imm; reg [4:0] dstreg; //GREG(dstreg, 5, riscv_core_gen_dstreg; reg [31:0] dstvalue; //GREG(dstvalue, 32, riscv_core_gen_dstreg; reg [31:0] ldaddr; //GREG(ldaddr, 2, riscv_core_gen_ldaddr; reg [4:0] divclk; reg [31:0] lastv; reg [31:0] lastaddr; /* CSR register */ reg [31:0] misa; /*0301*/ `ifdef CSRBASECOUNTER reg [63:0] ucycle64; /*0c00/0c80*/ reg [63:0] utime64; /*0c01/0c81*/ reg [63:0] uinstret64; /*0c02/0c82*/ reg [63:0] mcycle64; /*0b00/0b80*/ reg [63:0] minstret64; /*0b02/0b82*/ `endif `ifdef CSROPCOUNTER reg [63:0] opcounter_addsub64; /*0c20/0ca0*/ reg [63:0] opcounter_mul64; /*0c21/0ca0*/ reg [63:0] opcounter_div64; /*0c22/0ca0*/ reg [63:0] opcounter_ld64; /*0c23/0ca0*/ reg [63:0] opcounter_st64; /*0c24/0ca0*/ reg [63:0] opcounter_jmp64; /*0c25/0ca0*/ reg [63:0] opcounter_j64; /*0c26/0ca0*/ reg [63:0] opcounter_alui64; /* 0c27/0ca7*/ reg [63:0] opcounter_alu64; /* 0c28/0ca8*/ `endif reg [31:0] csr_r; always @(posedge wClk) if (state == `RISCVSTATE_READ_REGS) case (bReadData[31:20]) 12'h301: csr_r <= misa; `ifdef CSRBASECOUNTER 12'hc00: csr_r <= ucycle64[31:0]; 12'hc80: csr_r <= ucycle64[63:32]; 12'hc01: csr_r <= utime64[31:0]; 12'hc81: csr_r <= utime64[63:32]; 12'hc02: csr_r <= uinstret64[31:0]; 12'hc82: csr_r <= uinstret64[63:32]; 12'hb00: csr_r <= mcycle64[31:0]; 12'hb80: csr_r <= mcycle64[63:32]; 12'hb02: csr_r <= minstret64[31:0]; 12'hb82: csr_r <= minstret64[63:32]; `endif `ifdef CSROPCOUNTER 12'hc20: csr_r <= opcounter_addsub64[31:0]; 12'hca0: csr_r <= opcounter_addsub64[63:32]; 12'hc21: csr_r <= opcounter_mul64[31:0]; 12'hca1: csr_r <= opcounter_mul64[63:32]; 12'hc22: csr_r <= opcounter_div64[31:0]; 12'hca2: csr_r <= opcounter_div64[63:32]; 12'hc23: csr_r <= opcounter_ld64[31:0]; 12'hca3: csr_r <= opcounter_ld64[63:32]; 12'hc24: csr_r <= opcounter_st64[31:0]; 12'hca4: csr_r <= opcounter_st64[63:32]; 12'hc25: csr_r <= opcounter_jmp64[31:0]; 12'hca5: csr_r <= opcounter_jmp64[63:32]; 12'hc26: csr_r <= opcounter_j64[31:0]; 12'hca6: csr_r <= opcounter_j64[63:32]; 12'hc27: csr_r <= opcounter_alui64[31:0]; 12'hca7: csr_r <= opcounter_alui64[63:32]; 12'hc28: csr_r <= opcounter_alu64[31:0]; 12'hca8: csr_r <= opcounter_alu64[63:32]; `endif default: csr_r <= 0; endcase assign wWrite = write; assign bWriteAddr = writeaddr; assign bWriteData = writedata; assign bWriteMask = writemask; wire [4:0] opcode = instr[6:2]; wire [4:0] rd = instr[11:7]; wire [2:0] func3 = instr[14:12]; reg cond; wire [31:0] rs1 = regrddata; wire [31:0] rs2 = regrddata2; wire signed [31:0] rs1_s = rs1; wire signed [31:0] rs2_s = rs2; wire [31:0] rs1_abs = rs1[31] ? (-rs1_s) : rs1_s; wire [31:0] rs2_abs = rs2[31] ? (-rs2_s) : rs2_s; wire signed [31:0] imm_s = imm; wire [63:0] mul_result; wire [63:0] muls_result; wire [71:0] mulsu_result; wire [31:0] div_result_r, mod_result_r, divs_result_r, mods_result_r; wire [31:0] div_result, mod_result, divs_result, mods_result; `ifdef USE3MUL mult mul(wClk, rs1, rs2, mul_result); mult_s mul_s(wClk, rs1, rs2, muls_result); mulsu mul_su(wClk, rs1, {8'b0, rs2}, mulsu_result); `else wire signed [63:0] mul_result_sign = mul_result; reg [31:0] mul_rs1, mul_rs2; `ifdef USEMUL32 wire muldone; mul32 mul(wClk, (state == `RISCVSTATE_EXEC_INST)?1:0, mul_rs1, mul_rs2, mul_result, muldone); `else mult mul(wClk, mul_rs1, mul_rs2, mul_result); `endif wire [1:0] mul_unsign_op = func3[1:0]; reg [1:0] mul_unsign; reg mul_s; assign muls_result = mul_s?(-mul_result_sign):mul_result_sign; assign mulsu_result = mul_s?(-mul_result_sign):mul_result_sign; always @(mul_unsign_op or rs1 or rs2 or rs1_abs or rs2_abs) case (mul_unsign_op) 0: begin /* mul */ mul_rs1 = rs1_abs; mul_rs2 = rs2_abs; end 1: begin /* mulh */ mul_rs1 = rs1_abs; mul_rs2 = rs2_abs; end 2: begin /* mulhsu */ mul_rs1 = rs1_abs; mul_rs2 = rs2; end 3: begin /* mul */ mul_rs1 = rs1; mul_rs2 = rs2; end endcase always @(posedge wClk) if (state == `RISCVSTATE_EXEC_INST) begin mul_unsign <= mul_unsign_op; case (mul_unsign_op) 0: /* mul */ mul_s <= rs1[31] ^ rs2[31]; 1: /* mulh */ mul_s <= rs1[31] ^ rs2[31]; 2: /* mulhsu */ mul_s <= rs1[31]; 3: /* mulhu */ mul_s <= 1'b0; endcase end `endif /* 两个除法器: Total logic elements 8,079 / 114,480 ( 7 % ) Total combinational functions 7,107 / 114,480 ( 6 % ) Dedicated logic registers 4,309 / 114,480 ( 4 % ) Total registers 4309 Total memory bits 151,274 / 3,981,312 ( 4 % ) Embedded Multiplier 9-bit elements 0 / 532 ( 0 % ) 一个除法器: Total logic elements 6,319 / 114,480 ( 6 % ) Total combinational functions 5,601 / 114,480 ( 5 % ) Dedicated logic registers 2,916 / 114,480 ( 3 % ) Total registers 2916 Total memory bits 150,192 / 3,981,312 ( 4 % ) Embedded Multiplier 9-bit elements 0 / 532 ( 0 % ) */ `ifdef USE1DIV wire div_unsign_op = func3[0]; reg div_unsign; reg div_s; reg mod_s; always @(posedge wClk) if (state == `RISCVSTATE_EXEC_INST) begin div_unsign <= div_unsign_op; div_s <= rs1[31] ^ rs2[31]; mod_s <= rs1[31]; end `ifdef USEDIV32 wire divdone; div32 div(wClk, (state == `RISCVSTATE_EXEC_INST)?1:0, div_unsign_op?rs1:rs1_abs, div_unsign_op?rs2:rs2_abs, div_result_r, mod_result_r, divdone); `else div div(wClk, div_unsign_op?rs2:rs2_abs, div_unsign_op?rs1:rs1_abs, div_result_r, mod_result_r); `endif assign div_result = div_result_r; assign mod_result = mod_result_r; wire signed [31:0] div_result_r_sign = div_result_r; wire signed [31:0] mod_result_r_sign = mod_result_r; assign divs_result = div_s ? (-div_result_r_sign) : div_result_r; assign mods_result = mod_s ? (-mod_result_r_sign) : mod_result_r; `else div div(wClk, rs2, rs1, div_result_r, mod_result_r); div_s divs(wClk, rs2, rs1, divs_result_r, mods_result_r); assign div_result = div_result_r; assign divs_result = divs_result_r; assign mod_result = mod_result_r; assign mods_result = mods_result_r; `endif /* cond */ always @(rs1 or rs2 or rs1_s or rs2_s or func3) case(func3) 0:/*beq*/ cond = rs1 == rs2; 1:/*bne*/ cond = rs1 != rs2; 4:/*blt*/ cond = rs1_s < rs2_s; 5:/*bge*/ cond = rs1_s >= rs2_s; 6:/*bltu*/cond = rs1 < rs2; 7:/*bgeu*/cond = rs1 >= rs2; default: cond = 1'b0; endcase //DEFINE_FUNC(riscv_core_reg_gen_lastv, "state, instr, ldaddr") { always @(posedge wClk) if (state == `RISCVSTATE_WAIT_LD) begin //if (wReadReady) begin lastaddr <= ldaddr; if (func3 == 1 && ldaddr[1:0] == 3) begin /* lh */ lastv <= {24'b0, bReadData[31:24]}; end else if (func3 == 2 && ldaddr[1:0] != 0) begin /* lw */ if (ldaddr[1:0] == 1) lastv <= {8'b0, bReadData[31:8]}; else if (ldaddr[1:0] == 2) lastv <= {16'b0, bReadData[31:16]}; else lastv <= {24'b0, bReadData[31:24]}; end else if (func3 == 5 && ldaddr[1:0] == 3) begin /* lhu */ lastv <= {24'b0, bReadData[31:24]}; end end end else if (state == `RISCVSTATE_EXEC_INST) begin lastaddr <= rs1 + imm; lastv <= rs2; end reg [31:0] newpc; always @(opcode or pc or imm or cond or rs1) case (opcode) 5'h1b: newpc = pc + imm; 5'h19: newpc = rs1 + imm; 5'h18: newpc = cond ? pc + imm : pc + 4; default: newpc = pc + 4; endcase //DEFINE_FUNC(riscv_core_reg_gen_pc, "nwReset, state, instr, pc, rs1, imm, regrddata") { always @(posedge wClk) if (!nwReset) begin pc <= 0;//32'h00000074; end else begin if (state == `RISCVSTATE_EXEC_INST) begin pc <= newpc; end end //DEFINE_FUNC(riscv_core_reg_gen_instr, "state, bReadData") { always @(posedge wClk) if (state == `RISCVSTATE_READ_REGS) instr <= bReadData; //DEFINE_FUNC(riscv_core_reg_gen_readreg, "state, instr") { always @(posedge wClk) if (state == `RISCVSTATE_EXEC_INST) if (opcode == 5'h00) readreg <= rd; wire [31:0] newwriteaddr = rs1 + imm; //DEFINE_FUNC(riscv_core_gen_write, "nwReset, state, pc, instr, rs1, regrddata, imm") { always @(nwReset or state or opcode or newwriteaddr or rs2 or func3 or lastaddr or lastv) begin write = 0; writeaddr = 0; writemask = 0; writedata = 0; if (!nwReset) begin write = 0; end else if (state == `RISCVSTATE_EXEC_INST) begin write = 0; if (opcode == 5'h08) begin writeaddr = {newwriteaddr[31:2], 2'b00}; writemask = 4'h0; writedata = rs2; write = 1'b1; case (func3) 0:/*sb*/ begin case (newwriteaddr[1:0]) 0: begin writemask = 4'he; writedata = rs2; end 1: begin writemask = 4'hd; writedata = {rs2[23:0], 8'h0}; end 2: begin writemask = 4'hb; writedata = {rs2[15:0], 16'h0}; end 3: begin writemask = 4'h7; writedata = {rs2[7:0], 24'h0}; end endcase end 1:/*sh*/ begin case (newwriteaddr[1:0]) 0: begin writemask = 4'hc; writedata = rs2; end 1: begin writemask = 4'h9; writedata = {rs2[23:0], 8'h0}; end 2: begin writemask = 4'h3; writedata = {rs2[15:0], 16'h0}; end 3: begin writemask = 4'h7; writedata = {rs2[7:0], 24'h0}; end endcase end 2:/*sw*/ begin case (newwriteaddr[1:0]) 0: begin writemask = 4'h0; writedata = rs2; end 1: begin writemask = 4'h1; writedata = {rs2[23:0], 8'h0}; end 2: begin writemask = 4'h3; writedata = {rs2[15:0], 16'h0}; end 3: begin writemask = 4'h7; writedata = {rs2[7:0], 24'h0}; end endcase end endcase end end else if (state == `RISCVSTATE_WAIT_ST) begin write = 0; writeaddr = {lastaddr[31:2], 2'b0} + 4; if (opcode == 5'h08) begin case (func3) 1:/*sh*/ begin case (lastaddr[1:0]) 3: begin writemask = 4'he; writedata = {24'b0, lastv[31:24]}; write = 1; end endcase end 2:/*sw*/ begin case (lastaddr[1:0]) 1: begin writemask = 4'he; writedata = {24'b0, lastv[31:24]}; write = 1; end 2: begin writemask = 4'hc; writedata = {16'b0, lastv[31:16]}; write = 1; end 3: begin writemask = 4'h8; writedata = {8'b0, lastv[31:8]}; write = 1; end endcase end endcase end end else begin write = 0; end end //DEFINE_FUNC(riscv_core_gen_state, "state, instr, nwReset") { always @(posedge wClk) if (!nwReset) begin state <= `RISCVSTATE_READ_INST; end else begin case (state) `RISCVSTATE_READ_INST: state <= `RISCVSTATE_READ_REGS; `RISCVSTATE_READ_REGS: state <= `RISCVSTATE_EXEC_INST; `RISCVSTATE_EXEC_INST: begin if (opcode == 5'h00) begin state <= `RISCVSTATE_WAIT_LD; end else if (opcode == 5'h08) begin state <= `RISCVSTATE_WAIT_ST; end else if (opcode == 5'h0c && instr[25] && func3[2] && (rs2 != 0)) begin state <= `RISCVSTATE_WAIT_DIV; divclk <= 31; end else if (opcode == 5'h0c && instr[25] && (func3[2]==0) ) begin state <= `RISCVSTATE_WAIT_MUL; divclk <= 3; end else state <= `RISCVSTATE_READ_REGS; end `RISCVSTATE_WAIT_LD: begin if (wReadReady) begin if (func3 == 1 && ldaddr[1:0] == 3) begin /* lh */ state <= `RISCVSTATE_WAIT_LD2; end else if (func3 == 2 && ldaddr[1:0] != 0) begin /* lw */ state <= `RISCVSTATE_WAIT_LD2; end else if (func3 == 5 && ldaddr[1:0] == 3) begin /* lhu */ state <= `RISCVSTATE_WAIT_LD2; end else begin state <= `RISCVSTATE_READ_REGS; end end end `RISCVSTATE_WAIT_LD2: if (wReadReady) begin state <= `RISCVSTATE_READ_REGS; end `RISCVSTATE_WAIT_ST: begin state <= `RISCVSTATE_READ_REGS; if (opcode == 5'h08) begin if (func3 == 1 && (lastaddr & 3) == 3) begin /* sh */ state <= `RISCVSTATE_WAIT_ST2; end else if (func3 == 2 && (lastaddr & 3) != 0) begin state <= `RISCVSTATE_WAIT_ST2; end end end `RISCVSTATE_WAIT_ST2: state <= `RISCVSTATE_READ_REGS; `RISCVSTATE_WAIT_MUL: begin `ifdef USEMUL32 if (muldone) state <= `RISCVSTATE_READ_REGS; `else if (divclk == 0) state <= `RISCVSTATE_READ_REGS; else divclk <= divclk - 1; `endif end `RISCVSTATE_WAIT_DIV: begin `ifdef USEDIV32 if (divdone) state <= `RISCVSTATE_READ_REGS; `else if (divclk == 0) state <= `RISCVSTATE_READ_REGS; else divclk <= divclk - 1; `endif end endcase end //DEFINE_FUNC(riscv_core_gen_imm, "bReadData, state") { /* 在RISCVSTATE_READ_REGS周期生成imm */ always @(posedge wClk) if (state == `RISCVSTATE_READ_REGS) begin case (bReadData[6:2]) 5'h0d: imm <= {bReadData[31:12], 12'b0}; 5'h05: imm <= {bReadData[31:12], 12'b0}; 5'h1b: imm <= {{12{bReadData[31]}}, bReadData[19:12], bReadData[20], bReadData[30:21], 1'b0}; 5'h19: imm <= {{20{bReadData[31]}}, bReadData[31:20]}; 5'h18: imm <= {{20{bReadData[31]}}, bReadData[7], bReadData[30:25], bReadData[11:8], 1'b0}; 5'h00: imm <= {{20{bReadData[31]}}, bReadData[31:20]}; 5'h08: imm <= {{20{bReadData[31]}}, bReadData[31:25], bReadData[11:7]}; 5'h04: imm <= {{20{bReadData[31]}}, bReadData[31:20]}; 5'h1c: imm <= {27'b0, bReadData[19:15]}; endcase end reg[31:0] csr_v; reg csr_op; always @(func3 or rs1 or csr_r or imm) case (func3) 1: /* CSRRW */ begin csr_v = rs1; csr_op = 1; end 2: /* CSRRS */ begin csr_v = csr_r | rs1; csr_op = 1; end 3: /* CSRRC */ begin csr_v = csr_r & (~rs1); csr_op = 1; end 5: /* CSRRWI */ begin csr_v = imm; csr_op = 1; end 6: /* CSRRSI */ begin csr_v = csr_r | imm; csr_op = 1; end 7: /* CSRRCI */ begin csr_v = csr_r & (~imm); csr_op = 1; end default: begin csr_v = 0; csr_op = 0; end endcase reg opcounter_doit; //DEFINE_FUNC(riscv_core_gen_csr, "nwReset, ucycle64, misa, mcycle64, utime64, uinstret64, minstret64, instr, imm, regrddata") { always @(posedge wClk) if (nwReset == 0) begin misa <= 32'b0100_0000_0001_0000_0001_0001_0000_0000;// RV32IM `ifdef CSRBASECOUNTER ucycle64 <= 0; mcycle64 <= 0; utime64 <= 0; uinstret64 <= 0; minstret64 <= 0; `endif `ifdef CSROPCOUNTER opcounter_doit <= 1; opcounter_addsub64 <= 0; opcounter_alui64 <= 0; opcounter_alu64 <= 0; opcounter_mul64 <= 0; opcounter_div64 <= 0; opcounter_ld64 <= 0; opcounter_st64 <= 0; opcounter_jmp64 <= 0; opcounter_j64 <= 0; `endif end else begin `ifdef CSROPCOUNTER if (opcounter_doit) `endif `ifdef CSRBASECOUNTER ucycle64 <= ucycle64 + 1; utime64 <= utime64 + 1; mcycle64 <= mcycle64 + 1; `endif if (state == `RISCVSTATE_EXEC_INST) begin `ifdef CSROPCOUNTER if (opcounter_doit) `endif `ifdef CSRBASECOUNTER uinstret64 <= uinstret64 + 1; minstret64 <= minstret64 + 1; `endif `ifdef CSROPCOUNTER if (opcounter_doit) case (opcode) 5'h1b: opcounter_jmp64 <= opcounter_jmp64 + 1; 5'h19: opcounter_jmp64 <= opcounter_jmp64 + 1; 5'h18: opcounter_j64 <= opcounter_j64 + 1; 5'h00: opcounter_ld64 <= opcounter_ld64 + 1; 5'h08: opcounter_st64 <= opcounter_st64 + 1; 5'h04: opcounter_alui64 <= opcounter_alui64 + 1; 5'h0c: begin opcounter_alu64 <= opcounter_alu64 + 1; if (instr[25]) begin/* MUL/DIV */ if (func3[2]) begin opcounter_div64 <= opcounter_div64 + 1; end else begin opcounter_mul64 <= opcounter_mul64 + 1; end end else begin if (func3 == 0) opcounter_addsub64 <= opcounter_addsub64 + 1; end end endcase `endif if (opcode == 5'h1c) begin /* CSR */ if (csr_op) begin case (instr[31:20]) 12'h301: misa <= csr_v; `ifdef CSRBASECOUNTER 12'hc00: ucycle64[31:0] <= csr_v; 12'hc80: ucycle64[63:32] <= csr_v; 12'hc01: utime64[31:0] <= csr_v; 12'hc81: utime64[63:32] <= csr_v; 12'hc02: uinstret64[31:0] <= csr_v; 12'hc82: uinstret64[63:32] <= csr_v; 12'hb00: mcycle64[31:0] <= csr_v; 12'hb80: mcycle64[63:32] <= csr_v; 12'hb02: minstret64[31:0] <= csr_v; 12'hb82: minstret64[63:32] <= csr_v; `endif `ifdef CSROPCOUNTER 12'hc20: opcounter_addsub64[31:0] <= csr_v; 12'hca0: opcounter_addsub64[63:32] <= csr_v; 12'hc21: opcounter_mul64[31:0] <= csr_v; 12'hca1: opcounter_mul64[63:32] <= csr_v; 12'hc22: opcounter_div64[31:0] <= csr_v; 12'hca2: opcounter_div64[63:32] <= csr_v; 12'hc23: opcounter_ld64[31:0] <= csr_v; 12'hca3: opcounter_ld64[63:32] <= csr_v; 12'hc24: opcounter_st64[31:0] <= csr_v; 12'hca4: opcounter_st64[63:32] <= csr_v; 12'hc25: opcounter_jmp64[31:0] <= csr_v; 12'hca5: opcounter_jmp64[63:32] <= csr_v; 12'hc26: opcounter_j64[31:0] <= csr_v; 12'hca6: opcounter_j64[63:32] <= csr_v; 12'hc27: opcounter_alui64[31:0] <= csr_v; 12'hca7: opcounter_alui64[63:32] <= csr_v; 12'hc28: opcounter_alu64[31:0] <= csr_v; 12'hca8: opcounter_alu64[63:32] <= csr_v; 12'hc40: begin uinstret64 <= 0; ucycle64 <= 0; opcounter_addsub64 <= 0; opcounter_mul64 <= 0; opcounter_div64 <= 0; opcounter_ld64 <= 0; opcounter_st64 <= 0; opcounter_jmp64 <= 0; opcounter_j64 <= 0; opcounter_alui64 <= 0; opcounter_alu64 <= 0; opcounter_doit <= 1; end 12'hc41: begin opcounter_doit <= 0; end `endif endcase end end end end //DEFINE_FUNC(riscv_core_reg_wr_sig, "state, dstreg, dstvalue, bReadData, instr, regrddata, pc") { always @(state or dstreg or dstvalue or bReadData or instr or regrddata or regrddata2 or pc) case (state) `RISCVSTATE_READ_REGS: begin regno = bReadData[19:15]; /* instr */ regwren = 0; regena = 0; regwrdata = 0; regno2 = bReadData[24:20]; /* instr */ regwren2 = 0; regena2 = 0; regwrdata2 = 0; end `RISCVSTATE_EXEC_INST, `RISCVSTATE_WAIT_LD, `RISCVSTATE_WAIT_LD2, `RISCVSTATE_WAIT_DIV, `RISCVSTATE_WAIT_MUL : begin regwren = (dstreg != 0) ? 1 : 0; regno = dstreg; regena = 4'hf; regwrdata = dstvalue; regwren2 = (dstreg != 0) ? 1 : 0; regno2 = dstreg; regena2 = 4'hf; regwrdata2 = dstvalue; end default: begin regwren = 0; regno = 0; regena = 0; regwrdata = 0; regwren2 = 0; regno2 = 0; regena2 = 0; regwrdata2 = 0; end endcase //DEFINE_FUNC(riscv_core_gen_ldaddr, "state, pc, instr, rs1") { always @(posedge wClk) if (state == `RISCVSTATE_EXEC_INST) begin if (opcode == 5'h00) begin /* ld inst */ ldaddr <= rs1 + imm; end end //DEFINE_FUNC(riscv_core_gen_dstreg, "state, instr, ldaddr, readreg, bReadData, pc, rs1, regrddata, imm") { always @(state or readreg or instr or func3 or ldaddr or bReadData or rd or rs1 or rs2 or rs1_s or rs2_s or lastv or divclk or csr_r `ifdef USEMUL32 or muldone `endif `ifdef USEDIV32 or divdone `endif or divs_result or div_result or mods_result or mod_result or muls_result or mulsu_result or mul_result or opcode or imm or imm_s or pc) begin dstreg = 0; dstvalue = 0; case (state) `RISCVSTATE_WAIT_LD: begin dstreg = wReadReady?readreg:0; case (func3) 0: begin case (ldaddr[1:0]) 0: dstvalue = {{24{bReadData[7]}}, bReadData[7:0]}; 1: dstvalue = {{24{bReadData[15]}}, bReadData[15:8]}; 2: dstvalue = {{24{bReadData[23]}}, bReadData[23:16]}; 3: dstvalue = {{24{bReadData[31]}}, bReadData[31:24]}; endcase end 1: begin case (ldaddr[1:0]) 0: dstvalue = {{16{bReadData[15]}}, bReadData[15:0]}; 1: dstvalue = {{16{bReadData[23]}}, bReadData[23:8]}; 2: dstvalue = {{16{bReadData[31]}}, bReadData[31:16]}; 3: dstvalue = 32'hdeadbeef; endcase end 2: dstvalue = bReadData; 4: begin case (ldaddr[1:0]) 0: dstvalue = {24'b0, bReadData[7:0]}; 1: dstvalue = {24'b0, bReadData[15:8]}; 2: dstvalue = {24'b0, bReadData[23:16]}; 3: dstvalue = {24'b0, bReadData[31:24]}; endcase end 5: begin case (ldaddr[1:0]) 0: dstvalue = {16'b0, bReadData[15:0]}; 1: dstvalue = {16'b0, bReadData[23:8]}; 2: dstvalue = {16'b0, bReadData[31:16]}; 3: dstvalue = 32'hdeadbeef; endcase end endcase end `RISCVSTATE_WAIT_LD2: begin dstreg = wReadReady?rd:0; if (func3 == 1 && ldaddr[1:0] == 3) begin dstvalue = {{16{bReadData[7]}}, bReadData[7:0], lastv[7:0]}; end else if (func3 == 2 && ldaddr[1:0] != 0) begin if (ldaddr[1:0] == 1) dstvalue = {bReadData[7:0], lastv[23:0]}; else if (ldaddr[1:0] == 2) dstvalue = {bReadData[15:0], lastv[15:0]}; else if (ldaddr[1:0] == 3) dstvalue = {bReadData[23:0], lastv[7:0]}; end else if (func3 == 5 && ldaddr[1:0] == 3) begin dstvalue = {16'b0, bReadData[7:0], lastv[7:0]}; end else begin dstreg = 0; dstvalue = 0; end end `RISCVSTATE_WAIT_DIV: `ifdef USEDIV32 if (divdone) `else if (divclk == 0) `endif begin dstreg = 0; case (func3[1:0]) 0: begin //div dstreg = rd; dstvalue = divs_result; end 1: begin //divu dstreg = rd; dstvalue = div_result; end 2: begin//rem dstreg = rd; dstvalue = mods_result; end 3: begin //remu dstreg = rd; dstvalue = mod_result; end endcase end `RISCVSTATE_WAIT_MUL: `ifdef USEMUL32 if (muldone) `else if (divclk == 0) `endif begin dstreg = 0; case (func3[1:0]) 0: begin //mul dstvalue = muls_result[31:0]; dstreg = rd; end 1: begin //mulh dstvalue = muls_result[63:32]; dstreg = rd; end 2: begin //mulhsu dstvalue = mulsu_result[63:32]; dstreg = rd; end 3: begin //mulhu dstvalue = mul_result[63:32]; dstreg = rd; end endcase end `RISCVSTATE_EXEC_INST: begin dstreg = rd; case (opcode) 5'h0d: begin dstvalue = imm; end 5'h05: begin dstvalue = imm + pc; end 5'h1c: begin if (func3[1:0] != 0) begin /* csr */ dstvalue = csr_r; end else begin dstreg = 0; dstvalue = 0; end end 5'h1b: begin dstvalue = pc + 4; end 5'h19: begin dstvalue = pc + 4; end 5'h04: begin /* alui */ case (func3) 0:/*addi*/ dstvalue = rs1 + imm; 1:/*slli*/ dstvalue = rs1 << imm[4:0]; 2:/*slti*/ dstvalue = (rs1_s < imm_s) ? 1 : 0; 3:/*sltiu*/dstvalue = (rs1 < imm) ? 1 : 0; 4:/*xori*/ dstvalue = rs1 ^ imm; 5:/*srli/srai*/ dstvalue = instr[30] ? (rs1_s >> imm[4:0]) : (rs1 >> imm[4:0]); 6:/*ori*/ dstvalue = rs1 | imm; 7:/*andi*/ dstvalue = rs1 & imm; default: begin dstreg = 0; dstvalue=0; end endcase end 5'h0c: begin /*alu*/ if (instr[25]) begin /* is MUL/DIV instr*/ case (func3) /* 0: begin //mul dstvalue = muls_result[31:0]; end 1: begin //mulh dstvalue = muls_result[63:32]; end 2: begin //mulhsu dstvalue = mulsu_result[63:32]; end 3: begin //mulhu dstvalue = mul_result[63:32]; end */ 0: begin //mul dstreg = 0; dstvalue = 0; end 1: begin //mulh dstreg = 0; dstvalue = 0; end 2: begin //mulhsu dstreg = 0; dstvalue = 0; end 3: begin //mulhu dstreg = 0; dstvalue = 0; end 4: begin //div if (rs2 == 0) begin dstvalue = 32'hffffffff; end else begin dstreg = 0; dstvalue = 0; end end 5: begin //divu if (rs2 == 0) begin dstvalue = 32'hffffffff; end else begin dstreg = 0; dstvalue = 0; end end 6: begin//rem if (rs2 == 0) begin dstvalue = rs1; end else begin dstreg = 0; dstvalue = 0; end end 7: begin //remu if (rs2 == 0) begin dstvalue = rs1; end else begin dstreg = 0; dstvalue = 0; end end endcase end else begin case (func3) 0: begin if (instr[30]) dstvalue = rs1 - rs2; else dstvalue = rs1 + rs2; end 1: begin //sll dstvalue = rs1 << rs2[4:0]; end 2: begin //slt dstvalue = (rs1_s < rs2_s) ? 1 : 0; end 3: begin //sltu dstvalue = (rs1 < rs2) ? 1 : 0; end 4: begin //xor dstvalue = rs1 ^ rs2; end 5: begin //srl/sra if (instr[30]) dstvalue = rs1 >> rs2[4:0]; else dstvalue = rs1_s >> rs2[4:0]; end 6: begin //or dstvalue = rs1 | rs2; end 7: begin //and dstvalue = rs1 & rs2; end endcase end end default: begin dstreg = 0; dstvalue = 0; end endcase end endcase end reg [31:0] lastReadAddr; reg lastRead; always @(posedge wClk) begin lastRead <= wRead; lastReadAddr <= bReadAddr; end //DEFINE_FUNC(riscv_core_read_sig, "state, pc, instr, bReadData, rs1") { always @(state or pc or opcode or imm or rs1 or newpc or func3 or ldaddr or lastaddr `ifdef USEMUL32 or muldone `else or divclk `endif `ifdef USEDIV32 or divdone `else or divclk `endif ) begin wRead = 0; bReadAddr = 0; case (state) `RISCVSTATE_WAIT_LD2: if (wReadReady) begin wRead = 1; bReadAddr = pc; end else begin wRead = lastRead; bReadAddr = lastReadAddr; end `RISCVSTATE_WAIT_ST2, `RISCVSTATE_READ_INST: begin wRead = 1; bReadAddr = pc; end `RISCVSTATE_EXEC_INST: begin if (opcode == 5'h00) begin /* ld inst */ bReadAddr = rs1 + imm; wRead = 1; end else if (opcode == 5'h08) begin wRead = 0; bReadAddr = 0; end else begin wRead = 1; bReadAddr = newpc; end end `RISCVSTATE_WAIT_LD: begin if (wReadReady) begin if (func3 == 1 && ldaddr[1:0] == 3) begin /* lh */ wRead = 1; bReadAddr = ldaddr + 4; end else if (func3 == 2 && ldaddr[1:0] != 0) begin /* lw */ wRead = 1; bReadAddr = ldaddr + 4; end else if (func3 == 5 && ldaddr[1:0] == 3) begin /* lhu */ wRead = 1; bReadAddr = ldaddr + 4; end else begin wRead = 1; bReadAddr = pc; end end else begin wRead = lastRead; bReadAddr = lastReadAddr; end end `RISCVSTATE_WAIT_ST: begin if (opcode == 5'h08) begin if (func3 == 1 && lastaddr[1:0] == 3) begin /* sh */ end else if (func3 == 2 && lastaddr[1:0] != 0) begin end else begin wRead = 1; bReadAddr = pc; end end end `RISCVSTATE_WAIT_MUL: `ifdef USEMUL32 if (muldone) begin `else if (divclk == 0) begin `endif wRead = 1; bReadAddr = pc; end `RISCVSTATE_WAIT_DIV: `ifdef USEDIV32 if (divdone) begin `else if (divclk == 0) begin `endif wRead = 1; bReadAddr = pc; end default: begin wRead = 0; bReadAddr = 0; end endcase end endmodule