RISC-V CORE
This commit is contained in:
@@ -11,7 +11,16 @@ module RISCcore2 (
|
||||
initial begin
|
||||
$readmemh("program.hex", imem);
|
||||
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
|
||||
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};
|
||||
|
||||
// Register file
|
||||
reg [31:0] rf [0:31];
|
||||
|
||||
// Initialize register file (x0 always zero)
|
||||
// Initialize register file (x0 always zero)
|
||||
integer i;
|
||||
initial begin
|
||||
for (i = 0; i < 32; i = i + 1) begin
|
||||
@@ -109,7 +116,58 @@ module RISCcore2 (
|
||||
|
||||
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
|
||||
|
||||
//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 :
|
||||
@@ -124,7 +182,8 @@ module RISCcore2 (
|
||||
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 = (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) :
|
||||
(isSLT) ? slt_rslt :
|
||||
(isSLTU) ? sltu_rslt :
|
||||
@@ -145,13 +204,13 @@ module RISCcore2 (
|
||||
(isSLTIU) ? (sltiu_rslt) :
|
||||
(isLUI) ? ({Iimm[31:12], 12'b0}) :
|
||||
(isAUIPC) ? (pc + Iimm) :
|
||||
(isJAL) ? (pc + 32'd4) :
|
||||
(isJALR) ? (pc + 32'd4) :
|
||||
(isJAL || isJALR) ? (pc + 32'd4) :
|
||||
(isSRA) ? (sra_rslt[31:0]) :
|
||||
(isSRAI) ? (srai_rslt[31:0]) :
|
||||
(isSRAI) ? (srai_rslt[31:0]) :
|
||||
(is_load) ? (load_data) : //For register writeback
|
||||
32'b0;
|
||||
|
||||
// Branch condition logic
|
||||
|
||||
wire signed [31:0] signed_rs1 = rs1_val;
|
||||
wire signed [31:0] signed_rs2 = rs2_val;
|
||||
|
||||
@@ -164,14 +223,42 @@ module RISCcore2 (
|
||||
isBGEU ? (rs1_val >= rs2_val) :
|
||||
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
|
||||
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;
|
||||
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);
|
||||
wire [31:0] writeback_data = alu_result;
|
||||
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
|
||||
@@ -183,14 +270,14 @@ module RISCcore2 (
|
||||
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
|
||||
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
|
||||
// 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",
|
||||
@@ -200,5 +287,12 @@ module RISCcore2 (
|
||||
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
|
||||
|
Reference in New Issue
Block a user