This commit is contained in:
2025-08-10 01:51:26 +03:00
parent a7b59c12a7
commit f54646d82d
3 changed files with 172 additions and 0 deletions

141
step4.v Normal file
View File

@@ -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