From f54646d82d1f8487713a0b5a25780fe504eaffb1 Mon Sep 17 00:00:00 2001 From: kaltinsoy Date: Sun, 10 Aug 2025 01:51:26 +0300 Subject: [PATCH] ISA --- README.md | 1 + bench_iverilog.v | 30 ++++++++++ step4.v | 141 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 172 insertions(+) create mode 100644 bench_iverilog.v create mode 100644 step4.v diff --git a/README.md b/README.md index bd4130e..51f9442 100644 --- a/README.md +++ b/README.md @@ -6,3 +6,4 @@ - Check documentation Yosys ! - TOBB labs - Anki cards +- RISC-V ISA SET Manual diff --git a/bench_iverilog.v b/bench_iverilog.v new file mode 100644 index 0000000..c1664af --- /dev/null +++ b/bench_iverilog.v @@ -0,0 +1,30 @@ + +module bench(); + reg CLK; // Main clock + reg RESET; // Active-low reset + wire [4:0] LEDS; // LED outputs + reg RXD = 1'b1; // UART receive (idle high) + wire TXD; // UART transmit + + // Device Under Test + SOC uut( + .clk(CLK), + .rst_i(RESET), + .led(LEDS), + .RXD(RXD), + .TXD(TXD) + ); + + reg[4:0] prev_LEDS = 0; + initial begin + CLK = 0; + forever begin + #1 CLK = ~CLK; + if(LEDS != prev_LEDS) begin + $display("LEDS = %b",LEDS); + end + prev_LEDS <= LEDS; + end + end +endmodule + diff --git a/step4.v b/step4.v new file mode 100644 index 0000000..279fed3 --- /dev/null +++ b/step4.v @@ -0,0 +1,141 @@ +/** + * Step 4: Creating a RISC-V processor + * The instruction decoder + * central LED blinks, other LEDs show instr type. + * DONE* + */ + +`default_nettype none +`include "clockworks.v" + +module SOC ( + input clk, // system clock + input rst_i, // reset button + output [4:0] led, // system LEDs + input RXD, // UART receive + output TXD // UART transmit +); + + wire clk_i; // internal clock + wire resetn; // internal reset signal, goes low on reset + + reg [31:0] MEM [0:255]; + reg [31:0] PC; // program counter + reg [31:0] instr; // current instruction + + initial begin + PC = 0; + // add x0, x0, x0 + // rs2 rs1 add rd ALUREG + instr = 32'b0000000_00000_00000_000_00000_0110011; + // add x1, x0, x0 + // rs2 rs1 add rd ALUREG + MEM[0] = 32'b0000000_00000_00000_000_00001_0110011; + // addi x1, x1, 1 + // imm rs1 add rd ALUIMM + MEM[1] = 32'b000000000001_00001_000_00001_0010011; + // addi x1, x1, 1 + // imm rs1 add rd ALUIMM + MEM[2] = 32'b000000000001_00001_000_00001_0010011; + // addi x1, x1, 1 + // imm rs1 add rd ALUIMM + MEM[3] = 32'b000000000001_00001_000_00001_0010011; + // addi x1, x1, 1 + // imm rs1 add rd ALUIMM + MEM[4] = 32'b000000000001_00001_000_00001_0010011; + // lw x2,0(x1) + // imm rs1 w rd LOAD + MEM[5] = 32'b000000000000_00001_010_00010_0000011; + // sw x2,0(x1) + // imm rs2 rs1 w imm STORE + MEM[6] = 32'b000000_00010_00001_010_00000_0100011; + + // ebreak + // SYSTEM + MEM[7] = 32'b000000000001_00000_000_00000_1110011; + + end + + + // See the table P. 105 in RISC-V manual + + // The 10 RISC-V instructions + wire isALUreg = (instr[6:0] == 7'b0110011); // rd <- rs1 OP rs2 + wire isALUimm = (instr[6:0] == 7'b0010011); // rd <- rs1 OP Iimm + wire isBranch = (instr[6:0] == 7'b1100011); // if(rs1 OP rs2) PC<-PC+Bimm + wire isJALR = (instr[6:0] == 7'b1100111); // rd <- PC+4; PC<-rs1+Iimm + wire isJAL = (instr[6:0] == 7'b1101111); // rd <- PC+4; PC<-PC+Jimm + wire isAUIPC = (instr[6:0] == 7'b0010111); // rd <- PC + Uimm + wire isLUI = (instr[6:0] == 7'b0110111); // rd <- Uimm + wire isLoad = (instr[6:0] == 7'b0000011); // rd <- mem[rs1+Iimm] + wire isStore = (instr[6:0] == 7'b0100011); // mem[rs1+Simm] <- rs2 + wire isSYSTEM = (instr[6:0] == 7'b1110011); // special + + // The 5 immediate formats + wire [31:0] Uimm={ instr[31], instr[30:12], {12{1'b0}}}; + wire [31:0] Iimm={{21{instr[31]}}, instr[30:20]}; + wire [31:0] Simm={{21{instr[31]}}, instr[30:25],instr[11:7]}; + wire [31:0] Bimm={{20{instr[31]}}, instr[7],instr[30:25],instr[11:8],1'b0}; + wire [31:0] Jimm={{12{instr[31]}}, instr[19:12],instr[20],instr[30:21],1'b0}; + + // Source and destination registers + wire [4:0] rs1Id = instr[19:15]; + wire [4:0] rs2Id = instr[24:20]; + wire [4:0] rdId = instr[11:7]; + + // function codes + wire [2:0] funct3 = instr[14:12]; + wire [6:0] funct7 = instr[31:25]; + + always @(posedge clk_i) begin + if(!resetn) begin + PC <= 0; + instr <= 32'b0000000_00000_00000_000_00000_0110011; // NOP + end else if(!isSYSTEM) begin + instr <= MEM[PC]; + PC <= PC+1; + end +`ifdef BENCH + if(isSYSTEM) $finish(); +`endif + end + + assign led = isSYSTEM ? 31 : {PC[0],isALUreg,isALUimm,isStore,isLoad}; + +`ifdef BENCH + always @(posedge clk_i) begin + $display("PC=%0d",PC); + case (1'b1) + isALUreg: $display( + "ALUreg rd=%d rs1=%d rs2=%d funct3=%b", + rdId, rs1Id, rs2Id, funct3 + ); + isALUimm: $display( + "ALUimm rd=%d rs1=%d imm=%0d funct3=%b", + rdId, rs1Id, Iimm, funct3 + ); + isBranch: $display("BRANCH"); + isJAL: $display("JAL"); + isJALR: $display("JALR"); + isAUIPC: $display("AUIPC"); + isLUI: $display("LUI"); + isLoad: $display("LOAD"); + isStore: $display("STORE"); + isSYSTEM: $display("SYSTEM"); + endcase + end +`endif + + // Gearbox and reset circuitry. + Clockworks #( + .SLOW(21) // Divide clock frequency by 2^21 + )CW( + .CLK(clk), + .RESET(rst_i), + .clk(clk_i), + .resetn(resetn) + ); + + assign TXD = 1'b0; // not used for now +endmodule +