RISC-V CORE
This commit is contained in:
		
							
								
								
									
										286
									
								
								FINAL/RISCCore.v
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										286
									
								
								FINAL/RISCCore.v
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,286 @@ | |||||||
|  | module RISCCore ( | ||||||
|  |   input rst, | ||||||
|  |   input clk, | ||||||
|  |   output reg [31:0] pc, | ||||||
|  |   output wire [31:0] next_pc,  // Changed to wire | ||||||
|  |   output wire [31:0] instr | ||||||
|  | ); | ||||||
|  |  | ||||||
|  |   // IMem - reduced size for simplicity | ||||||
|  |   reg [31:0] imem [0:63]; | ||||||
|  |   initial begin | ||||||
|  |     $readmemh("program.hex", imem); | ||||||
|  |   end | ||||||
|  |   assign instr = (pc[31:2] < 64) ? imem[pc[31:2]] : 32'h00000013;  // Word-aligned access | ||||||
|  |  | ||||||
|  |   //Data Mem | ||||||
|  |   reg [31:0] dmem [0:31]; | ||||||
|  |   wire [31:0] ld_data; | ||||||
|  |   wire [4:0] word_addr = mem_addr[6:2]; | ||||||
|  |  | ||||||
|  |   integer j; | ||||||
|  |   initial begin | ||||||
|  |     for(j = 0; j < 32; j = j + 1) begin | ||||||
|  |       dmem[j] = 32'b0; | ||||||
|  |     end  | ||||||
|  |   end | ||||||
|  |  | ||||||
|  |   assign ld_data = (word_addr < 32) ? dmem[word_addr] : 32'b0; | ||||||
|  |  | ||||||
|  |   // Instruction decoder | ||||||
|  |   wire [6:0] opcode = instr[6:0]; | ||||||
|  |   wire [4:0] rs1 = instr[19:15]; | ||||||
|  |   wire [4:0] rs2 = instr[24:20]; | ||||||
|  |   wire [4:0] rd = instr[11:7]; | ||||||
|  |   wire [2:0] funct3 = instr[14:12]; | ||||||
|  |   wire [6:0] funct7 = instr[31:25]; | ||||||
|  |  | ||||||
|  |   // Instruction type detection | ||||||
|  |   wire isUType = (opcode == 7'b0110111) || (opcode == 7'b0010111);  // LUI, AUIPC | ||||||
|  |   wire isIType = (opcode == 7'b0000011) || (opcode == 7'b0000111) ||  // LOAD | ||||||
|  |                  (opcode == 7'b0010011) || (opcode == 7'b0011011) ||  // OP-IMM | ||||||
|  |                  (opcode == 7'b1100111);                               // JALR | ||||||
|  |   wire isRType = (opcode == 7'b0110011) || (opcode == 7'b0111011);     // OP | ||||||
|  |   wire isSType = (opcode == 7'b0100011) || (opcode == 7'b0100111);     // STORE | ||||||
|  |   wire isBType = (opcode == 7'b1100011);                               // BRANCH | ||||||
|  |   wire isJType = (opcode == 7'b1101111);                               // JAL | ||||||
|  |  | ||||||
|  |   // Immediate generation | ||||||
|  |   wire [31:0] Iimm = {{20{instr[31]}}, instr[31:20]}; | ||||||
|  |   wire [31:0] Simm = {{20{instr[31]}}, instr[31:25], instr[11:7]}; | ||||||
|  |   wire [31:0] Bimm = {{19{instr[31]}}, instr[31], instr[7], instr[30:25], instr[11:8], 1'b0}; | ||||||
|  |   wire [31:0] Uimm = {instr[31:12], 12'b0}; | ||||||
|  |   wire [31:0] Jimm = {{11{instr[31]}}, instr[31], instr[19:12], instr[20], instr[30:21], 1'b0}; | ||||||
|  |  | ||||||
|  |   // Register file | ||||||
|  |    // Initialize register file (x0 always zero) | ||||||
|  |   reg [31:0] rf [0:31]; //Register file | ||||||
|  |   integer i; | ||||||
|  |   initial begin | ||||||
|  |     for (i = 0; i < 32; i = i + 1) begin | ||||||
|  |       rf[i] = 32'b0; | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  |  | ||||||
|  |   // Read ports | ||||||
|  |   wire [31:0] rs1_val = (rs1 != 0) ? rf[rs1] : 32'b0; | ||||||
|  |   wire [31:0] rs2_val = (rs2 != 0) ? rf[rs2] : 32'b0; | ||||||
|  |  | ||||||
|  |   // Instruction decoding | ||||||
|  |   wire isADDI = (opcode == 7'b0010011) && (funct3 == 3'b000); | ||||||
|  |   wire isADD = (opcode == 7'b0110011) && (funct3 == 3'b000) && (funct7 == 7'b0000000);   | ||||||
|  |   // Branch instructions | ||||||
|  |   wire isBEQ  = (isBType) && (funct3 == 3'b000); | ||||||
|  |   wire isBNE  = (isBType) && (funct3 == 3'b001); | ||||||
|  |   wire isBLT  = (isBType) && (funct3 == 3'b100); | ||||||
|  |   wire isBGE  = (isBType) && (funct3 == 3'b101); | ||||||
|  |   wire isBLTU = (isBType) && (funct3 == 3'b110); | ||||||
|  |   wire isBGEU = (isBType) && (funct3 == 3'b111); | ||||||
|  |  | ||||||
|  |   //store load instructions | ||||||
|  |   wire isLB = (isIType) && (funct3 == 3'b000); | ||||||
|  |   wire isLH = (isIType) && (funct3 == 3'b001); | ||||||
|  |   wire isLW = (opcode == 7'b0000011) && (funct3 == 3'b010); | ||||||
|  |   wire isLBU = (isIType) && (funct3 == 3'b100); | ||||||
|  |   wire isLHU = (isIType) && (funct3 == 3'b101); | ||||||
|  |  | ||||||
|  |   wire isSB = (isSType) && (funct3 == 3'b000); | ||||||
|  |   wire isSH = (isSType) && (funct3 == 3'b001); | ||||||
|  |   wire isSW = (opcode == 7'b0100011) && (funct3 == 3'b010); | ||||||
|  |  | ||||||
|  |   //sl and sr instructions | ||||||
|  |   wire isSLT = (isRType) && (funct3 == 3'b010) && (funct7[5] == 1'b0); | ||||||
|  |   wire isSLTU = (isRType) && (funct3 == 3'b011) && (funct7[5] == 1'b0); | ||||||
|  |   wire isSLL  = (opcode == 7'b0110011) && (funct3 == 3'b001) && (funct7 == 7'b0000000); | ||||||
|  |   wire isSLTI = (isIType) && (funct3 == 3'b010); | ||||||
|  |   wire isSLTIU = (isIType) && (funct3 == 3'b011); | ||||||
|  |  | ||||||
|  |   wire isSRL  = (opcode == 7'b0110011) && (funct3 == 3'b101) && (funct7 == 7'b0000000); | ||||||
|  |   wire isSRA  = (opcode == 7'b0110011) && (funct3 == 3'b101) && (funct7 == 7'b0100000); | ||||||
|  |  | ||||||
|  |   wire isSLLI = (opcode == 7'b0010011) && (funct3 == 3'b001) && (funct7[6:1] == 6'b000000); | ||||||
|  |   wire isSRLI = (opcode == 7'b0010011) && (funct3 == 3'b101) && (funct7[6:1] == 6'b000000); | ||||||
|  |   wire isSRAI = (opcode == 7'b0010011) && (funct3 == 3'b101) && (funct7[6:1] == 6'b010000); | ||||||
|  |  | ||||||
|  |   //logic imms | ||||||
|  |   wire isANDI = (opcode == 7'b0010011) && (funct3 == 3'b111); | ||||||
|  |   wire isORI  = (opcode == 7'b0010011) && (funct3 == 3'b110); | ||||||
|  |   wire isXORI = (opcode == 7'b0010011) && (funct3 == 3'b100); | ||||||
|  |   // logic | ||||||
|  |   wire isAND  = (opcode == 7'b0110011) && (funct3 == 3'b111) && (funct7 == 7'b0000000); | ||||||
|  |   wire isOR   = (opcode == 7'b0110011) && (funct3 == 3'b110) && (funct7 == 7'b0000000); | ||||||
|  |   wire isXOR  = (opcode == 7'b0110011) && (funct3 == 3'b100) && (funct7 == 7'b0000000); | ||||||
|  |   wire isSUB = (opcode == 7'b0110011) && (funct3 == 3'b000) && (funct7 == 7'b0100000); | ||||||
|  |   //lui auipc (opcode use) | ||||||
|  |   wire isLUI = (opcode == 7'b0110111);  | ||||||
|  |   wire isAUIPC = (opcode == 7'b0010111); | ||||||
|  |   wire isJAL = (opcode == 7'b1101111); | ||||||
|  |   //jal UType | ||||||
|  |  | ||||||
|  |   wire isJALR = (opcode == 7'b1100111) && (funct3 == 3'b000); | ||||||
|  |  | ||||||
|  |   //Mem address calculation | ||||||
|  |   wire [31:0] mem_addr = (is_mem_op) ? alu_result : 32'b0; | ||||||
|  |  | ||||||
|  |   //Mem address logic | ||||||
|  |   //For simplicity we only implement all loads as word loads (lw) | ||||||
|  |   //byte/halfword ignored | ||||||
|  |   wire is_load = (opcode == 7'b0000011);  // All load instructions | ||||||
|  |   wire is_store = (opcode == 7'b0100011); // All store instructions | ||||||
|  |   wire is_mem_op = is_store || is_load; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | //Load operations | ||||||
|  |  | ||||||
|  |   reg [31:0] load_data; | ||||||
|  |  | ||||||
|  |   always @(*) begin  | ||||||
|  |     if (mem_addr[1:0] == 2'b00) begin  | ||||||
|  |       case (funct3) | ||||||
|  |         3'b000: load_data = {{24{ld_data[7]}}, ld_data[7:0]}; | ||||||
|  |         3'b001: load_data = {{16{ld_data[15]}}, ld_data[15:0]}; | ||||||
|  |         3'b010: load_data = ld_data; | ||||||
|  |         3'b100: load_data = {24'b0, ld_data[7:0]}; | ||||||
|  |         3'b101: load_data = {16'b0, ld_data[15:0]}; | ||||||
|  |         default: load_data = 32'b0; | ||||||
|  |       endcase | ||||||
|  |     end else begin  | ||||||
|  |       load_data = 32'b0; | ||||||
|  |       if (is_load) begin  // Only show error for actual loads | ||||||
|  |         $display("ERROR: Misaligned memory address at addr %h", mem_addr); | ||||||
|  |       end | ||||||
|  |     end  | ||||||
|  |   end | ||||||
|  |  | ||||||
|  | //Store operations | ||||||
|  | always @(*) begin  | ||||||
|  |   if (!rst && is_store && (word_addr < 32) && (mem_addr[1:0] == 2'b00)) begin  | ||||||
|  |     case (funct3) | ||||||
|  |       3'b000: begin //SB: store byte 0  | ||||||
|  |         dmem[word_addr][7:0] = rs2_val[7:0]; | ||||||
|  |       end  | ||||||
|  |       3'b001: begin //SH: store halfword | ||||||
|  |         dmem[word_addr][15:0] = rs2_val[15:0]; | ||||||
|  |       end  | ||||||
|  |       3'b010: begin //SW: store word  | ||||||
|  |         dmem[word_addr] = rs2_val; | ||||||
|  |       end  | ||||||
|  |     endcase | ||||||
|  |     $display("MEM Write: word_addr=%h, data=%h", word_addr, rs2_val); | ||||||
|  |   end | ||||||
|  | end | ||||||
|  |   // ALU operations | ||||||
|  |  | ||||||
|  |   //sltu and slt | ||||||
|  |   wire [31:0] sltu_rslt = {31'b0, (rs1_val < rs2_val)}; | ||||||
|  |   wire [31:0] signed_slt = (rs1_val[31] && !rs2_val[31]) ? 1'b1 : | ||||||
|  |                            (!rs1_val[31] && rs2_val[31]) ? 1'b0 : | ||||||
|  |                            (rs1_val < rs2_val); | ||||||
|  |   wire [31:0] slt_rslt = {31'b0, signed_slt}; | ||||||
|  |   wire [31:0] slti_rslt = ((rs1_val[31] == Iimm[31]) ? sltu_rslt : {31'b0, rs1_val[31]}); | ||||||
|  |  | ||||||
|  |   wire [63:0] SErs1_val = {{32{rs1_val[31]}}, (rs1_val < rs2_val)}; | ||||||
|  |  | ||||||
|  |   wire [63:0] sra_rslt = {SErs1_val >> rs2_val[4:0]}; | ||||||
|  |   wire [63:0] srai_rslt = {SErs1_val >> Iimm[4:0]}; | ||||||
|  |   wire [31:0] sltiu_rslt = {31'b0, (rs1_val < Iimm)}; | ||||||
|  |   | ||||||
|  |   wire [31:0] alu_result = (is_mem_op) ? (rs1_val + Iimm) : // Mem address computation | ||||||
|  |                            (isADDI) ? (rs1_val + Iimm) : | ||||||
|  |                            (isADD) ? (rs1_val + rs2_val) :  | ||||||
|  |                            (isSLT) ? slt_rslt : | ||||||
|  |                            (isSLTU) ? sltu_rslt : | ||||||
|  |                            (isSLTI) ? slti_rslt : | ||||||
|  |                            (isANDI) ? (rs1_val & Iimm) : | ||||||
|  |                            (isORI) ? (rs1_val | Iimm) : | ||||||
|  |                            (isXORI) ? (rs1_val ^ Iimm) : | ||||||
|  |                            (isSLLI) ? (rs1_val << Iimm[4:0]) : | ||||||
|  |                            (isSRLI) ? (rs1_val >> Iimm[4:0]) : | ||||||
|  |                            (isAND) ? (rs1_val & rs2_val) : | ||||||
|  |                            (isOR) ? (rs1_val | rs2_val) : | ||||||
|  |                            (isXOR) ? (rs1_val ^ rs2_val) : | ||||||
|  |                            (isSUB) ? (rs1_val - rs2_val) : | ||||||
|  |                            (isSLL) ? (rs1_val << rs2_val[4:0]) : | ||||||
|  |                            (isSRL) ? (rs1_val >> rs2_val[4:0]) : | ||||||
|  |                            (isSLTIU) ? (sltiu_rslt) : | ||||||
|  |                            (isLUI) ? ({Iimm[31:12], 12'b0}) : | ||||||
|  |                            (isAUIPC) ? (pc + Iimm) : | ||||||
|  |                            (isJAL || isJALR) ? (pc + 32'd4) : | ||||||
|  |                            (isSRA) ? (sra_rslt[31:0]) : | ||||||
|  |                            (isSRAI) ? (srai_rslt[31:0]) : | ||||||
|  |                            32'b0; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   wire signed [31:0] signed_rs1 = rs1_val; | ||||||
|  |   wire signed [31:0] signed_rs2 = rs2_val; | ||||||
|  |  | ||||||
|  |   wire branch_taken = | ||||||
|  |       isBEQ  ? (rs1_val == rs2_val) : | ||||||
|  |       isBNE  ? (rs1_val != rs2_val) : | ||||||
|  |       isBLT  ? (signed_rs1 < signed_rs2) : | ||||||
|  |       isBGE  ? (signed_rs1 >= signed_rs2) : | ||||||
|  |       isBLTU ? (rs1_val < rs2_val) : | ||||||
|  |       isBGEU ? (rs1_val >= rs2_val) : | ||||||
|  |       1'b0; | ||||||
|  |  | ||||||
|  |   // Next PC calculation - FIXED: using wire for continuous assignment | ||||||
|  |   wire [31:0] branch_target = pc + Bimm; | ||||||
|  |   wire [31:0] next_pc_base = pc + 32'h4; | ||||||
|  |   wire [31:0] jalr_tgt_pc = rs1_val + Iimm; | ||||||
|  |    | ||||||
|  |   assign next_pc = branch_taken ? branch_target : | ||||||
|  |                    isJAL ? branch_target : | ||||||
|  |                    isJALR ? jalr_tgt_pc : | ||||||
|  |                    next_pc_base; | ||||||
|  |  | ||||||
|  |   // Register write back | ||||||
|  |   wire rf_write_enable = (rd != 0) && ( | ||||||
|  |                           isADDI || isADD || isSUB || | ||||||
|  |                           isJAL || isJALR || | ||||||
|  |                           isSLT || isSLTU || isSLTI || isSLTIU || | ||||||
|  |                           isSLL || isSRL || isSRA || isSLLI || isSRLI || isSRAI || | ||||||
|  |                           isLB || isLH || isLW || isLBU || isLHU || | ||||||
|  |                           isXORI || isORI || isANDI || | ||||||
|  |                           isXOR || isOR || isAND || | ||||||
|  |                           is_load || isLUI || isAUIPC | ||||||
|  |                         ); | ||||||
|  |    | ||||||
|  |  | ||||||
|  |   wire [31:0] writeback_data = is_load ? load_data : alu_result; | ||||||
|  |  | ||||||
|  |   // PC update | ||||||
|  |   always @(posedge clk) begin | ||||||
|  |     if (rst) begin | ||||||
|  |       pc <= 32'h0; | ||||||
|  |     end else begin | ||||||
|  |       pc <= next_pc; | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  |  | ||||||
|  |   // Register write back | ||||||
|  | always @(posedge clk) begin | ||||||
|  |   if (rf_write_enable && !rst) begin | ||||||
|  |     rf[rd] <= writeback_data;  // Use writeback_data instead of alu_result | ||||||
|  |     $display("RF Write: x%d = %h", rd, writeback_data); | ||||||
|  |   end | ||||||
|  | end   | ||||||
|  |  | ||||||
|  | // Debug monitoring | ||||||
|  |   always @(posedge clk) begin | ||||||
|  |     if (!rst) begin | ||||||
|  |       $display("PC=%08h, Instr=%08h, rs1=x%d(%h), rs2=x%d(%h), rd=x%d, branch_taken=%b", | ||||||
|  |                pc, instr, rs1, rs1_val, rs2, rs2_val, rd, branch_taken); | ||||||
|  |       if (pc[1:0] != 2'b00) begin | ||||||
|  |         $display("WARNING: PC not word-aligned: %h", pc); | ||||||
|  |       end | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  |    | ||||||
|  |   always @(posedge clk) begin | ||||||
|  |     if (!rst && (opcode == 7'b0000011)) begin | ||||||
|  |       $display("LOAD: byte_addr=%h, word_addr=%h, data=%h, funct3=%b",  | ||||||
|  |                mem_addr, word_addr, load_data, funct3); | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  |  | ||||||
|  | endmodule | ||||||
							
								
								
									
										62
									
								
								FINAL/RISCCore_tb.v
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								FINAL/RISCCore_tb.v
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,62 @@ | |||||||
|  | `timescale 1ns/1ps | ||||||
|  |  | ||||||
|  | module RISCCore_tb; | ||||||
|  |   reg clk; | ||||||
|  |   reg rst; | ||||||
|  |   wire [31:0] pc; | ||||||
|  |   wire [31:0] next_pc; | ||||||
|  |   wire [31:0] instr; | ||||||
|  |    | ||||||
|  |   // Instantiate the RISC-V core | ||||||
|  |   RISCCore uut ( | ||||||
|  |     .rst(rst), | ||||||
|  |     .clk(clk), | ||||||
|  |     .pc(pc), | ||||||
|  |     .next_pc(next_pc), | ||||||
|  |     .instr(instr) | ||||||
|  |   ); | ||||||
|  |    | ||||||
|  |   // Clock generation | ||||||
|  |   always #5 clk = ~clk; | ||||||
|  |    | ||||||
|  |   // Initialize signals | ||||||
|  |   initial begin | ||||||
|  |     clk = 0; | ||||||
|  |     rst = 1; | ||||||
|  |      | ||||||
|  |     // Reset sequence | ||||||
|  |     #10 rst = 0; | ||||||
|  |      | ||||||
|  |     // Run for enough clock cycles | ||||||
|  |     #500; | ||||||
|  |      | ||||||
|  |     // Display final register values | ||||||
|  |     $display("\n=== FINAL REGISTER STATE ==="); | ||||||
|  |     $display("x1 (ra)  = %h", uut.rf[1]); | ||||||
|  |     $display("x2 (sp)  = %h", uut.rf[2]); | ||||||
|  |     $display("x3 (gp)  = %h", uut.rf[3]); | ||||||
|  |     $display("x4 (tp)  = %h", uut.rf[4]); | ||||||
|  |     $display("x5 (t0)  = %h", uut.rf[5]); | ||||||
|  |     $display("x6 (t1)  = %h", uut.rf[6]); | ||||||
|  |     $display("x7 (t2)  = %h", uut.rf[7]); | ||||||
|  |     $display("x8 (s0)  = %h", uut.rf[8]); | ||||||
|  |     $display("x10 (a0) = %h", uut.rf[10]); | ||||||
|  |      | ||||||
|  |     // Display memory contents | ||||||
|  |     $display("\n=== MEMORY STATE ==="); | ||||||
|  |     begin : memory_display | ||||||
|  |       integer i; | ||||||
|  |       for (i = 0; i < 10; i = i + 1) begin | ||||||
|  |         $display("mem[%0d] = %h", i, uut.dmem[i]); | ||||||
|  |       end | ||||||
|  |     end | ||||||
|  |      | ||||||
|  |     $finish; | ||||||
|  |   end | ||||||
|  |    | ||||||
|  |   // Simple monitor | ||||||
|  |   initial begin | ||||||
|  |     $monitor("Time=%0t: PC=%h, Instr=%h", $time, uut.pc, uut.instr); | ||||||
|  |   end | ||||||
|  |    | ||||||
|  | endmodule | ||||||
							
								
								
									
										12
									
								
								FINAL/program.hex
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								FINAL/program.hex
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | |||||||
|  | 00000093  // addi x1, x0, 0   - x1 = 0 | ||||||
|  | 00100113  // addi x2, x0, 1   - x2 = 1   | ||||||
|  | 00200193  // addi x3, x0, 2   - x3 = 2 | ||||||
|  | 003081b3  // add  x3, x1, x3  - x3 = 0 + 2 = 2 | ||||||
|  | 00420233  // add  x4, x4, x4  - x4 = x4 + x4 (should be 0) | ||||||
|  | 00228463  // beq  x5, x2, 8   - branch if x5 == x2 (should not take) | ||||||
|  | 00400463  // beq  x0, x4, 8   - branch if 0 == 0 (should take) | ||||||
|  | 00a00513  // addi x10, x0, 10 - x10 = 10 (should be skipped) | ||||||
|  | fff00513  // addi x10, x0, -1 - x10 = -1 (should execute) | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
							
								
								
									
										1318
									
								
								FINAL/risc_tb
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										1318
									
								
								FINAL/risc_tb
									
									
									
									
									
										Executable file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										286
									
								
								chapter5/RISCCore.v
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										286
									
								
								chapter5/RISCCore.v
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,286 @@ | |||||||
|  | module RISCCore ( | ||||||
|  |   input rst, | ||||||
|  |   input clk, | ||||||
|  |   output reg [31:0] pc, | ||||||
|  |   output wire [31:0] next_pc,  // Changed to wire | ||||||
|  |   output wire [31:0] instr | ||||||
|  | ); | ||||||
|  |  | ||||||
|  |   // IMem - reduced size for simplicity | ||||||
|  |   reg [31:0] imem [0:63]; | ||||||
|  |   initial begin | ||||||
|  |     $readmemh("program.hex", imem); | ||||||
|  |   end | ||||||
|  |   assign instr = (pc[31:2] < 64) ? imem[pc[31:2]] : 32'h00000013;  // Word-aligned access | ||||||
|  |  | ||||||
|  |   //Data Mem | ||||||
|  |   reg [31:0] dmem [0:31]; | ||||||
|  |   wire [31:0] ld_data; | ||||||
|  |   wire [4:0] word_addr = mem_addr[6:2]; | ||||||
|  |  | ||||||
|  |   integer j; | ||||||
|  |   initial begin | ||||||
|  |     for(j = 0; j < 32; j = j + 1) begin | ||||||
|  |       dmem[j] = 32'b0; | ||||||
|  |     end  | ||||||
|  |   end | ||||||
|  |  | ||||||
|  |   assign ld_data = (word_addr < 32) ? dmem[word_addr] : 32'b0; | ||||||
|  |  | ||||||
|  |   // Instruction decoder | ||||||
|  |   wire [6:0] opcode = instr[6:0]; | ||||||
|  |   wire [4:0] rs1 = instr[19:15]; | ||||||
|  |   wire [4:0] rs2 = instr[24:20]; | ||||||
|  |   wire [4:0] rd = instr[11:7]; | ||||||
|  |   wire [2:0] funct3 = instr[14:12]; | ||||||
|  |   wire [6:0] funct7 = instr[31:25]; | ||||||
|  |  | ||||||
|  |   // Instruction type detection | ||||||
|  |   wire isUType = (opcode == 7'b0110111) || (opcode == 7'b0010111);  // LUI, AUIPC | ||||||
|  |   wire isIType = (opcode == 7'b0000011) || (opcode == 7'b0000111) ||  // LOAD | ||||||
|  |                  (opcode == 7'b0010011) || (opcode == 7'b0011011) ||  // OP-IMM | ||||||
|  |                  (opcode == 7'b1100111);                               // JALR | ||||||
|  |   wire isRType = (opcode == 7'b0110011) || (opcode == 7'b0111011);     // OP | ||||||
|  |   wire isSType = (opcode == 7'b0100011) || (opcode == 7'b0100111);     // STORE | ||||||
|  |   wire isBType = (opcode == 7'b1100011);                               // BRANCH | ||||||
|  |   wire isJType = (opcode == 7'b1101111);                               // JAL | ||||||
|  |  | ||||||
|  |   // Immediate generation | ||||||
|  |   wire [31:0] Iimm = {{20{instr[31]}}, instr[31:20]}; | ||||||
|  |   wire [31:0] Simm = {{20{instr[31]}}, instr[31:25], instr[11:7]}; | ||||||
|  |   wire [31:0] Bimm = {{19{instr[31]}}, instr[31], instr[7], instr[30:25], instr[11:8], 1'b0}; | ||||||
|  |   wire [31:0] Uimm = {instr[31:12], 12'b0}; | ||||||
|  |   wire [31:0] Jimm = {{11{instr[31]}}, instr[31], instr[19:12], instr[20], instr[30:21], 1'b0}; | ||||||
|  |  | ||||||
|  |   // Register file | ||||||
|  |    // Initialize register file (x0 always zero) | ||||||
|  |   reg [31:0] rf [0:31]; //Register file | ||||||
|  |   integer i; | ||||||
|  |   initial begin | ||||||
|  |     for (i = 0; i < 32; i = i + 1) begin | ||||||
|  |       rf[i] = 32'b0; | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  |  | ||||||
|  |   // Read ports | ||||||
|  |   wire [31:0] rs1_val = (rs1 != 0) ? rf[rs1] : 32'b0; | ||||||
|  |   wire [31:0] rs2_val = (rs2 != 0) ? rf[rs2] : 32'b0; | ||||||
|  |  | ||||||
|  |   // Instruction decoding | ||||||
|  |   wire isADDI = (opcode == 7'b0010011) && (funct3 == 3'b000); | ||||||
|  |   wire isADD = (opcode == 7'b0110011) && (funct3 == 3'b000) && (funct7 == 7'b0000000);   | ||||||
|  |   // Branch instructions | ||||||
|  |   wire isBEQ  = (isBType) && (funct3 == 3'b000); | ||||||
|  |   wire isBNE  = (isBType) && (funct3 == 3'b001); | ||||||
|  |   wire isBLT  = (isBType) && (funct3 == 3'b100); | ||||||
|  |   wire isBGE  = (isBType) && (funct3 == 3'b101); | ||||||
|  |   wire isBLTU = (isBType) && (funct3 == 3'b110); | ||||||
|  |   wire isBGEU = (isBType) && (funct3 == 3'b111); | ||||||
|  |  | ||||||
|  |   //store load instructions | ||||||
|  |   wire isLB = (isIType) && (funct3 == 3'b000); | ||||||
|  |   wire isLH = (isIType) && (funct3 == 3'b001); | ||||||
|  |   wire isLW = (opcode == 7'b0000011) && (funct3 == 3'b010); | ||||||
|  |   wire isLBU = (isIType) && (funct3 == 3'b100); | ||||||
|  |   wire isLHU = (isIType) && (funct3 == 3'b101); | ||||||
|  |  | ||||||
|  |   wire isSB = (isSType) && (funct3 == 3'b000); | ||||||
|  |   wire isSH = (isSType) && (funct3 == 3'b001); | ||||||
|  |   wire isSW = (opcode == 7'b0100011) && (funct3 == 3'b010); | ||||||
|  |  | ||||||
|  |   //sl and sr instructions | ||||||
|  |   wire isSLT = (isRType) && (funct3 == 3'b010) && (funct7[5] == 1'b0); | ||||||
|  |   wire isSLTU = (isRType) && (funct3 == 3'b011) && (funct7[5] == 1'b0); | ||||||
|  |   wire isSLL  = (opcode == 7'b0110011) && (funct3 == 3'b001) && (funct7 == 7'b0000000); | ||||||
|  |   wire isSLTI = (isIType) && (funct3 == 3'b010); | ||||||
|  |   wire isSLTIU = (isIType) && (funct3 == 3'b011); | ||||||
|  |  | ||||||
|  |   wire isSRL  = (opcode == 7'b0110011) && (funct3 == 3'b101) && (funct7 == 7'b0000000); | ||||||
|  |   wire isSRA  = (opcode == 7'b0110011) && (funct3 == 3'b101) && (funct7 == 7'b0100000); | ||||||
|  |  | ||||||
|  |   wire isSLLI = (opcode == 7'b0010011) && (funct3 == 3'b001) && (funct7[6:1] == 6'b000000); | ||||||
|  |   wire isSRLI = (opcode == 7'b0010011) && (funct3 == 3'b101) && (funct7[6:1] == 6'b000000); | ||||||
|  |   wire isSRAI = (opcode == 7'b0010011) && (funct3 == 3'b101) && (funct7[6:1] == 6'b010000); | ||||||
|  |  | ||||||
|  |   //logic imms | ||||||
|  |   wire isANDI = (opcode == 7'b0010011) && (funct3 == 3'b111); | ||||||
|  |   wire isORI  = (opcode == 7'b0010011) && (funct3 == 3'b110); | ||||||
|  |   wire isXORI = (opcode == 7'b0010011) && (funct3 == 3'b100); | ||||||
|  |   // logic | ||||||
|  |   wire isAND  = (opcode == 7'b0110011) && (funct3 == 3'b111) && (funct7 == 7'b0000000); | ||||||
|  |   wire isOR   = (opcode == 7'b0110011) && (funct3 == 3'b110) && (funct7 == 7'b0000000); | ||||||
|  |   wire isXOR  = (opcode == 7'b0110011) && (funct3 == 3'b100) && (funct7 == 7'b0000000); | ||||||
|  |   wire isSUB = (opcode == 7'b0110011) && (funct3 == 3'b000) && (funct7 == 7'b0100000); | ||||||
|  |   //lui auipc (opcode use) | ||||||
|  |   wire isLUI = (opcode == 7'b0110111);  | ||||||
|  |   wire isAUIPC = (opcode == 7'b0010111); | ||||||
|  |   wire isJAL = (opcode == 7'b1101111); | ||||||
|  |   //jal UType | ||||||
|  |  | ||||||
|  |   wire isJALR = (opcode == 7'b1100111) && (funct3 == 3'b000); | ||||||
|  |  | ||||||
|  |   //Mem address calculation | ||||||
|  |   wire [31:0] mem_addr = (is_mem_op) ? alu_result : 32'b0; | ||||||
|  |  | ||||||
|  |   //Mem address logic | ||||||
|  |   //For simplicity we only implement all loads as word loads (lw) | ||||||
|  |   //byte/halfword ignored | ||||||
|  |   wire is_load = (opcode == 7'b0000011);  // All load instructions | ||||||
|  |   wire is_store = (opcode == 7'b0100011); // All store instructions | ||||||
|  |   wire is_mem_op = is_store || is_load; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | //Load operations | ||||||
|  |  | ||||||
|  |   reg [31:0] load_data; | ||||||
|  |  | ||||||
|  |   always @(*) begin  | ||||||
|  |     if (mem_addr[1:0] == 2'b00) begin  | ||||||
|  |       case (funct3) | ||||||
|  |         3'b000: load_data = {{24{ld_data[7]}}, ld_data[7:0]}; | ||||||
|  |         3'b001: load_data = {{16{ld_data[15]}}, ld_data[15:0]}; | ||||||
|  |         3'b010: load_data = ld_data; | ||||||
|  |         3'b100: load_data = {24'b0, ld_data[7:0]}; | ||||||
|  |         3'b101: load_data = {16'b0, ld_data[15:0]}; | ||||||
|  |         default: load_data = 32'b0; | ||||||
|  |       endcase | ||||||
|  |     end else begin  | ||||||
|  |       load_data = 32'b0; | ||||||
|  |       if (is_load) begin  // Only show error for actual loads | ||||||
|  |         $display("ERROR: Misaligned memory address at addr %h", mem_addr); | ||||||
|  |       end | ||||||
|  |     end  | ||||||
|  |   end | ||||||
|  |  | ||||||
|  | //Store operations | ||||||
|  | always @(*) begin  | ||||||
|  |   if (!rst && is_store && (word_addr < 32) && (mem_addr[1:0] == 2'b00)) begin  | ||||||
|  |     case (funct3) | ||||||
|  |       3'b000: begin //SB: store byte 0  | ||||||
|  |         dmem[word_addr][7:0] = rs2_val[7:0]; | ||||||
|  |       end  | ||||||
|  |       3'b001: begin //SH: store halfword | ||||||
|  |         dmem[word_addr][15:0] = rs2_val[15:0]; | ||||||
|  |       end  | ||||||
|  |       3'b010: begin //SW: store word  | ||||||
|  |         dmem[word_addr] = rs2_val; | ||||||
|  |       end  | ||||||
|  |     endcase | ||||||
|  |     $display("MEM Write: word_addr=%h, data=%h", word_addr, rs2_val); | ||||||
|  |   end | ||||||
|  | end | ||||||
|  |   // ALU operations | ||||||
|  |  | ||||||
|  |   //sltu and slt | ||||||
|  |   wire [31:0] sltu_rslt = {31'b0, (rs1_val < rs2_val)}; | ||||||
|  |   wire [31:0] signed_slt = (rs1_val[31] && !rs2_val[31]) ? 1'b1 : | ||||||
|  |                            (!rs1_val[31] && rs2_val[31]) ? 1'b0 : | ||||||
|  |                            (rs1_val < rs2_val); | ||||||
|  |   wire [31:0] slt_rslt = {31'b0, signed_slt}; | ||||||
|  |   wire [31:0] slti_rslt = ((rs1_val[31] == Iimm[31]) ? sltu_rslt : {31'b0, rs1_val[31]}); | ||||||
|  |  | ||||||
|  |   wire [63:0] SErs1_val = {{32{rs1_val[31]}}, (rs1_val < rs2_val)}; | ||||||
|  |  | ||||||
|  |   wire [63:0] sra_rslt = {SErs1_val >> rs2_val[4:0]}; | ||||||
|  |   wire [63:0] srai_rslt = {SErs1_val >> Iimm[4:0]}; | ||||||
|  |   wire [31:0] sltiu_rslt = {31'b0, (rs1_val < Iimm)}; | ||||||
|  |   | ||||||
|  |   wire [31:0] alu_result = (is_mem_op) ? (rs1_val + Iimm) : // Mem address computation | ||||||
|  |                            (isADDI) ? (rs1_val + Iimm) : | ||||||
|  |                            (isADD) ? (rs1_val + rs2_val) :  | ||||||
|  |                            (isSLT) ? slt_rslt : | ||||||
|  |                            (isSLTU) ? sltu_rslt : | ||||||
|  |                            (isSLTI) ? slti_rslt : | ||||||
|  |                            (isANDI) ? (rs1_val & Iimm) : | ||||||
|  |                            (isORI) ? (rs1_val | Iimm) : | ||||||
|  |                            (isXORI) ? (rs1_val ^ Iimm) : | ||||||
|  |                            (isSLLI) ? (rs1_val << Iimm[4:0]) : | ||||||
|  |                            (isSRLI) ? (rs1_val >> Iimm[4:0]) : | ||||||
|  |                            (isAND) ? (rs1_val & rs2_val) : | ||||||
|  |                            (isOR) ? (rs1_val | rs2_val) : | ||||||
|  |                            (isXOR) ? (rs1_val ^ rs2_val) : | ||||||
|  |                            (isSUB) ? (rs1_val - rs2_val) : | ||||||
|  |                            (isSLL) ? (rs1_val << rs2_val[4:0]) : | ||||||
|  |                            (isSRL) ? (rs1_val >> rs2_val[4:0]) : | ||||||
|  |                            (isSLTIU) ? (sltiu_rslt) : | ||||||
|  |                            (isLUI) ? ({Iimm[31:12], 12'b0}) : | ||||||
|  |                            (isAUIPC) ? (pc + Iimm) : | ||||||
|  |                            (isJAL || isJALR) ? (pc + 32'd4) : | ||||||
|  |                            (isSRA) ? (sra_rslt[31:0]) : | ||||||
|  |                            (isSRAI) ? (srai_rslt[31:0]) : | ||||||
|  |                            32'b0; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   wire signed [31:0] signed_rs1 = rs1_val; | ||||||
|  |   wire signed [31:0] signed_rs2 = rs2_val; | ||||||
|  |  | ||||||
|  |   wire branch_taken = | ||||||
|  |       isBEQ  ? (rs1_val == rs2_val) : | ||||||
|  |       isBNE  ? (rs1_val != rs2_val) : | ||||||
|  |       isBLT  ? (signed_rs1 < signed_rs2) : | ||||||
|  |       isBGE  ? (signed_rs1 >= signed_rs2) : | ||||||
|  |       isBLTU ? (rs1_val < rs2_val) : | ||||||
|  |       isBGEU ? (rs1_val >= rs2_val) : | ||||||
|  |       1'b0; | ||||||
|  |  | ||||||
|  |   // Next PC calculation - FIXED: using wire for continuous assignment | ||||||
|  |   wire [31:0] branch_target = pc + Bimm; | ||||||
|  |   wire [31:0] next_pc_base = pc + 32'h4; | ||||||
|  |   wire [31:0] jalr_tgt_pc = rs1_val + Iimm; | ||||||
|  |    | ||||||
|  |   assign next_pc = branch_taken ? branch_target : | ||||||
|  |                    isJAL ? branch_target : | ||||||
|  |                    isJALR ? jalr_tgt_pc : | ||||||
|  |                    next_pc_base; | ||||||
|  |  | ||||||
|  |   // Register write back | ||||||
|  |   wire rf_write_enable = (rd != 0) && ( | ||||||
|  |                           isADDI || isADD || isSUB || | ||||||
|  |                           isJAL || isJALR || | ||||||
|  |                           isSLT || isSLTU || isSLTI || isSLTIU || | ||||||
|  |                           isSLL || isSRL || isSRA || isSLLI || isSRLI || isSRAI || | ||||||
|  |                           isLB || isLH || isLW || isLBU || isLHU || | ||||||
|  |                           isXORI || isORI || isANDI || | ||||||
|  |                           isXOR || isOR || isAND || | ||||||
|  |                           is_load || isLUI || isAUIPC | ||||||
|  |                         ); | ||||||
|  |    | ||||||
|  |  | ||||||
|  |   wire [31:0] writeback_data = is_load ? load_data : alu_result; | ||||||
|  |  | ||||||
|  |   // PC update | ||||||
|  |   always @(posedge clk) begin | ||||||
|  |     if (rst) begin | ||||||
|  |       pc <= 32'h0; | ||||||
|  |     end else begin | ||||||
|  |       pc <= next_pc; | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  |  | ||||||
|  |   // Register write back | ||||||
|  | always @(posedge clk) begin | ||||||
|  |   if (rf_write_enable && !rst) begin | ||||||
|  |     rf[rd] <= writeback_data;  // Use writeback_data instead of alu_result | ||||||
|  |     $display("RF Write: x%d = %h", rd, writeback_data); | ||||||
|  |   end | ||||||
|  | end   | ||||||
|  |  | ||||||
|  | // Debug monitoring | ||||||
|  |   always @(posedge clk) begin | ||||||
|  |     if (!rst) begin | ||||||
|  |       $display("PC=%08h, Instr=%08h, rs1=x%d(%h), rs2=x%d(%h), rd=x%d, branch_taken=%b", | ||||||
|  |                pc, instr, rs1, rs1_val, rs2, rs2_val, rd, branch_taken); | ||||||
|  |       if (pc[1:0] != 2'b00) begin | ||||||
|  |         $display("WARNING: PC not word-aligned: %h", pc); | ||||||
|  |       end | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  |    | ||||||
|  |   always @(posedge clk) begin | ||||||
|  |     if (!rst && (opcode == 7'b0000011)) begin | ||||||
|  |       $display("LOAD: byte_addr=%h, word_addr=%h, data=%h, funct3=%b",  | ||||||
|  |                mem_addr, word_addr, load_data, funct3); | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  |  | ||||||
|  | endmodule | ||||||
							
								
								
									
										55
									
								
								chapter5/RISCCore_0.2tb.v
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								chapter5/RISCCore_0.2tb.v
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,55 @@ | |||||||
|  | module RISCCore_tb; | ||||||
|  |   reg clk; | ||||||
|  |   reg rst; | ||||||
|  |   wire [31:0] pc; | ||||||
|  |   wire [31:0] next_pc; | ||||||
|  |   wire [31:0] instr; | ||||||
|  |    | ||||||
|  |   // Instantiate the RISC-V core | ||||||
|  |   RISCCore uut ( | ||||||
|  |     .rst(rst), | ||||||
|  |     .clk(clk), | ||||||
|  |     .pc(pc), | ||||||
|  |     .next_pc(next_pc), | ||||||
|  |     .instr(instr) | ||||||
|  |   ); | ||||||
|  |    | ||||||
|  |   // Clock generation | ||||||
|  |   always #5 clk = ~clk; | ||||||
|  |    | ||||||
|  |   // Test sequence | ||||||
|  |   initial begin | ||||||
|  |     // Initialize signals | ||||||
|  |     clk = 0; | ||||||
|  |     rst = 1; | ||||||
|  |      | ||||||
|  |     // Apply reset | ||||||
|  |     #10 rst = 0; | ||||||
|  |      | ||||||
|  |     // Run for 100 clock cycles | ||||||
|  |     #1000; | ||||||
|  |      | ||||||
|  |     // Display final register values | ||||||
|  |     $display("\n=== Final Register Values ==="); | ||||||
|  |     for (integer i = 0; i < 32; i = i + 1) begin | ||||||
|  |       if (uut.rf[i] != 0) begin | ||||||
|  |         $display("x%d = %h", i, uut.rf[i]); | ||||||
|  |       end | ||||||
|  |     end | ||||||
|  |      | ||||||
|  |     // Display final memory contents | ||||||
|  |     $display("\n=== Final Memory Contents ==="); | ||||||
|  |     for (integer i = 0; i < 32; i = i + 1) begin | ||||||
|  |       if (uut.dmem[i] != 0) begin | ||||||
|  |         $display("Mem[%d] = %h", i, uut.dmem[i]); | ||||||
|  |       end | ||||||
|  |     end | ||||||
|  |      | ||||||
|  |     $finish; | ||||||
|  |   end | ||||||
|  |    | ||||||
|  |   // Monitor important signals | ||||||
|  |   initial begin | ||||||
|  |     $monitor("Time=%0t, PC=%h, Instr=%h", $time, pc, instr); | ||||||
|  |   end | ||||||
|  | endmodule | ||||||
							
								
								
									
										62
									
								
								chapter5/RISCCore_tb.v
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								chapter5/RISCCore_tb.v
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,62 @@ | |||||||
|  | `timescale 1ns/1ps | ||||||
|  |  | ||||||
|  | module RISCCore_tb; | ||||||
|  |   reg clk; | ||||||
|  |   reg rst; | ||||||
|  |   wire [31:0] pc; | ||||||
|  |   wire [31:0] next_pc; | ||||||
|  |   wire [31:0] instr; | ||||||
|  |    | ||||||
|  |   // Instantiate the RISC-V core | ||||||
|  |   RISCCore uut ( | ||||||
|  |     .rst(rst), | ||||||
|  |     .clk(clk), | ||||||
|  |     .pc(pc), | ||||||
|  |     .next_pc(next_pc), | ||||||
|  |     .instr(instr) | ||||||
|  |   ); | ||||||
|  |    | ||||||
|  |   // Clock generation | ||||||
|  |   always #5 clk = ~clk; | ||||||
|  |    | ||||||
|  |   // Initialize signals | ||||||
|  |   initial begin | ||||||
|  |     clk = 0; | ||||||
|  |     rst = 1; | ||||||
|  |      | ||||||
|  |     // Reset sequence | ||||||
|  |     #10 rst = 0; | ||||||
|  |      | ||||||
|  |     // Run for enough clock cycles | ||||||
|  |     #500; | ||||||
|  |      | ||||||
|  |     // Display final register values | ||||||
|  |     $display("\n=== FINAL REGISTER STATE ==="); | ||||||
|  |     $display("x1 (ra)  = %h", uut.rf[1]); | ||||||
|  |     $display("x2 (sp)  = %h", uut.rf[2]); | ||||||
|  |     $display("x3 (gp)  = %h", uut.rf[3]); | ||||||
|  |     $display("x4 (tp)  = %h", uut.rf[4]); | ||||||
|  |     $display("x5 (t0)  = %h", uut.rf[5]); | ||||||
|  |     $display("x6 (t1)  = %h", uut.rf[6]); | ||||||
|  |     $display("x7 (t2)  = %h", uut.rf[7]); | ||||||
|  |     $display("x8 (s0)  = %h", uut.rf[8]); | ||||||
|  |     $display("x10 (a0) = %h", uut.rf[10]); | ||||||
|  |      | ||||||
|  |     // Display memory contents | ||||||
|  |     $display("\n=== MEMORY STATE ==="); | ||||||
|  |     begin : memory_display | ||||||
|  |       integer i; | ||||||
|  |       for (i = 0; i < 10; i = i + 1) begin | ||||||
|  |         $display("mem[%0d] = %h", i, uut.dmem[i]); | ||||||
|  |       end | ||||||
|  |     end | ||||||
|  |      | ||||||
|  |     $finish; | ||||||
|  |   end | ||||||
|  |    | ||||||
|  |   // Simple monitor | ||||||
|  |   initial begin | ||||||
|  |     $monitor("Time=%0t: PC=%h, Instr=%h", $time, uut.pc, uut.instr); | ||||||
|  |   end | ||||||
|  |    | ||||||
|  | endmodule | ||||||
							
								
								
									
										287
									
								
								chapter5/RISCcore0.2.v
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										287
									
								
								chapter5/RISCcore0.2.v
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,287 @@ | |||||||
|  | module RISCCore ( | ||||||
|  |   input rst, | ||||||
|  |   input clk, | ||||||
|  |   output reg [31:0] pc, | ||||||
|  |   output wire [31:0] next_pc,  // Changed to wire | ||||||
|  |   output wire [31:0] instr | ||||||
|  | ); | ||||||
|  |  | ||||||
|  |   // IMem - reduced size for simplicity | ||||||
|  |   reg [31:0] imem [0:63]; | ||||||
|  |   initial begin | ||||||
|  |     $readmemh("program.hex", imem); | ||||||
|  |   end | ||||||
|  |   assign instr = (pc[31:2] < 64) ? imem[pc[31:2]] : 32'h00000013;  // Word-aligned access | ||||||
|  |  | ||||||
|  |   //Data Mem | ||||||
|  |   reg [31:0] dmem [0:31]; | ||||||
|  |   wire [31:0] ld_data; | ||||||
|  |   wire [4:0] word_addr = mem_addr[6:2]; | ||||||
|  |  | ||||||
|  |   integer j; | ||||||
|  |   initial begin | ||||||
|  |     for(j = 0; j < 32; j = j + 1) begin | ||||||
|  |       dmem[j] = 32'b0; | ||||||
|  |     end  | ||||||
|  |   end | ||||||
|  |  | ||||||
|  |   assign ld_data = (word_addr < 32) ? dmem[word_addr] : 32'b0; | ||||||
|  |  | ||||||
|  |   // Instruction decoder | ||||||
|  |   wire [6:0] opcode = instr[6:0]; | ||||||
|  |   wire [4:0] rs1 = instr[19:15]; | ||||||
|  |   wire [4:0] rs2 = instr[24:20]; | ||||||
|  |   wire [4:0] rd = instr[11:7]; | ||||||
|  |   wire [2:0] funct3 = instr[14:12]; | ||||||
|  |   wire [6:0] funct7 = instr[31:25]; | ||||||
|  |  | ||||||
|  |   // Instruction type detection | ||||||
|  |   wire isUType = (opcode == 7'b0110111) || (opcode == 7'b0010111);  // LUI, AUIPC | ||||||
|  |   wire isIType = (opcode == 7'b0000011) || (opcode == 7'b0000111) ||  // LOAD | ||||||
|  |                  (opcode == 7'b0010011) || (opcode == 7'b0011011) ||  // OP-IMM | ||||||
|  |                  (opcode == 7'b1100111);                               // JALR | ||||||
|  |   wire isRType = (opcode == 7'b0110011) || (opcode == 7'b0111011);     // OP | ||||||
|  |   wire isSType = (opcode == 7'b0100011) || (opcode == 7'b0100111);     // STORE | ||||||
|  |   wire isBType = (opcode == 7'b1100011);                               // BRANCH | ||||||
|  |   wire isJType = (opcode == 7'b1101111);                               // JAL | ||||||
|  |  | ||||||
|  |   // Immediate generation | ||||||
|  |   wire [31:0] Iimm = {{20{instr[31]}}, instr[31:20]}; | ||||||
|  |   wire [31:0] Simm = {{20{instr[31]}}, instr[31:25], instr[11:7]}; | ||||||
|  |   wire [31:0] Bimm = {{19{instr[31]}}, instr[31], instr[7], instr[30:25], instr[11:8], 1'b0}; | ||||||
|  |   wire [31:0] Uimm = {instr[31:12], 12'b0}; | ||||||
|  |   wire [31:0] Jimm = {{11{instr[31]}}, instr[31], instr[19:12], instr[20], instr[30:21], 1'b0}; | ||||||
|  |  | ||||||
|  |   // Register file | ||||||
|  |    // Initialize register file (x0 always zero) | ||||||
|  |   reg [31:0] rf [0:31]; //Register file | ||||||
|  |   integer i; | ||||||
|  |   initial begin | ||||||
|  |     for (i = 0; i < 32; i = i + 1) begin | ||||||
|  |       rf[i] = 32'b0; | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  |  | ||||||
|  |   // Read ports | ||||||
|  |   wire [31:0] rs1_val = (rs1 != 0) ? rf[rs1] : 32'b0; | ||||||
|  |   wire [31:0] rs2_val = (rs2 != 0) ? rf[rs2] : 32'b0; | ||||||
|  |  | ||||||
|  |   // Instruction decoding | ||||||
|  |   wire isADDI = (opcode == 7'b0010011) && (funct3 == 3'b000); | ||||||
|  |   wire isADD = (opcode == 7'b0110011) && (funct3 == 3'b000) && (funct7 == 7'b0000000);   | ||||||
|  |   // Branch instructions | ||||||
|  |   wire isBEQ  = (isBType) && (funct3 == 3'b000); | ||||||
|  |   wire isBNE  = (isBType) && (funct3 == 3'b001); | ||||||
|  |   wire isBLT  = (isBType) && (funct3 == 3'b100); | ||||||
|  |   wire isBGE  = (isBType) && (funct3 == 3'b101); | ||||||
|  |   wire isBLTU = (isBType) && (funct3 == 3'b110); | ||||||
|  |   wire isBGEU = (isBType) && (funct3 == 3'b111); | ||||||
|  |  | ||||||
|  |   //store load instructions | ||||||
|  |   wire isLB = (isIType) && (funct3 == 3'b000); | ||||||
|  |   wire isLH = (isIType) && (funct3 == 3'b001); | ||||||
|  |   wire isLW = (opcode == 7'b0000011) && (funct3 == 3'b010); | ||||||
|  |   wire isLBU = (isIType) && (funct3 == 3'b100); | ||||||
|  |   wire isLHU = (isIType) && (funct3 == 3'b101); | ||||||
|  |  | ||||||
|  |   wire isSB = (isSType) && (funct3 == 3'b000); | ||||||
|  |   wire isSH = (isSType) && (funct3 == 3'b001); | ||||||
|  |   wire isSW = (opcode == 7'b0100011) && (funct3 == 3'b010); | ||||||
|  |  | ||||||
|  |   //sl and sr instructions | ||||||
|  |   wire isSLT = (isRType) && (funct3 == 3'b010) && (funct7[5] == 1'b0); | ||||||
|  |   wire isSLTU = (isRType) && (funct3 == 3'b011) && (funct7[5] == 1'b0); | ||||||
|  |   wire isSLL  = (opcode == 7'b0110011) && (funct3 == 3'b001) && (funct7 == 7'b0000000); | ||||||
|  |   wire isSLTI = (isIType) && (funct3 == 3'b010); | ||||||
|  |   wire isSLTIU = (isIType) && (funct3 == 3'b011); | ||||||
|  |  | ||||||
|  |   wire isSRL  = (opcode == 7'b0110011) && (funct3 == 3'b101) && (funct7 == 7'b0000000); | ||||||
|  |   wire isSRA  = (opcode == 7'b0110011) && (funct3 == 3'b101) && (funct7 == 7'b0100000); | ||||||
|  |  | ||||||
|  |   wire isSLLI = (opcode == 7'b0010011) && (funct3 == 3'b001) && (funct7[6:1] == 6'b000000); | ||||||
|  |   wire isSRLI = (opcode == 7'b0010011) && (funct3 == 3'b101) && (funct7[6:1] == 6'b000000); | ||||||
|  |   wire isSRAI = (opcode == 7'b0010011) && (funct3 == 3'b101) && (funct7[6:1] == 6'b010000); | ||||||
|  |  | ||||||
|  |   //logic imms | ||||||
|  |   wire isANDI = (opcode == 7'b0010011) && (funct3 == 3'b111); | ||||||
|  |   wire isORI  = (opcode == 7'b0010011) && (funct3 == 3'b110); | ||||||
|  |   wire isXORI = (opcode == 7'b0010011) && (funct3 == 3'b100); | ||||||
|  |   // logic | ||||||
|  |   wire isAND  = (opcode == 7'b0110011) && (funct3 == 3'b111) && (funct7 == 7'b0000000); | ||||||
|  |   wire isOR   = (opcode == 7'b0110011) && (funct3 == 3'b110) && (funct7 == 7'b0000000); | ||||||
|  |   wire isXOR  = (opcode == 7'b0110011) && (funct3 == 3'b100) && (funct7 == 7'b0000000); | ||||||
|  |   wire isSUB = (opcode == 7'b0110011) && (funct3 == 3'b000) && (funct7 == 7'b0100000); | ||||||
|  |   //lui auipc (opcode use) | ||||||
|  |   wire isLUI = (opcode == 7'b0110111);  | ||||||
|  |   wire isAUIPC = (opcode == 7'b0010111); | ||||||
|  |   wire isJAL = (opcode == 7'b1101111); | ||||||
|  |   //jal UType | ||||||
|  |  | ||||||
|  |   wire isJALR = (opcode == 7'b1100111) && (funct3 == 3'b000); | ||||||
|  |  | ||||||
|  |   //Mem address calculation | ||||||
|  |   wire [31:0] mem_addr = alu_result; | ||||||
|  |  | ||||||
|  |   //Mem address logic | ||||||
|  |   //For simplicity we only implement all loads as word loads (lw) | ||||||
|  |   //byte/halfword ignored | ||||||
|  |   wire is_load = (opcode == 7'b0000011);  // All load instructions | ||||||
|  |   wire is_store = (opcode == 7'b0100011); // All store instructions | ||||||
|  |   wire is_mem_op = is_store || is_load; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   //Load operations | ||||||
|  |  | ||||||
|  |   reg [31:0] load_data; | ||||||
|  |   always @(*) begin  | ||||||
|  |     if (mem_addr[1:0] == 2'b00) begin  | ||||||
|  |       case (funct3) | ||||||
|  |         3'b000: load_data = {{24{ld_data[7]}}, ld_data[7:0]}; //LB sign-extended byte 0  | ||||||
|  |         3'b001: load_data = {{16{ld_data[15]}}, ld_data[15:0]}; //LH sign-extended halfword | ||||||
|  |         3'b010: load_data = ld_data; //LW full word | ||||||
|  |         3'b100: load_data = {24'b0, ld_data[7:0]}; //LBU zero-extended byte 0  | ||||||
|  |         3'b101: load_data = {16'b0, ld_data[15:0]}; // LHU zero-extended halfword | ||||||
|  |         default: load_data = 32'b0; | ||||||
|  |       endcase | ||||||
|  |     end else begin  | ||||||
|  |       load_data = 32'b0; // Misaligned access not supported | ||||||
|  |       $display("ERROR: Misaligned memory address at addr %h", mem_addr); | ||||||
|  |     end  | ||||||
|  |   end  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | //Store operations | ||||||
|  | always @(posedge clk) begin  | ||||||
|  |   if (!rst && (word_addr < 32) && (mem_addr[1:0] == 2'b00)) begin  | ||||||
|  |     case (funct3) | ||||||
|  |       3'b000: begin //SB: store byte 0  | ||||||
|  |         dmem[word_addr][7:0] <= rs2_val[7:0]; | ||||||
|  |       end  | ||||||
|  |       3'b001: begin //SH: store halfword | ||||||
|  |         dmem[word_addr][15:0] <= rs2_val[15:0]; | ||||||
|  |       end  | ||||||
|  |       3'b010: begin //SW: store word  | ||||||
|  |         dmem[word_addr] <= rs2_val; | ||||||
|  |       end  | ||||||
|  |     endcase | ||||||
|  |     $display("MEM Write: word_addr=%h, data=%h", word_addr, rs2_val); | ||||||
|  |   end | ||||||
|  | end | ||||||
|  |   // ALU operations | ||||||
|  |  | ||||||
|  |   //sltu and slt | ||||||
|  |   wire [31:0] sltu_rslt = {31'b0, (rs1_val < rs2_val)}; | ||||||
|  |   wire [31:0] signed_slt = (rs1_val[31] && !rs2_val[31]) ? 1'b1 : | ||||||
|  |                            (!rs1_val[31] && rs2_val[31]) ? 1'b0 : | ||||||
|  |                            (rs1_val < rs2_val); | ||||||
|  |   wire [31:0] slt_rslt = {31'b0, signed_slt}; | ||||||
|  |   wire [31:0] slti_rslt = ((rs1_val[31] == Iimm[31]) ? sltu_rslt : {31'b0, rs1_val[31]}); | ||||||
|  |  | ||||||
|  |   wire [63:0] SErs1_val = {{32{rs1_val[31]}}, (rs1_val < rs2_val)}; | ||||||
|  |  | ||||||
|  |   wire [63:0] sra_rslt = {SErs1_val >> rs2_val[4:0]}; | ||||||
|  |   wire [63:0] srai_rslt = {SErs1_val >> Iimm[4:0]}; | ||||||
|  |   wire [31:0] sltiu_rslt = {31'b0, (rs1_val < Iimm)}; | ||||||
|  |   | ||||||
|  |   wire [31:0] alu_result = (is_mem_op) ? (rs1_val + Iimm) & 32'hFFFFFFFC : // Mem address computation (force word alignment) | ||||||
|  |                            (isADDI) ? (rs1_val + Iimm) : | ||||||
|  |                            (isADD) ? (rs1_val + rs2_val) :  | ||||||
|  |                            (isSLT) ? slt_rslt : | ||||||
|  |                            (isSLTU) ? sltu_rslt : | ||||||
|  |                            (isSRA) ? sra_rslt : | ||||||
|  |                            (isSRAI) ? srai_rslt : | ||||||
|  |                            (isSLTI) ? slti_rslt : | ||||||
|  |                            (isANDI) ? (rs1_val & Iimm) : | ||||||
|  |                            (isORI) ? (rs1_val | Iimm) : | ||||||
|  |                            (isXORI) ? (rs1_val ^ Iimm) : | ||||||
|  |                            (isSLLI) ? (rs1_val << Iimm[4:0]) : | ||||||
|  |                            (isSRLI) ? (rs1_val >> Iimm[4:0]) : | ||||||
|  |                            (isAND) ? (rs1_val & rs2_val) : | ||||||
|  |                            (isOR) ? (rs1_val | rs2_val) : | ||||||
|  |                            (isXOR) ? (rs1_val ^ rs2_val) : | ||||||
|  |                            (isSUB) ? (rs1_val - rs2_val) : | ||||||
|  |                            (isSLL) ? (rs1_val << rs2_val[4:0]) : | ||||||
|  |                            (isSRL) ? (rs1_val >> rs2_val[4:0]) : | ||||||
|  |                            (isSLTIU) ? (sltiu_rslt) : | ||||||
|  |                            (isLUI) ? ({Iimm[31:12], 12'b0}) : | ||||||
|  |                            (isAUIPC) ? (pc + Iimm) : | ||||||
|  |                            (isJAL || isJALR) ? (pc + 32'd4) : | ||||||
|  |                            (isSRA) ? (sra_rslt[31:0]) : | ||||||
|  |                            (isSRAI) ? (srai_rslt[31:0]) : | ||||||
|  |                            (is_load) ? (load_data) : //For register writeback | ||||||
|  |                            32'b0; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   wire signed [31:0] signed_rs1 = rs1_val; | ||||||
|  |   wire signed [31:0] signed_rs2 = rs2_val; | ||||||
|  |  | ||||||
|  |   wire branch_taken = | ||||||
|  |       isBEQ  ? (rs1_val == rs2_val) : | ||||||
|  |       isBNE  ? (rs1_val != rs2_val) : | ||||||
|  |       isBLT  ? (signed_rs1 < signed_rs2) : | ||||||
|  |       isBGE  ? (signed_rs1 >= signed_rs2) : | ||||||
|  |       isBLTU ? (rs1_val < rs2_val) : | ||||||
|  |       isBGEU ? (rs1_val >= rs2_val) : | ||||||
|  |       1'b0; | ||||||
|  |  | ||||||
|  |   // Next PC calculation - FIXED: using wire for continuous assignment | ||||||
|  |   wire [31:0] branch_target = pc + Bimm; | ||||||
|  |   wire [31:0] next_pc_base = pc + 32'h4; | ||||||
|  |   wire [31:0] jalr_tgt_pc = rs1_val + Iimm; | ||||||
|  |    | ||||||
|  |   assign next_pc = branch_taken ? branch_target : | ||||||
|  |                    isJAL ? branch_target : | ||||||
|  |                    isJALR ? jalr_tgt_pc : | ||||||
|  |                    next_pc_base; | ||||||
|  |  | ||||||
|  |   // Register write back | ||||||
|  |   wire rf_write_enable = (rd != 0) && ( | ||||||
|  |                           isADDI || isADD || isSUB || | ||||||
|  |                           isJAL || isJALR || | ||||||
|  |                           isSLT || isSLTU || isSLTI || isSLTIU || | ||||||
|  |                           isSLL || isSRL || isSRA || isSLLI || isSRLI || isSRAI || | ||||||
|  |                           isLB || isLH || isLW || isLBU || isLHU || | ||||||
|  |                           isXORI || isORI || isANDI || | ||||||
|  |                           isXOR || isOR || isAND || | ||||||
|  |                           is_load || isLUI || isAUIPC | ||||||
|  |                         ); | ||||||
|  |    | ||||||
|  |  | ||||||
|  |   wire [31:0] writeback_data = is_load ? load_data : alu_result; | ||||||
|  |  | ||||||
|  |   // PC update | ||||||
|  |   always @(posedge clk) begin | ||||||
|  |     if (rst) begin | ||||||
|  |       pc <= 32'h0; | ||||||
|  |     end else begin | ||||||
|  |       pc <= next_pc; | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  |  | ||||||
|  |   // Register write back | ||||||
|  | always @(posedge clk) begin | ||||||
|  |   if (rf_write_enable && !rst) begin | ||||||
|  |     rf[rd] <= writeback_data;  // Use writeback_data instead of alu_result | ||||||
|  |     $display("RF Write: x%d = %h", rd, writeback_data); | ||||||
|  |   end | ||||||
|  | end   | ||||||
|  |  | ||||||
|  | // Debug monitoring | ||||||
|  |   always @(posedge clk) begin | ||||||
|  |     if (!rst) begin | ||||||
|  |       $display("PC=%08h, Instr=%08h, rs1=x%d(%h), rs2=x%d(%h), rd=x%d, branch_taken=%b", | ||||||
|  |                pc, instr, rs1, rs1_val, rs2, rs2_val, rd, branch_taken); | ||||||
|  |       if (pc[1:0] != 2'b00) begin | ||||||
|  |         $display("WARNING: PC not word-aligned: %h", pc); | ||||||
|  |       end | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  |    | ||||||
|  |   always @(posedge clk) begin | ||||||
|  |     if (!rst && (opcode == 7'b0000011)) begin | ||||||
|  |       $display("LOAD: byte_addr=%h, word_addr=%h, data=%h, funct3=%b",  | ||||||
|  |                mem_addr, word_addr, load_data, funct3); | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  |  | ||||||
|  | endmodule | ||||||
| @@ -11,7 +11,16 @@ module RISCcore2 ( | |||||||
|   initial begin |   initial begin | ||||||
|     $readmemh("program.hex", imem); |     $readmemh("program.hex", imem); | ||||||
|   end |   end | ||||||
|   assign instr = imem[pc[31:2]];  // Word-aligned access |   assign instr = (pc[31:2] < 64) ? imem[pc[31:2]] : 32'h00000013;  // Word-aligned access | ||||||
|  |  | ||||||
|  |   //Data Mem | ||||||
|  |   reg [31:0] dmem [0:63]; | ||||||
|  |   integer j; | ||||||
|  |   initial begin | ||||||
|  |     for(j = 0; j < 64; j = j + 1) begin | ||||||
|  |       dmem[j] = 32'b0; | ||||||
|  |     end  | ||||||
|  |   end | ||||||
|  |  | ||||||
|   // Instruction decoder |   // Instruction decoder | ||||||
|   wire [6:0] opcode = instr[6:0]; |   wire [6:0] opcode = instr[6:0]; | ||||||
| @@ -39,9 +48,7 @@ module RISCcore2 ( | |||||||
|   wire [31:0] Jimm = {{11{instr[31]}}, instr[31], instr[19:12], instr[20], instr[30:21], 1'b0}; |   wire [31:0] Jimm = {{11{instr[31]}}, instr[31], instr[19:12], instr[20], instr[30:21], 1'b0}; | ||||||
|  |  | ||||||
|   // Register file |   // Register file | ||||||
|   reg [31:0] rf [0:31]; |    // Initialize register file (x0 always zero) | ||||||
|    |  | ||||||
|   // Initialize register file (x0 always zero) |  | ||||||
|   integer i; |   integer i; | ||||||
|   initial begin |   initial begin | ||||||
|     for (i = 0; i < 32; i = i + 1) begin |     for (i = 0; i < 32; i = i + 1) begin | ||||||
| @@ -109,7 +116,58 @@ module RISCcore2 ( | |||||||
|  |  | ||||||
|   wire isJALR = (opcode == 7'b1100111) && (funct3 == 3'b000); |   wire isJALR = (opcode == 7'b1100111) && (funct3 == 3'b000); | ||||||
|  |  | ||||||
|  |   //Mem address calculation | ||||||
|  |   wire [31:0] mem_addr = alu_result; | ||||||
|  |   wire [31:0] word_addr = mem_addr[31:2]; | ||||||
|  |  | ||||||
|  |   //Mem address logic | ||||||
|  |   //For simplicity we only implement all loads as word loads (lw) | ||||||
|  |   //byte/halfword ignored | ||||||
|  |   wire is_load = (opcode == 7'b0000011);  // All load instructions | ||||||
|  |   wire is_store = (opcode == 7'b0100011); // All store instructions | ||||||
|  |   wire is_mem_op = is_store || is_load; | ||||||
|  |  | ||||||
|  |   assign loaded_data = (mem_addr[31:2] < 64) ? dmem[mem_addr[31:2]] : 32'b0; | ||||||
|  |  | ||||||
|  |   reg [31:0] load_data; | ||||||
|  |   always @(*) begin  | ||||||
|  |     if (mem_addr[1:0] == 2'b00) begin  | ||||||
|  |       case (funct3) | ||||||
|  |         3'b000: load_data = {{24{loaded_data[7]}}, loaded_data[7:0]}; //LB sign-extended byte 0  | ||||||
|  |         3'b001: load_data = {{16{loaded_data[15]}}, loaded_data[15:0]}; //LH sign-extended halfword | ||||||
|  |         3'b010: load_data = loaded_data; //LW full word | ||||||
|  |         3'b100: load_data = {24'b0, loaded_data[7:0]}; //LBU zero-extended byte 0  | ||||||
|  |         3'b101: load_data = {16'b0, loaded_data[15:0]}; // LHU zero-extended halfword | ||||||
|  |         default: load_data = 32'b0; | ||||||
|  |       endcase | ||||||
|  |     end else begin  | ||||||
|  |       load_data = 32'b0; // Misaligned access not supported | ||||||
|  |       $display("ERROR: Misaligned memory address at addr %h", mem_addr); | ||||||
|  |     end  | ||||||
|  |   end  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   //Store operations | ||||||
|  |   always @(posedge clk) begin  | ||||||
|  |     if (!rst && (word_addr < 64) && (mem_addr[1:0] == 2'b00)) begin  | ||||||
|  |       case (funct3) | ||||||
|  |         3'b000: begin //SB: store byte 0  | ||||||
|  |           dmem[word_addr][7:0] <= rs2_val[7:0]; | ||||||
|  |         end  | ||||||
|  |         3'b001: begin //SH: store halfword | ||||||
|  |           dmem[word_addr][15:0] <= rs2_val[15:0]; | ||||||
|  |         end  | ||||||
|  |         3'b010: begin //SW: store word  | ||||||
|  |         dmem[word_addr] <= rs2_val; | ||||||
|  |       end  | ||||||
|  |     endcase | ||||||
|  |       $display("MEM Write: word_addr=%h, data=%h", word_addr, rs2_val); | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  |  | ||||||
|  |  | ||||||
|   // ALU operations |   // ALU operations | ||||||
|  |  | ||||||
|   //sltu and slt |   //sltu and slt | ||||||
|   wire [31:0] sltu_rslt = {31'b0, (rs1_val < rs2_val)}; |   wire [31:0] sltu_rslt = {31'b0, (rs1_val < rs2_val)}; | ||||||
|   wire [31:0] signed_slt = (rs1_val[31] && !rs2_val[31]) ? 1'b1 : |   wire [31:0] signed_slt = (rs1_val[31] && !rs2_val[31]) ? 1'b1 : | ||||||
| @@ -124,7 +182,8 @@ module RISCcore2 ( | |||||||
|   wire [63:0] srai_rslt = {SErs1_val >> Iimm[4:0]}; |   wire [63:0] srai_rslt = {SErs1_val >> Iimm[4:0]}; | ||||||
|   wire [31:0] sltiu_rslt = {31'b0, (rs1_val < Iimm)}; |   wire [31:0] sltiu_rslt = {31'b0, (rs1_val < Iimm)}; | ||||||
|   |   | ||||||
|   wire [31:0] alu_result = (isADDI) ? (rs1_val + Iimm) : |   wire [31:0] alu_result = (is_mem_op) ? (rs1_val + Iimm) : //Mem address computation first | ||||||
|  |                            (isADDI) ? (rs1_val + Iimm) : | ||||||
|                            (isADD) ? (rs1_val + rs2_val) :  |                            (isADD) ? (rs1_val + rs2_val) :  | ||||||
|                            (isSLT) ? slt_rslt : |                            (isSLT) ? slt_rslt : | ||||||
|                            (isSLTU) ? sltu_rslt : |                            (isSLTU) ? sltu_rslt : | ||||||
| @@ -145,13 +204,13 @@ module RISCcore2 ( | |||||||
|                            (isSLTIU) ? (sltiu_rslt) : |                            (isSLTIU) ? (sltiu_rslt) : | ||||||
|                            (isLUI) ? ({Iimm[31:12], 12'b0}) : |                            (isLUI) ? ({Iimm[31:12], 12'b0}) : | ||||||
|                            (isAUIPC) ? (pc + Iimm) : |                            (isAUIPC) ? (pc + Iimm) : | ||||||
|                            (isJAL) ? (pc + 32'd4) : |                            (isJAL || isJALR) ? (pc + 32'd4) : | ||||||
|                            (isJALR) ? (pc + 32'd4) : |  | ||||||
|                            (isSRA) ? (sra_rslt[31:0]) : |                            (isSRA) ? (sra_rslt[31:0]) : | ||||||
|                            (isSRAI) ? (srai_rslt[31:0]) :  |                            (isSRAI) ? (srai_rslt[31:0]) : | ||||||
|  |                            (is_load) ? (load_data) : //For register writeback | ||||||
|                            32'b0; |                            32'b0; | ||||||
|  |  | ||||||
|   // Branch condition logic |  | ||||||
|   wire signed [31:0] signed_rs1 = rs1_val; |   wire signed [31:0] signed_rs1 = rs1_val; | ||||||
|   wire signed [31:0] signed_rs2 = rs2_val; |   wire signed [31:0] signed_rs2 = rs2_val; | ||||||
|  |  | ||||||
| @@ -164,14 +223,42 @@ module RISCcore2 ( | |||||||
|       isBGEU ? (rs1_val >= rs2_val) : |       isBGEU ? (rs1_val >= rs2_val) : | ||||||
|       1'b0; |       1'b0; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   // Store operations | ||||||
|  |   always @(posedge clk) begin  | ||||||
|  |     if(!rst) begin  | ||||||
|  |       if (is_store && (mem_addr[31:2] < 64)) begin  | ||||||
|  |         dmem[mem_addr[31:2]] <= rs2_val; | ||||||
|  |         $display("MEM Write: address = %h, data=%h", mem_addr, rs2_val); | ||||||
|  |       end  | ||||||
|  |     end  | ||||||
|  |   end  | ||||||
|  |  | ||||||
|  |  | ||||||
|   // Next PC calculation - FIXED: using wire for continuous assignment |   // Next PC calculation - FIXED: using wire for continuous assignment | ||||||
|   wire [31:0] branch_target = pc + Bimm; |   wire [31:0] branch_target = pc + Bimm; | ||||||
|   wire [31:0] next_pc_base = pc + 32'h4; |   wire [31:0] next_pc_base = pc + 32'h4; | ||||||
|   assign next_pc = branch_taken ? branch_target : next_pc_base; |   wire [31:0] jalr_tgt_pc = rs1_val + Iimm; | ||||||
|  |    | ||||||
|  |   assign next_pc = branch_taken ? branch_target : | ||||||
|  |                    isJAL ? branch_target : | ||||||
|  |                    isJALR ? jalr_tgt_pc : | ||||||
|  |                    next_pc_base; | ||||||
|  |  | ||||||
|   // Register write back |   // Register write back | ||||||
|   wire rf_write_enable = (rd != 0) && (isADDI || isADD); |   wire rf_write_enable = (rd != 0) && ( | ||||||
|   wire [31:0] writeback_data = alu_result; |                           isADDI || isADD || isSUB || | ||||||
|  |                           isJAL || isJALR || | ||||||
|  |                           isSLT || isSLTU || isSLTI || isSLTIU || | ||||||
|  |                           isSLL || isSRL || isSRA || isSLLI || isSRLI || isSRAI || | ||||||
|  |                           isLB || isLH || isLW || isLBU || isLHU || | ||||||
|  |                           isXORI || isORI || isANDI || | ||||||
|  |                           isXOR || isOR || isAND || | ||||||
|  |                           is_load || isLUI || isAUIPC | ||||||
|  |                         ); | ||||||
|  |    | ||||||
|  |  | ||||||
|  |   wire [31:0] writeback_data = is_load ? load_data : alu_result; | ||||||
|  |  | ||||||
|   // PC update |   // PC update | ||||||
|   always @(posedge clk) begin |   always @(posedge clk) begin | ||||||
| @@ -183,14 +270,14 @@ module RISCcore2 ( | |||||||
|   end |   end | ||||||
|  |  | ||||||
|   // Register write back |   // Register write back | ||||||
|   always @(posedge clk) begin | always @(posedge clk) begin | ||||||
|     if (rf_write_enable && !rst) begin |   if (rf_write_enable && !rst) begin | ||||||
|       rf[rd] <= writeback_data; |     rf[rd] <= writeback_data;  // Use writeback_data instead of alu_result | ||||||
|       $display("RF Write: x%d = %h", rd, writeback_data); |     $display("RF Write: x%d = %h", rd, writeback_data); | ||||||
|     end |  | ||||||
|   end |   end | ||||||
|  | end   | ||||||
|  |  | ||||||
|   // Debug monitoring | // Debug monitoring | ||||||
|   always @(posedge clk) begin |   always @(posedge clk) begin | ||||||
|     if (!rst) begin |     if (!rst) begin | ||||||
|       $display("PC=%08h, Instr=%08h, rs1=x%d(%h), rs2=x%d(%h), rd=x%d, branch_taken=%b", |       $display("PC=%08h, Instr=%08h, rs1=x%d(%h), rs2=x%d(%h), rd=x%d, branch_taken=%b", | ||||||
| @@ -200,5 +287,12 @@ module RISCcore2 ( | |||||||
|       end |       end | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
|  |    | ||||||
|  |   always @(posedge clk) begin | ||||||
|  |     if (!rst && (opcode == 7'b0000011)) begin | ||||||
|  |       $display("LOAD: byte_addr=%h, word_addr=%h, data=%h, funct3=%b",  | ||||||
|  |                mem_addr, word_addr, load_data, funct3); | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  |  | ||||||
| endmodule | endmodule | ||||||
|   | |||||||
| @@ -1,15 +1,12 @@ | |||||||
| 00100093  // addi x1, x0, 1     (x1 = 1) | 00000093  // addi x1, x0, 0   - x1 = 0 | ||||||
| 00200113  // addi x2, x0, 2     (x2 = 2) | 00100113  // addi x2, x0, 1   - x2 = 1   | ||||||
| 00300193  // addi x3, x0, 3     (x3 = 3) | 00200193  // addi x3, x0, 2   - x3 = 2 | ||||||
| 00400213  // addi x4, x0, 4     (x4 = 4) | 003081b3  // add  x3, x1, x3  - x3 = 0 + 2 = 2 | ||||||
| 00500293  // addi x5, x0, 5     (x5 = 5) | 00420233  // add  x4, x4, x4  - x4 = x4 + x4 (should be 0) | ||||||
| 00600313  // addi x6, x0, 6     (x6 = 6) | 00228463  // beq  x5, x2, 8   - branch if x5 == x2 (should not take) | ||||||
| 00700393  // addi x7, x0, 7     (x7 = 7) | 00400463  // beq  x0, x4, 8   - branch if 0 == 0 (should take) | ||||||
| 00800413  // addi x8, x0, 8     (x8 = 8) | 00a00513  // addi x10, x0, 10 - x10 = 10 (should be skipped) | ||||||
| 00900493  // addi x9, x0, 9     (x9 = 9) | fff00513  // addi x10, x0, -1 - x10 = -1 (should execute) | ||||||
| 00510233  // add  x4, x2, x5    (x4 = 2+3=5) | 00000013  // nop | ||||||
| 00620333  // add  x6, x4, x6    (x6 = 5+6=11) | 00000013  // nop | ||||||
| 007303b3  // add  x7, x6, x7    (x7 = 11+7=18) | 00000013  // nop | ||||||
| 00840433  // add  x8, x8, x8    (x8 = 8+8=16) |  | ||||||
| 009484b3  // add  x9, x9, x9    (x9 = 9+9=18) |  | ||||||
| 0000006f  // jal x0, 0          (infinite loop) |  | ||||||
|   | |||||||
							
								
								
									
										64
									
								
								chapter5/program0.1.hex
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								chapter5/program0.1.hex
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,64 @@ | |||||||
|  | 00000093  // addi x1, x0, 0      | x1 = 0 | ||||||
|  | 00100113  // addi x2, x0, 1      | x2 = 1 | ||||||
|  | 002081B3  // add x3, x1, x2      | x3 = x1 + x2 = 1 | ||||||
|  | 00400293  // addi x5, x0, 4      | x5 = 4 (memory address) | ||||||
|  | 0051A023  // sw x5, 0(x3)        | Store x5 at address x3 (1) | ||||||
|  | 0001A303  // lw x6, 0(x3)        | Load from address x3 to x6 | ||||||
|  | 00600393  // addi x7, x0, 6      | x7 = 6 | ||||||
|  | 40738433  // sub x8, x7, x7      | x8 = x7 - x7 = 0 | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
|  | 00000013  // nop | ||||||
							
								
								
									
										1318
									
								
								chapter5/risc_tb
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										1318
									
								
								chapter5/risc_tb
									
									
									
									
									
										Executable file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1815
									
								
								chapter5/riscv
									
									
									
									
									
								
							
							
						
						
									
										1815
									
								
								chapter5/riscv
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Reference in New Issue
	
	Block a user