/* ** 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_v2.v */ `define RISCVSTATE_INIT_REGX1 0 `define RISCVSTATE_INIT_REGX2 1 `define RISCVSTATE_READ_INST 2 `define RISCVSTATE_READ_REGS 3 `define RISCVSTATE_EXEC_INST 4 `define RISCVSTATE_WAIT_LD 5 `define RISCVSTATE_WAIT_LD2 6 `define RISCVSTATE_WAIT_ST 7 `define RISCVSTATE_WAIT_ST2 8 `define RISCVSTATE_WAIT_DIV 9 `define RAMSIZE 4096 (* HDL4SE="LCOM", CLSID="638E8BC3-B0E0-41DC-9EDD-D35A39FD8051", softmodule="hdl4se" *) module riscv_core( input wClk, nwReset, output wWrite, output [31:0] bWriteAddr, output [31:0] bWriteData, output [3:0] bWriteMask, output reg wRead, output reg [31:0] bReadAddr, input [31:0] bReadData, 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*/ reg [31:0] ucycle; /*0c00*/ reg [31:0] utime; /*0c01*/ reg [31:0] uinstret; /*0c02*/ reg [31:0] ucycleh; /*0c80*/ reg [31:0] utimeh; /*0c81*/ reg [31:0] uinstreth; /*0c82*/ reg [31:0] mcycle; /*0b00*/ reg [31:0] minstret; /*0b02*/ reg [31:0] mcycleh; /*0b80*/ reg [31:0] minstreth; /*0b82*/ reg [31:0] csr_r; always @(posedge wClk) if (state == `RISCVSTATE_READ_REGS) case (bReadData[31:20]) 12'h301: csr_r <= misa; 12'hc00: csr_r <= ucycle; 12'hc01: csr_r <= utime; 12'hc02: csr_r <= uinstret; 12'hc80: csr_r <= ucycleh; 12'hc81: csr_r <= utimeh; 12'hc82: csr_r <= uinstreth; 12'hb00: csr_r <= mcycle; 12'hb02: csr_r <= minstret; 12'hb80: csr_r <= mcycleh; 12'hb82: csr_r <= minstreth; 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 signed [31:0] imm_s = imm; wire [31:0] add_result; wire [31:0] sub_result; 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; adder add(rs1, rs2, add_result); suber sub(rs1, rs2, sub_result); mult mul(rs1, rs2, mul_result); mult_s mul_s(rs1, rs2, muls_result); mulsu mul_su(rs1, {8'b0, rs2}, mulsu_result); 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; /* 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 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 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 <= 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 @(posedge wClk) 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 //DEFINE_FUNC(riscv_core_gen_state, "state, instr, nwReset") { always @(posedge wClk) if (!nwReset) begin state <= `RISCVSTATE_INIT_REGX1; end else begin case (state) `RISCVSTATE_INIT_REGX1: state <= `RISCVSTATE_INIT_REGX2; `RISCVSTATE_INIT_REGX2: state <= `RISCVSTATE_READ_REGS; `RISCVSTATE_READ_INST: state <= `RISCVSTATE_READ_REGS; `RISCVSTATE_READ_REGS: state <= `RISCVSTATE_EXEC_INST; `RISCVSTATE_EXEC_INST: begin if (opcode == 5'h00) state <= `RISCVSTATE_WAIT_LD; else if (opcode == 5'h08) state <= `RISCVSTATE_WAIT_ST; else if (opcode == 5'h0c && instr[25] && func3[2] && (rs2 != 0)) begin state <= `RISCVSTATE_WAIT_DIV; divclk <= 11; end else state <= `RISCVSTATE_READ_REGS; end `RISCVSTATE_WAIT_LD: 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_INST; end end `RISCVSTATE_WAIT_LD2: state <= `RISCVSTATE_READ_INST; `RISCVSTATE_WAIT_ST: begin state <= `RISCVSTATE_READ_INST; 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_INST; `RISCVSTATE_WAIT_DIV: begin if (divclk == 0) state <= `RISCVSTATE_READ_INST; else divclk <= divclk - 1; 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 //DEFINE_FUNC(riscv_core_gen_csr, "nwReset, ucycle, ucycleh, misa, mcycle, mcycleh, utime,utimeh, uinstret, uinstreth, minstret, minstreth, instr, imm, regrddata") { always @(posedge wClk) if (nwReset == 0) begin misa <= 32'b0100_0000_0001_0000_0001_0001_0000_0000;// RV32IM ucycle <= 0; ucycleh <= 0; mcycle <= 0; mcycleh <= 0; utime <= 0; utimeh <= 0; uinstret <= 0; uinstreth <= 0; minstret <= 0; minstreth <= 0; end else begin if (ucycle == 32'hffffffff) begin ucycleh <= ucycleh + 1; ucycle <= 0; end else begin ucycle <= ucycle + 1; end if (utime == 32'hffffffff) begin utimeh <= utimeh + 1; utime <= 0; end else begin utime <= utime + 1; end if (mcycle == 32'hffffffff) begin mcycleh <= mcycleh + 1; mcycle <= 0; end else begin mcycle <= mcycle + 1; end if (state == `RISCVSTATE_EXEC_INST) begin if (uinstret == 32'hffffffff) begin uinstreth <= uinstreth + 1; uinstret <= 0; end else begin uinstret <= uinstret + 1; end if (minstret == 32'hffffffff) begin minstreth <= minstreth + 1; minstret <= 0; end else begin minstret <= minstret + 1; end if (opcode == 5'h1c) begin /* CSR */ if (csr_op) begin case (instr[31:20]) 12'h301: misa <= csr_v; 12'hc00: ucycle <= csr_v; 12'hc01: utime <= csr_v; 12'hc02: uinstret <= csr_v; 12'hc80: ucycleh <= csr_v; 12'hc81: utimeh <= csr_v; 12'hc82: uinstreth <= csr_v; 12'hb00: mcycle <= csr_v; 12'hb02: minstret <= csr_v; 12'hb80: mcycleh <= csr_v; 12'hb82: minstreth <= csr_v; 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 : 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 `RISCVSTATE_INIT_REGX1: begin regwren = 1; regno = 1; regena = 4'hf; regwrdata = 32'h8c; regwren2 = 1; regno2 = 1; regena2 = 4'hf; regwrdata2 = 32'h8c; end `RISCVSTATE_INIT_REGX2: begin regwren = 1; regno = 2; regena = 4'hf; regwrdata = `RAMSIZE * 4 - 16; regwren2 = 1; regno2 = 2; regena2 = 4'hf; regwrdata2 = `RAMSIZE * 4 - 16; 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 divs_result or div_result or mods_result or mod_result or muls_result or mulsu_result or mul_result or sub_result or add_result or opcode or imm or pc) begin dstreg = 0; dstvalue = 0; case (state) `RISCVSTATE_WAIT_LD: begin dstreg = readreg; 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 = rd; 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: if (divclk == 0) 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_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 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 = sub_result; else dstvalue = add_result; 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 //DEFINE_FUNC(riscv_core_read_sig, "state, pc, instr, bReadData, rs1") { always @(state or pc or opcode or imm or rs1 or func3 or ldaddr or newpc) begin wRead = 0; bReadAddr = 0; case (state) `RISCVSTATE_INIT_REGX2: begin wRead = 1; bReadAddr = pc; end `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 (func3 == 1 && (ldaddr & 3) == 3) begin /* lh */ wRead = 1; bReadAddr = ldaddr + 4; end else if (func3 == 2 && (ldaddr & 3) != 0) begin /* lw */ wRead = 1; bReadAddr = ldaddr + 4; end else if (func3 == 5 && (ldaddr & 3) == 3) begin /* lhu */ wRead = 1; bReadAddr = ldaddr + 4; end else begin wRead = 0; bReadAddr = 0; end end default: begin wRead = 0; bReadAddr = 0; end endcase end endmodule