bugfix
This commit is contained in:
122
chapter5/RISCcore2.v
Normal file
122
chapter5/RISCcore2.v
Normal file
@@ -0,0 +1,122 @@
|
||||
module RISCcore2 (
|
||||
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 = imem[pc[31:2]]; // Word-aligned access
|
||||
|
||||
// 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
|
||||
reg [31:0] rf [0:31];
|
||||
|
||||
// Initialize register file (x0 always zero)
|
||||
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 = (opcode == 7'b1100011) && (funct3 == 3'b000);
|
||||
wire isBNE = (opcode == 7'b1100011) && (funct3 == 3'b001);
|
||||
wire isBLT = (opcode == 7'b1100011) && (funct3 == 3'b100);
|
||||
wire isBGE = (opcode == 7'b1100011) && (funct3 == 3'b101);
|
||||
wire isBLTU = (opcode == 7'b1100011) && (funct3 == 3'b110);
|
||||
wire isBGEU = (opcode == 7'b1100011) && (funct3 == 3'b111);
|
||||
|
||||
// ALU operations
|
||||
wire [31:0] alu_src2 = isADDI ? Iimm : rs2_val;
|
||||
wire [31:0] alu_result = (isADDI || isADD) ? (rs1_val + alu_src2) : 32'b0;
|
||||
|
||||
// Branch condition logic
|
||||
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;
|
||||
assign next_pc = branch_taken ? branch_target : next_pc_base;
|
||||
|
||||
// Register write back
|
||||
wire rf_write_enable = (rd != 0) && (isADDI || isADD);
|
||||
wire [31:0] writeback_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;
|
||||
$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
|
||||
|
||||
endmodule
|
Reference in New Issue
Block a user