`default_nettype none module rv30(input wire clk, input wire [1:0] but, output wire [1:0] led); // 47 instructions total : 25 done! :) parameter FENCE = 5'b00011; parameter RT = 5'b01100; // RT = R-type instructions opcode (last 2 bits 11 removed) parameter IT_1 = 5'b11100; parameter IT_2 = 5'b00100; parameter BT = 5'b11000; parameter UT_1 = 5'b01101; // LUI parameter UT_2 = 5'b00101; // AUIPC parameter JT = 5'b11011; // JAL parameter IT_4 = 5'b11001; // JALR parameter IT_3 = 5'b00000; parameter ST = 5'b01000; //reg [16:0] program [31:0]; // for testing only reg [31:0] rvx [15:0]; // RV32E, 32 registers not required - riscv registers reg [31:0] pc = 32'h00000000; reg [1:0] led_r; assign led[1] = led_r[1]; wire clk_24k; reg [11:0] clk_div; always @(posedge clk) begin clk_div = clk_div + 12'b1; end assign clk_24k = clk_div[11]; reg [29:0] instr; reg compute=1'b0; always @(posedge but[0]) begin rvx[0] = 32'h00000000; rvx[8] = 32'h00000003; rvx[15] = 32'h73468a89; // program[0] = 30'b011011010110011110000101000100; //fill in instr instr = 30'b011011010110011110000101000100; compute=1'b1; end // ======================= // below statement will not work //reg [29:0] instr [5:0]; // 30-bit instructions tied to first 30 bits assign led[0] = (rvx[10]==32'b11111111111111111111111001101011) ? 1 : 0 ; reg [4:0] opcode; reg [19:0] imm; wire [2:0] funct3; wire [6:0] funct7; assign funct3 = instr[12:10]; assign funct7 = instr[29:23]; always @(posedge clk_24k) begin if (compute==1'b1) begin led_r[1]=1'b1; // instr = program[pc][31:2]; opcode = instr[4:0]; case ({funct3, opcode}) {3'bxxx, UT_1}: begin // LUI rvx[instr[9:5]] = {instr[29:10], 12'h000}; pc = pc + 32'h00000001; end {3'bxxx, UT_2}: begin // AUIPC rvx[instr[9:5]] = pc + {instr[29:10], 12'h000}; pc = pc + 32'h00000001; end /* {3'bxxx, JT}: begin // JAL rvx[instr[9:5]] = pc + 32'h00000004; pc = pc + end {3'bxxx, IT_4}: begin // JALR end */ // increments pc - Jump instruction - last bit is zero because pc is incremented in multiples of 2 as seen in spec. {3'b000, BT}: pc = pc + ((instr[17:13]==instr[22:18]) ? {20{instr[29]}, instr[5], instr[28:23], instr[9:6], 1'b0} : 1); // BEQ x equality not allowed {3'b001, BT}: pc = pc + ((instr[17:13]!=instr[22:18]) ? {20{instr[29]}, instr[5], instr[28:23], instr[9:6], 1'b0} : 1); // BNE x inequality not allowed {3'b100, BT}: pc = pc + ((instr[17:13]=instr[22:18]) ? {20{instr[29]}, instr[5], instr[28:23], instr[9:6], 1'b0} : 1); // BGE {3'b110, BT}: pc = pc + ((instr[17:13]=instr[22:18]) ? {20{instr[29]}, instr[5], instr[28:23], instr[9:6], 1'b0} : 1); // BGEU /* {3'b000, IT_3}: // LB fetch from memory and store in rd (32-bit) {3'b001, IT_3}: // LH fetch from memory, sign extend to 32-bit and store in rd (16-bit) {3'b010, IT_3}: // rvx[17:13] + {20{instr[29]}, instr[29:18]} // LW fetch from memory, zero extend to 32-bit and store in rd (16-bit) {3'b100, IT_3}: // LBU fetch from memory, sign extend to 32-bit and store in rd (8-bit) {3'b101, IT_3}: // LHU fetch from memory, zero-extend to 32-bit and store in rd (8-bit) */ // rs1 + {instr[29:29], instr[9:5]} // address in RAM /* {3'b000, ST}: begin // SB // store rs2 to above memory end {3'b001, ST}: begin // SH // store rs2[15:0] to above memory end {3'b010, ST}: begin // SW // store rs2[7:0] to above memory end */ {3'b000, IT_2}: begin // ADDI rvx[instr[9:5]] = rvx[instr[17:13]] + {{20{instr[29]}},{instr[29:18]}}; // adds sign extended imm pc = pc + 32'h00000001; end {3'b010, IT_2}: begin // SLTI rvx[instr[9:5]] = (rvx[instr[17:13]] < {{20{instr[29]}},{instr[29:18]}}); pc = pc + 32'h00000001; end {3'b011, IT_2}: begin // SLTIU rvx[instr[9:5]] = (rvx[instr[17:13]]==32'h00000000) ? 32'h00000001 : 32'h00000000 ; pc = pc + 32'h00000001; end {3'b100, IT_2}: begin // XORI rvx[instr[9:5]] = (rvx[instr[17:13]] ^ {{20{instr[29]}},{instr[29:18]}}); pc = pc + 32'h00000001; end {3'b110, IT_2}: begin // ORI rvx[instr[9:5]] = (rvx[instr[17:13]] | {{20{instr[29]}},{instr[29:18]}}); pc = pc + 32'h00000001; end {3'b111, IT_2}: begin // ANDI rvx[instr[9:5]] = (rvx[instr[17:13]] & {{20{instr[29]}},{instr[29:18]}}); pc = pc + 32'h00000001; end {3'b001, IT_2}: begin // SLLI - shamt rvx[instr[9:5]] = rvx[instr[17:13]] << rvx[instr[22:18]][4:0]; pc = pc + 32'h00000001; end {3'b101, IT_2}: begin // SRLI or SRAI -shamt case (instr[29]) 1'b1: begin //SRAI rvx[instr[9:5]] = rvx[instr[17:13]] >> rvx[instr[22:18]][4:0]; pc = pc + 32'h00000001; end 1'b0: begin //SRLI rvx[instr[9:5]] = rvx[instr[17:13]] >>> rvx[instr[22:18]][4:0]; pc = pc + 32'h00000001; end // default: ; endcase end // default: compute=1'b0; // instructions ADD to AND {3'b000, RT}: begin // ADD or SUB case (instr[29]) 1'b1: begin //SUB rvx[instr[9:5]] = rvx[instr[17:13]] - rvx[instr[22:18]]; pc = pc + 32'h00000001; end 1'b0: begin //ADD rvx[instr[9:5]] = rvx[instr[17:13]] + rvx[instr[22:18]]; pc = pc + 32'h00000001; end // default: ; endcase end {3'b001, RT}: begin // SLL rvx[instr[9:5]] = rvx[instr[17:13]] << rvx[instr[22:18]][4:0]; // recheck indexing of arrays pc = pc + 32'h00000001; end {3'b010, RT}: begin // SLT rvx[instr[9:5]] = (rvx[instr[17:13]] < rvx[instr[22:18]]) ? 32'h00000001 : 32'h00000000; //recheck, is verilog default signed or unsigned pc = pc + 32'h00000001; end {3'b011, RT}: begin // SLTU rvx[instr[9:5]] = (rvx[instr[17:13]] < rvx[instr[22:18]]) ? 32'h00000001 : 32'h00000000; //recheck, is verilog default signed or unsigned pc = pc + 32'h00000001; end {3'b100, RT}: begin // XOR rvx[instr[9:5]] = rvx[instr[17:13]] ^ rvx[instr[22:18]]; pc = pc + 32'h00000001; end {3'b101, RT}: begin // SRL or SRA case (instr[29]) 1'b1: begin //SRA rvx[instr[9:5]] = rvx[instr[17:13]] >>> rvx[instr[22:18]][4:0]; pc = pc + 32'h00000001; end 1'b0: begin //SRL rvx[instr[9:5]] = rvx[instr[17:13]] >> rvx[instr[22:18]][4:0]; pc = pc + 32'h00000001; end // default: ; endcase end {3'b110, RT}: begin // OR rvx[instr[9:5]] = rvx[instr[17:13]] | rvx[instr[22:18]]; pc = pc + 32'h00000001; end {3'b111, RT}: begin // AND rvx[instr[9:5]] = rvx[instr[17:13]] & rvx[instr[22:18]]; pc = pc + 32'h00000001; end // default: compute=1'b0; end /* {3'b000, FENCE}: case (instr[10]) begin 1'b0: // FENCE 1'b1: // FENCE.I endcase */ /* {3'b000, IT_1}: begin // ECALL or EBREAK case (instr[18]) 1'b1: // EBREAK 1'b0: // ECALL endcase end {3'b001, IT_1}: // CSRRW {3'b010, IT_1}: // CSRRS {3'b011, IT_1}: // CSRRC {3'b101, IT_1}: // CSRRWI {3'b110, IT_1}: // CSRRSI {3'b111, IT_1}: // CSRRCI */ // default: compute=1'b0; endcase compute=1'b0; end // if compute else if (compute==1'b0) begin // in case of z or x, defaults to 0. led_r[1]=1'b0; // fetch 16-bit word //pc = pc+1; // fetch 16-bit word // if valid instruction, set compute=1 // else fetch 1 more, repeat //compute=1'b1; end end //always block // ram is stored generally as 16-bit words. So the algo for fetching instruction is, // fetch twice // check if it is a valid instruction // fetch once // stop at end of memory. endmodule