From 0c7aa94b39ab847c83df9e2b0b5a6db5469ebba6 Mon Sep 17 00:00:00 2001 From: GameBoyAdvSP <90002537+Meowcaroni@users.noreply.github.com> Date: Fri, 7 Nov 2025 18:29:14 -0500 Subject: [PATCH 01/20] Update fetch.sv --- rtl/cpu/core/fetch.sv | 1 + 1 file changed, 1 insertion(+) diff --git a/rtl/cpu/core/fetch.sv b/rtl/cpu/core/fetch.sv index e69de29..2070b65 100644 --- a/rtl/cpu/core/fetch.sv +++ b/rtl/cpu/core/fetch.sv @@ -0,0 +1 @@ +// Test \ No newline at end of file From fcc254a6734d3991d107b11942628292a1f874d4 Mon Sep 17 00:00:00 2001 From: Adrian Date: Thu, 5 Feb 2026 11:55:20 -0500 Subject: [PATCH 02/20] feat For Execute, 32 x 32 unsigned restoring iterative divider. --- rtl/cpu/core/division.sv | 147 +++++++++++++++++++++++++++++++++++++++ rtl/cpu/core/execute.sv | 59 ++++++++++++++++ 2 files changed, 206 insertions(+) create mode 100644 rtl/cpu/core/division.sv diff --git a/rtl/cpu/core/division.sv b/rtl/cpu/core/division.sv new file mode 100644 index 0000000..4ef9a73 --- /dev/null +++ b/rtl/cpu/core/division.sv @@ -0,0 +1,147 @@ +`timescale 1ns / 1ps + +// Restoring division, divisor initially left-shifted by 32, quotient built MSB→LSB, divisor shifted right each iteration." +// refactor and clarify intent, only working version is 7/2 unsigned + +module division +import rv32_pkg::*; +( + input logic clk, + input logic rst, + input logic Division_START, // Start Division + input logic [31:0] dividend, // numerator + input logic [31:0] divisor, // denominator + output logic [63:0] remainder, // result + output logic Division_DONE // done flag + ); + + logic [31:0] dividend_reg; // internal registers driven by inputs + logic signed [63:0] divisor_reg; + logic signed [63:0] remainder_reg; + logic [31:0] quotient_reg; + logic [5:0] counter; + logic Division_DONE_reg; + + + + enum {IDLE,STALL,DONE} current_state, next_state; // Division FSM states 0 or 1 + + + always_ff @(posedge clk) begin // Division Stall FSM + if(rst==1'b0) begin + current_state <= IDLE; + end else begin + current_state <= next_state; + end + + $display("Current State is: %0s",current_state,); + $display("next State is: %0s",next_state,); + $display("Division_START : %0b",Division_START,); + $display("remainder : %0d",remainder_reg,); + $display("divisor : %0d",divisor_reg,); + end + + always_comb begin // Combinational part of state FSM + next_state = current_state; + + unique case(current_state) + IDLE: next_state = (Division_START) ? STALL : IDLE; // When Division_start gets asserted by mux, go to STALL + STALL: next_state = (Division_DONE_reg) ? DONE : STALL; // When Division circuit is done on last clk edge, it will assert Division_DONE 1 to indicate DONE STATE + DONE: next_state = IDLE; + default: next_state = current_state; + endcase + + end + + + + + enum {GREATER_EQUAL_THAN_ZERO,LESS_THAN_ZERO} Test_remainder_flag; // Flags used for test comparison case + + logic signed [63:0] remainder_test_comparison; // Test combinational logic that will be used for testing. + logic [63:0] remainder_test_mux; + logic [63:0] divisor_comb; + logic [31:0] quotient_comb; // Comnbinational logic that will b driven by always_comb case and then latched on in sequential always_ff + + assign remainder_test_comparison = remainder_reg - divisor_reg; // Combinational Test remainder case + + assign Test_remainder_flag = (remainder_test_comparison[63]) ? LESS_THAN_ZERO : GREATER_EQUAL_THAN_ZERO; // Will assign a flag if Remainder >= 0 or remainder <0 + + + always_comb begin // This always combinational block will assign the sequential remainder register that is clocked + + + case(Test_remainder_flag) // Comparison case case to see if test remainder is less than zero or equal to zero + GREATER_EQUAL_THAN_ZERO: begin + remainder_test_mux = remainder_test_comparison; // If Remainder >= zero, assign remainder_reg(clocked ff) to be Test_remainder_reg + quotient_comb = (quotient_reg << 1) | 1'b1; // shift quotient_reg left and set LSB to 1'b1 + divisor_comb = divisor_reg >> 1; + end + LESS_THAN_ZERO: begin + quotient_comb = (quotient_reg << 1) | 1'b0; // if Remainder <0, shift quotient register left and set LSB to 1'b0 + remainder_test_mux = remainder_reg; + divisor_comb = divisor_reg >> 1; + end + default: begin + quotient_comb = (quotient_reg << 1) | 1'b0; + remainder_test_mux = remainder_reg; + divisor_comb = divisor_reg >> 1; + + end + endcase + + end + + + always_ff @(posedge clk) begin + if(rst == 1'b0) begin + dividend_reg <= 32'd0; + divisor_reg <= 64'd0; + remainder_reg <= 64'd0; + quotient_reg <= 32'd0; + Division_DONE_reg <= 1'b0; + counter <= 6'd0; + + end else begin + case(current_state) + IDLE: begin + dividend_reg <= dividend; // dividend_reg will latch on to dividend input + divisor_reg <= divisor << 32; // Divisor_reg will latch on to divisor input + remainder_reg <= {32'd0,dividend}; // remainder_reg will latch on to remainder input + Division_DONE_reg <= 1'b0; + counter <= 6'd0; + quotient_reg <= 32'd0; + + end + STALL: begin + remainder_reg <= remainder_test_mux; + quotient_reg <= quotient_comb; + divisor_reg <= divisor_comb; + counter <= counter + 1'b1; + $display("result : %0",remainder_reg); + $display("quotient : %0d",quotient_reg); + $display("counter : %0d",counter); + $display("denominator : %0d",divisor_reg); + + if(counter == 6'd32) + Division_DONE_reg <= 1'b1; + + end + DONE: begin + Division_DONE_reg <= 1'b0; + + end + endcase + + end + + end + + + assign remainder = remainder_reg; + assign Division_DONE = Division_DONE_reg; + + + + +endmodule diff --git a/rtl/cpu/core/execute.sv b/rtl/cpu/core/execute.sv index e69de29..d97d392 100644 --- a/rtl/cpu/core/execute.sv +++ b/rtl/cpu/core/execute.sv @@ -0,0 +1,59 @@ +`timescale 1ns / 1ps + +/* Assumptions: + +1) All immediates are sign-extended, no zero extension AT ALL unless the ISA specifies it for special instructions +2) No overflow detection at the hardware level, we have to check at the software level +3) No integer computational instructions cause arithmetic exceptions, No overflow, underflow, carryout, or trap ever +4) unsigned instructions still get signed extended and instructions like SLTU will compare raw bit pattern, so SLTU -1 > 32 is TRUE for example, and not interpret the sign bit unlike SLT which is signed +5) divide (div), divide unsigned (divu), remainder (rem), and remainder unsigned (remu), see pg 390 +6) multiply (mul), multiply high(mulh), multiply high unsigned(mulhu) multiply high signed-unsigned(mulhsu) are supported 384 + + + +*/ + +module execute +import rv32_pkg::*; +( + input logic clk, // Main clk input + input logic rst, // Active-low asynchronous reset + input logic ctrl_i, // Control signals to execute + input logic [DATA_WIDTH-1:0] op_a_i, // Register A operand (data) from RF + input logic [DATA_WIDTH-1:0] op_b_i, // Register B operand (data) from RF + input logic [3:0] ALU_select, // Is driven by decoder Funct 3 & 7 bundled together + output logic [DATA_WIDTH-1:0] alu_res_o, // ALU result from procesing operands + output logic [DATA_WIDTH-1:0] ALU_OUTPUT, + output logic branch_taken_o, // Control signal for whether branch should be taken + output logic branch_target_o // Address for branch to redirect program counter +); + + + + //TODO 1: Need ALU operation control input for combinational case statement + //TODO 2: signed Overflow detection, we need to extend operands to 32 bits, and do overflow = Carryin ^ Carryout; All of sum MSB + //TODO 3: sign extension or zero padding + //TODO 4: Figure out signed vs unsigned addition subtration etc + //TODO 5: Division + //TODO 6: Stall FSM for division, and figure out division unit + //TODO 7: data forwarding + //TODO 8: invariarnts + //TODO 9: Divides could take up to 32 cycles with naive shift right divider + + + always_comb begin // ALU selection OPCODE + ALU_OUTPUT = 32'b0; // Defaults + + case(ALU_select) + FUNCT3_ADD: ALU_OUTPUT = op_a_i + op_b_i; // I need to know if to sign extend or not to detect unsigned/signed overflow + FUNCT3_SUB: ALU_OUTPUT = op_a_i - op_b_i; + + + endcase + + + end + + + +endmodule From 0c9dbc918c828672d636a8ed804552317f54fd23 Mon Sep 17 00:00:00 2001 From: Gavin Wiese Date: Mon, 9 Feb 2026 09:31:44 -0500 Subject: [PATCH 03/20] Update clint.sv --- rtl/irq/clint.sv | 58 +++++++++++++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 20 deletions(-) diff --git a/rtl/irq/clint.sv b/rtl/irq/clint.sv index 4e55cf2..0665034 100644 --- a/rtl/irq/clint.sv +++ b/rtl/irq/clint.sv @@ -1,25 +1,43 @@ module clint( input logic clk_i, input logic rst_ni, - output logic Timer_irq_o, - input logic [63:0] user_time, // - output logic [63:0] mtime_o, // - output logic msip -); + // write ports + input logic msip_we, + input logic msip_wdata, + + input logic mtimecmp_we, + input logic [63:0] mtimecmp_wdata, + + // outputs + output logic [63:0] mtime_o, + output logic timer_irq_o, + output logic soft_irq_o + ); + + //---------------------------------------- + // Internal Registers + //---------------------------------------- logic [63:0] mtimecmp; - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - mtime_o <= 16'd0; - mtimecmp <= 16'd0; - Timer_irq_o <= 1'b0; - msip <= 1'b0; - end else begin - mtime_o <= mtime_o + 1; - mtimecmp <= user_time; - Timer_irq_o <= (mtime_o >= mtimecmp); - msip <= Timer_irq_o; - end - end + logic msip; + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + mtime_o <= 64'd0; + mtimecmp <= 64'd0; + msip <= 1'b0; + timer_irq_o <= 1'b0; + soft_irq_o <= 1'b0; + end else begin + //free running timer + mtime_o <= mtime_o + 1; + + // register writes + if (mtimecmp_we) mtimecmp <= mtimecmp_wdata; + if (msip_we) msip <= msip_wdata; + + // irq outputs (compare against "next" mtime to avoid 1-cycle lag) + timer_irq_o <= ((mtime_o + 64'd1) >= (mtimecmp_we ? mtimecmp_wdata : mtimecmp)); + soft_irq_o <= (msip_we ? msip_wdata : msip); + end + end endmodule - From 45de86884c298bb5a76e9c14e34280229f28bb7c Mon Sep 17 00:00:00 2001 From: Adrian Date: Tue, 10 Feb 2026 22:55:10 -0500 Subject: [PATCH 04/20] Update to division & execute cleaned up division module, added better comments to describe intent, still needs signed division and zero edge case --- rtl/cpu/core/division.sv | 113 +++++++++++++++++++++++---------------- rtl/cpu/core/execute.sv | 22 +++++--- 2 files changed, 84 insertions(+), 51 deletions(-) diff --git a/rtl/cpu/core/division.sv b/rtl/cpu/core/division.sv index 4ef9a73..c2844b4 100644 --- a/rtl/cpu/core/division.sv +++ b/rtl/cpu/core/division.sv @@ -1,7 +1,7 @@ `timescale 1ns / 1ps // Restoring division, divisor initially left-shifted by 32, quotient built MSB→LSB, divisor shifted right each iteration." -// refactor and clarify intent, only working version is 7/2 unsigned + module division import rv32_pkg::*; @@ -11,8 +11,9 @@ import rv32_pkg::*; input logic Division_START, // Start Division input logic [31:0] dividend, // numerator input logic [31:0] divisor, // denominator - output logic [63:0] remainder, // result - output logic Division_DONE // done flag + output logic [63:0] remainder, // Mod + output logic Division_DONE, // done flag + output logic [31:0] quotient // result ); logic [31:0] dividend_reg; // internal registers driven by inputs @@ -24,30 +25,24 @@ import rv32_pkg::*; - enum {IDLE,STALL,DONE} current_state, next_state; // Division FSM states 0 or 1 + enum {IDLE,STALL} current_state, next_state; // Division FSM states 0 or 1 always_ff @(posedge clk) begin // Division Stall FSM - if(rst==1'b0) begin + if(rst==1'b0) begin // Active low reset current_state <= IDLE; end else begin current_state <= next_state; end - - $display("Current State is: %0s",current_state,); - $display("next State is: %0s",next_state,); - $display("Division_START : %0b",Division_START,); - $display("remainder : %0d",remainder_reg,); - $display("divisor : %0d",divisor_reg,); + end always_comb begin // Combinational part of state FSM next_state = current_state; unique case(current_state) - IDLE: next_state = (Division_START) ? STALL : IDLE; // When Division_start gets asserted by mux, go to STALL - STALL: next_state = (Division_DONE_reg) ? DONE : STALL; // When Division circuit is done on last clk edge, it will assert Division_DONE 1 to indicate DONE STATE - DONE: next_state = IDLE; + IDLE:next_state = (Division_START) ? STALL : IDLE; // When Division_start gets asserted by mux, go to STALL + STALL: next_state = (Division_DONE_reg) ? IDLE : STALL; // When Division circuit is done on last clk edge, it will assert Division_DONE 1 to indicate DONE STATE default: next_state = current_state; endcase @@ -58,34 +53,40 @@ import rv32_pkg::*; enum {GREATER_EQUAL_THAN_ZERO,LESS_THAN_ZERO} Test_remainder_flag; // Flags used for test comparison case - logic signed [63:0] remainder_test_comparison; // Test combinational logic that will be used for testing. + // Test combinational logic interface that will be used for testing. + logic signed [63:0] remainder_test_comparison; logic [63:0] remainder_test_mux; logic [63:0] divisor_comb; - logic [31:0] quotient_comb; // Comnbinational logic that will b driven by always_comb case and then latched on in sequential always_ff + logic [31:0] quotient_comb; - assign remainder_test_comparison = remainder_reg - divisor_reg; // Combinational Test remainder case + assign remainder_test_comparison = remainder_reg - divisor_reg; // will subtract remainder from divisor - assign Test_remainder_flag = (remainder_test_comparison[63]) ? LESS_THAN_ZERO : GREATER_EQUAL_THAN_ZERO; // Will assign a flag if Remainder >= 0 or remainder <0 + assign Test_remainder_flag = (remainder_test_comparison[63]) ? LESS_THAN_ZERO : GREATER_EQUAL_THAN_ZERO; // will assign a flag based on the remainder - always_comb begin // This always combinational block will assign the sequential remainder register that is clocked - + always_comb begin + // Restoring division step: + // Try subtracting divisor from remainder. + // If result >= 0 keep subtraction and append 1 to quotient. + // If result < 0 restore old remainder and append 0 to quotient. + // Then shift divisor for next bit position. + - case(Test_remainder_flag) // Comparison case case to see if test remainder is less than zero or equal to zero + case(Test_remainder_flag) // Comparison case case GREATER_EQUAL_THAN_ZERO: begin - remainder_test_mux = remainder_test_comparison; // If Remainder >= zero, assign remainder_reg(clocked ff) to be Test_remainder_reg - quotient_comb = (quotient_reg << 1) | 1'b1; // shift quotient_reg left and set LSB to 1'b1 - divisor_comb = divisor_reg >> 1; + remainder_test_mux = remainder_test_comparison; // Accept trial remainder (subtract succeeded) + quotient_comb = (quotient_reg << 1) | 1'b1; // shift left, add quotient bit = 1 + divisor_comb = divisor_reg >> 1; // next alignment (shift divisor) we are basically doing long division and comparing bit positions to see if they match end LESS_THAN_ZERO: begin - quotient_comb = (quotient_reg << 1) | 1'b0; // if Remainder <0, shift quotient register left and set LSB to 1'b0 - remainder_test_mux = remainder_reg; - divisor_comb = divisor_reg >> 1; + quotient_comb = (quotient_reg << 1) | 1'b0; // Restore remainder (subtract failed) + remainder_test_mux = remainder_reg; // Shift left, add quotient bit = 0 + divisor_comb = divisor_reg >> 1; // Next alignment (shift divisor) end - default: begin + default: begin // default should never happen but keeps tools happy quotient_comb = (quotient_reg << 1) | 1'b0; - remainder_test_mux = remainder_reg; - divisor_comb = divisor_reg >> 1; + remainder_test_mux = remainder_reg; // Restore remainder (subtract failed) + divisor_comb = divisor_reg >> 1;// next alignment (shift divisor) we are basically doing long division and comparing bit positions to see if they match end endcase @@ -101,44 +102,66 @@ import rv32_pkg::*; quotient_reg <= 32'd0; Division_DONE_reg <= 1'b0; counter <= 6'd0; + end else begin case(current_state) - IDLE: begin + IDLE: begin + dividend_reg <= dividend; // dividend_reg will latch on to dividend input - divisor_reg <= divisor << 32; // Divisor_reg will latch on to divisor input - remainder_reg <= {32'd0,dividend}; // remainder_reg will latch on to remainder input + divisor_reg <= divisor << 32; // Divisor is aligned to the top 32 bits, divisor_reg is 64 Bit reg + remainder_reg <= {32'd0,dividend}; // remainder_reg will be initialized with numerator Division_DONE_reg <= 1'b0; counter <= 6'd0; - quotient_reg <= 32'd0; - + quotient_reg <= 32'd0; + end STALL: begin remainder_reg <= remainder_test_mux; quotient_reg <= quotient_comb; divisor_reg <= divisor_comb; counter <= counter + 1'b1; - $display("result : %0",remainder_reg); - $display("quotient : %0d",quotient_reg); - $display("counter : %0d",counter); - $display("denominator : %0d",divisor_reg); - if(counter == 6'd32) + if(counter == 6'd32) begin Division_DONE_reg <= 1'b1; + + end else begin + + Division_DONE_reg <= 1'b0; + + end + end - DONE: begin - Division_DONE_reg <= 1'b0; - - end + endcase end end - + always_ff @(posedge clk) begin + + if(counter == 32'd33) begin + $display("Quotient: %0d",quotient); + $display("Remainder: %0d",remainder); + $display("Counter: %0d",counter); + $display("Done Signal: %0d", Division_DONE); + $display("Current State: %s", current_state); + $display("next State: %s", next_state); + $display("Division Start flag: %d", Division_START); + $display("\n"); + end + + + + + + end + + assign remainder = remainder_reg; + assign quotient = quotient_reg; assign Division_DONE = Division_DONE_reg; diff --git a/rtl/cpu/core/execute.sv b/rtl/cpu/core/execute.sv index d97d392..e1fb1f9 100644 --- a/rtl/cpu/core/execute.sv +++ b/rtl/cpu/core/execute.sv @@ -20,8 +20,8 @@ import rv32_pkg::*; input logic rst, // Active-low asynchronous reset input logic ctrl_i, // Control signals to execute input logic [DATA_WIDTH-1:0] op_a_i, // Register A operand (data) from RF - input logic [DATA_WIDTH-1:0] op_b_i, // Register B operand (data) from RF - input logic [3:0] ALU_select, // Is driven by decoder Funct 3 & 7 bundled together + input logic [DATA_WIDTH-1:0] op_b_i, // Register B operand (data) or sign extended immediate 32'b values + input logic [4:0] ALU_OP, output logic [DATA_WIDTH-1:0] alu_res_o, // ALU result from procesing operands output logic [DATA_WIDTH-1:0] ALU_OUTPUT, output logic branch_taken_o, // Control signal for whether branch should be taken @@ -43,12 +43,22 @@ import rv32_pkg::*; always_comb begin // ALU selection OPCODE ALU_OUTPUT = 32'b0; // Defaults + + case(ALU_OP) - case(ALU_select) - FUNCT3_ADD: ALU_OUTPUT = op_a_i + op_b_i; // I need to know if to sign extend or not to detect unsigned/signed overflow + FUNCT3_ADD: ALU_OUTPUT = op_a_i + op_b_i; FUNCT3_SUB: ALU_OUTPUT = op_a_i - op_b_i; - - + FUNCT3_SLL: ALU_OUTPUT = op_a_i << op_b_i; + FUNCT3_SLT: ALU_OUTPUT = ($signed(op_a_i) < $signed(op_b_i)) ? 32'd1 : 32'd0; // if A < b return 1 else 0 SIGNED + FUNCT3_SLTU: ALU_OUTPUT = (op_a_i < op_b_i) ? 32'd1 : 32'd0; // if A < b return 1 else 0 UNSIGNED + FUNCT3_XOR: ALU_OUTPUT = op_a_i ^ op_b_i; // will XOR every individual bit + FUNCT3_SRL: ALU_OUTPUT = op_a_i >> op_b_i; + FUNCT3_OR: ALU_OUTPUT = op_a_i | op_b_i; + FUNCT3_AND: ALU_OUTPUT = op_a_i & op_b_i; + FUNCT7_SRA: ALU_OUTPUT = op_a_i >>> op_b_i; + // add mul signed and unsigned & signed unsigned divider + + endcase From ce5bf32f767efa768f4262b022aa10f5fa1f45dd Mon Sep 17 00:00:00 2001 From: Gavin Wiese Date: Thu, 12 Feb 2026 20:48:12 -0500 Subject: [PATCH 05/20] Update plic.sv --- rtl/irq/plic.sv | 114 ++++++++++++++++++++---------------------------- 1 file changed, 47 insertions(+), 67 deletions(-) diff --git a/rtl/irq/plic.sv b/rtl/irq/plic.sv index e5be350..af74cb5 100644 --- a/rtl/irq/plic.sv +++ b/rtl/irq/plic.sv @@ -1,21 +1,20 @@ module plic #( - parameter NSOURCES = 32, - parameter PRIO_WIDTH = 3 + parameter NSOURCES = 32, + parameter PRIO_WIDTH = 3, + parameter SRC_ID_WIDTH = 5 )( input logic clk_i, input logic rst_ni, input logic [NSOURCES-1:0] src_i, // External interrupt sources - // Simple register interface (bus-free) input logic [NSOURCES*PRIO_WIDTH-1:0] priority_wdata, input logic priority_we, input logic [NSOURCES-1:0] enable_wdata, input logic enable_we, - input logic [$clog2(NSOURCES)-1:0] claim_wdata, input logic claim_we, output logic ext_irq_o, - output logic [$clog2(NSOURCES)-1:0] claim_o + output logic [SRC_ID_WIDTH-1:0] claim_o ); // ------------------------- @@ -23,83 +22,64 @@ module plic #( // ------------------------- logic [NSOURCES*PRIO_WIDTH-1:0] priorities; // Interrupt priorities logic [NSOURCES-1:0] enable; // Enable bits for sources - logic [$clog2(NSOURCES)-1:0] claim; // Claim register - logic [NSOURCES-1:0] pending; // Pending interrupts - logic [$clog2(NSOURCES)-1:0] highestPriorIndex; + logic [SRC_ID_WIDTH-1:0] claim; // Claim register + logic [NSOURCES-1:0] pending; // Pending interrupts + logic [SRC_ID_WIDTH-1:0] highestPriorIndex; logic [PRIO_WIDTH-1:0] tempHighestValue; logic activeClaim; - assign claim_o = claim; + assign claim_o = claim; + assign ext_irq_o = (tempHighestValue != 0); // ------------------------- - // Active low reset + // Priority selector // ------------------------- - always_ff @(negedge rst_ni) begin - if (!rst_ni) begin - priorities <= 0; - enable <= 0; - claim <= 0; - pending <= 0; - highestPriorIndex <= 0; - tempHighestValue <= 0; - activeClaim <= 0; - end - end + always_comb begin + tempHighestValue = 0; + highestPriorIndex = 0; - // ------------------------- - // Simple register writes - // ------------------------- - always_ff @(posedge clk_i) begin - if (priority_we) begin - priorities <= priority_wdata; - end - if (enable_we) begin - enable <= enable_wdata; - end - if (claim_we) begin - activeClaim <= 0; // Claim complete - end - end - - // ------------------------- - // Pending interrupt latching - // ------------------------- - always_ff @(posedge clk_i) begin for (int i = 0; i < NSOURCES; i++) begin - pending[i] <= pending[i] | (src_i[i] & enable[i]); + if (pending[i] && + priorities[i*PRIO_WIDTH +: PRIO_WIDTH] > tempHighestValue) begin + tempHighestValue = priorities[i*PRIO_WIDTH +: PRIO_WIDTH]; + highestPriorIndex = i[SRC_ID_WIDTH-1:0]; + end end end // ------------------------- - // Priority selector + // Sequential logic // ------------------------- - always_ff @(posedge clk_i) begin - tempHighestValue <= 0; - highestPriorIndex <= 0; - for (int i = 0; i < NSOURCES; i++) begin - if (pending[i] && priorities[i*PRIO_WIDTH +: PRIO_WIDTH] > tempHighestValue) begin - tempHighestValue <= priorities[i*PRIO_WIDTH +: PRIO_WIDTH]; - highestPriorIndex <= i[$clog2(NSOURCES)-1:0]; + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + priorities <= 0; + enable <= 0; + claim <= 0; + pending <= 0; + activeClaim <= 0; + end else begin + + // Register writes + if (priority_we) + priorities <= priority_wdata; + + if (enable_we) + enable <= enable_wdata; + + if (claim_we) + activeClaim <= 0; // Claim complete + + // Pending interrupt latching + for (int i = 0; i < NSOURCES; i++) begin + pending[i] <= pending[i] | (src_i[i] & enable[i]); end - end - end - // ------------------------- - // Claim logic - // ------------------------- - always_ff @(posedge clk_i) begin - if (!activeClaim && tempHighestValue != 0) begin - claim <= highestPriorIndex; - pending[highestPriorIndex] <= 0; - activeClaim <= 1; + // Claim logic + if (!activeClaim && tempHighestValue != 0) begin + claim <= highestPriorIndex; + pending[highestPriorIndex] <= 0; + activeClaim <= 1; + end end end - - // ------------------------- - // IRQ output - // ------------------------- - always_ff @(posedge clk_i) begin - ext_irq_o <= activeClaim; - end - endmodule From 876e8f0ec45fa256f6d4dc8d116e4aa37626ab5f Mon Sep 17 00:00:00 2001 From: Nidal Rahman Date: Fri, 13 Feb 2026 13:18:27 -0500 Subject: [PATCH 06/20] AXI instruction cache file progress so far, beginning logic --- rtl/bus/axi/axi_dcache_port.sv | 3 +- rtl/bus/axi/axi_icache_port.sv | 54 ++++++++++++++++++++++++++++++---- rtl/bus/interconnect_pkg.sv | 21 +++++++++++++ 3 files changed, 72 insertions(+), 6 deletions(-) diff --git a/rtl/bus/axi/axi_dcache_port.sv b/rtl/bus/axi/axi_dcache_port.sv index 2859d17..9ab8c90 100644 --- a/rtl/bus/axi/axi_dcache_port.sv +++ b/rtl/bus/axi/axi_dcache_port.sv @@ -1,6 +1,6 @@ module axi_dcache_port #( // TODO: Parameter setups - parameter + parameter unsigned )( // TODO: Port set up ports @@ -9,6 +9,7 @@ module axi_dcache_port #( input logic clk_i, input logic rst_ni + ); endmodule diff --git a/rtl/bus/axi/axi_icache_port.sv b/rtl/bus/axi/axi_icache_port.sv index 1f92419..09c81da 100644 --- a/rtl/bus/axi/axi_icache_port.sv +++ b/rtl/bus/axi/axi_icache_port.sv @@ -1,13 +1,57 @@ +import interconnect_pkg; + module axi_icache_port #( - // TODO: Parameter setups - parameter + // System AXI Parameters + parameter int unsigned AXI_ADDR_WIDTH = 32, + parameter int unsigned AXI_DATA_WIDTH = 64, + parameter int unsigned AXI_ID_WIDTH = 4, + parameter int unsigned AXI_USER_WIDTH = 1, + + + )( - // TODO: Port set up - ports + // TODO: Port set up ports - // TODO: Input logic + // global clock and reset signals input logic clk_i, input logic rst_ni + + // icache valid request and address + input logic ic_req_valid_i, + input logic[AXI_ADDR_WIDTH-1:0] ic_addr_valid_i, + + // icache + + + // axi address read signals + output logic axi_mem_ar_o, + output logic axi_ar_valid_o, + input logic axi_ar_ready_i, + + // axi read data signals + input logic axi_mem_r_i, + input logic axi_r_ready_i, + input logic axi_r_valid_i, + + + typedef enum [2:0] { + IDLE; // Do nothing, wait for i$ to miss + AR_SEND; // cache requested a line, put it on araddr and set ARVALID to high + R_COLLECT; // collect the requested data from the crossbar and send it to cache + + } icache_port_state_e; + + icache_port_state_e current_state, next_state; + + // state transition + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + current_state <= IDLE; + end + else begin + current_state <= next_state; + end + end ); diff --git a/rtl/bus/interconnect_pkg.sv b/rtl/bus/interconnect_pkg.sv index e69de29..71f8bce 100644 --- a/rtl/bus/interconnect_pkg.sv +++ b/rtl/bus/interconnect_pkg.sv @@ -0,0 +1,21 @@ +// + + +package interconnect_pkg; + +// AXI Data Widths +parameter int unsigned AXI_ADDR_WIDTH = 32; +parameter int unsigned AXI_DATA_WIDTH = 64; +parameter int unsigned AXI_ID_WIDTH = 4; +parameter int unsigned AXI_USER_WIDTH = 1; + +parameter int unsigned AXI_STRB_WIDTH = AXI_DATA_WIDTH/8; + +// Master IDs (TBD) + +// Address Map (TBD) + +// Cache Line + + +endpackage \ No newline at end of file From fbf2643fce8df963afb8603c3f327772f9874020 Mon Sep 17 00:00:00 2001 From: Nidal Rahman Date: Fri, 13 Feb 2026 13:20:07 -0500 Subject: [PATCH 07/20] Create gamingCPU.editorconfig --- gamingCPU.editorconfig | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 gamingCPU.editorconfig diff --git a/gamingCPU.editorconfig b/gamingCPU.editorconfig new file mode 100644 index 0000000..12a5341 --- /dev/null +++ b/gamingCPU.editorconfig @@ -0,0 +1,17 @@ +root = true +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true +[*.{sv,svh,v,vh}] +indent_style = space +indent_size = 2 +max_line_length = 100 +[*.{c,h}] +indent_style = space +indent_size = 2 +max_line_length = 100 +[*.{yaml,yml,dts,dtsi,md}] +indent_style = space +indent_size = 2 \ No newline at end of file From 53632d6336f58677c74b6d1f476be84133de0799 Mon Sep 17 00:00:00 2001 From: XyzalAxel <145172488+XyzalAxel@users.noreply.github.com> Date: Fri, 13 Feb 2026 18:45:16 -0500 Subject: [PATCH 08/20] updated performance targets of axi_crossbar.md --- docs/ip-briefs/axi_crossbar.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/ip-briefs/axi_crossbar.md b/docs/ip-briefs/axi_crossbar.md index 559da11..9fcf462 100644 --- a/docs/ip-briefs/axi_crossbar.md +++ b/docs/ip-briefs/axi_crossbar.md @@ -35,14 +35,14 @@ Central AXI4 interconnect between managers and subordinates. Performs address de ### Performance Targets -- **Clock:** **TBD** MHz (ASIC), **TBD** MHz (FPGA) +- **Clock:** 100 MHz (FPGA) - **Throughput:** **1 beat/cycle** once granted (R & W) - **Latency (xbar-only):** addr → grant ≤ 2 cycles; read addr → first data ≤ 3 cycles beyond subordinate; last-W → B ≤ 3 cycles - **Arbitration:** **Round-robin;** starvation ≤ **N_M grants** -- **Bursts:** **INCR**, max len **TBD** -- **Outstanding:** per-manager **TBD R/TBD W**; backpressure only -- **CDC:** each crossing adds **+TBD cycles;** throughput unchanged -- **Reset:** READY may assert within ≤ **TBD cycles** after `rst_ni` deassert +- **Bursts:** **INCR**, max len 16 +- **Outstanding:** per-manager 2 R/2 W; backpressure only +- **CDC:** each crossing adds 3-5 cycles; throughput unchanged +- **Reset:** READY may assert within ≤ 2 cycles after `rst_ni` deassert --- ### Behavior & Timing From 62c8f1f0e149bb5313a2bfaf91ba94096fc6e74b Mon Sep 17 00:00:00 2001 From: Adrian Date: Fri, 13 Feb 2026 18:56:10 -0500 Subject: [PATCH 09/20] Update execute.sv Added MUL and Division instructions --- rtl/cpu/core/execute.sv | 235 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 211 insertions(+), 24 deletions(-) diff --git a/rtl/cpu/core/execute.sv b/rtl/cpu/core/execute.sv index e1fb1f9..84ad3f1 100644 --- a/rtl/cpu/core/execute.sv +++ b/rtl/cpu/core/execute.sv @@ -23,40 +23,227 @@ import rv32_pkg::*; input logic [DATA_WIDTH-1:0] op_b_i, // Register B operand (data) or sign extended immediate 32'b values input logic [4:0] ALU_OP, output logic [DATA_WIDTH-1:0] alu_res_o, // ALU result from procesing operands - output logic [DATA_WIDTH-1:0] ALU_OUTPUT, output logic branch_taken_o, // Control signal for whether branch should be taken - output logic branch_target_o // Address for branch to redirect program counter + output logic state // used for stalling the pipeline when division module enters STALL state + //output logic [DATA_WIDTH-1:0] branch_target_o // Address for branch to redirect program counter deleted because decode will produce branch target in a registered state ); + // TEMP parameters + parameter FUNCT7_MUL = 5'd13; + parameter FUNCT7_MULH = 5'd14; + parameter FUNCT7_MULHSU = 5'd15; + parameter FUNCT_MULHU = 5'd16; + parameter FUNCT_XOR = 5'd17; + parameter FUNCT_BEQ = 5'd18; + parameter FUNCT_BNE = 5'd19; + parameter FUNCT_BLT = 5'd20; + parameter FUNCT_BGE = 5'd21; + parameter FUNCT_BLTU = 5'd22; + parameter FUNCT_BGEU = 5'd23; + parameter FUNCT_DIVU = 5'd24; + parameter FUNCT_REMU = 5'd25; + parameter FUNCT_DIV = 5'd26; + parameter FUNCT_REM = 5'd27; + + logic [DATA_WIDTH*2:0] MULTIPLY_REG; // Used for M instructions + logic [DATA_WIDTH-1:0] ALU_OUTPUT_COMB; - //TODO 1: Need ALU operation control input for combinational case statement - //TODO 2: signed Overflow detection, we need to extend operands to 32 bits, and do overflow = Carryin ^ Carryout; All of sum MSB - //TODO 3: sign extension or zero padding - //TODO 4: Figure out signed vs unsigned addition subtration etc - //TODO 5: Division - //TODO 6: Stall FSM for division, and figure out division unit - //TODO 7: data forwarding - //TODO 8: invariarnts - //TODO 9: Divides could take up to 32 cycles with naive shift right divider - + + always_ff @(posedge clk) begin + if(rst == 1'b0) + alu_res_o <= 32'd0; + else begin + alu_res_o <= ALU_OUTPUT_COMB; + end + + end + + // Division interface + logic Division_START; + logic Division_DONE; + logic [DATA_WIDTH-1:0] divisor; // numberator + logic [DATA_WIDTH-1:0] dividend; // denominator + logic [DATA_WIDTH-1:0] quotient; //result + logic [DATA_WIDTH-1:0] result_fix; // Will decide if quotient should be signed + logic [DATA_WIDTH-1:0] remainder; // mod + logic sign_bit; + logic signed_overflow; + logic state; // used for stalling the pipeline when division module enters STALL state + + division Unit( + .clk(clk), + .rst(rst), + .Division_START(Division_START), + .dividend(dividend), + .divisor(divisor), + .remainder(remainder), + .Division_DONE(Division_DONE), + .quotient(quotient), + .state(state) + ); + + //TODO: for division we have to add the stalling and only latch on to values when they are valid, right now they are always being driven, + // so garbage values are seen throughout the cycles + always_comb begin // ALU selection OPCODE - ALU_OUTPUT = 32'b0; // Defaults + ALU_OUTPUT_COMB = 32'b0; // Defaults + MULTIPLY_REG = 64'b0; + branch_taken_o = 1'b0; + divisor = 32'b0; + dividend = 32'b0; + Division_START = 1'b0; + sign_bit = 1'b0; + result_fix = 32'b0; + signed_overflow = 1'b0; case(ALU_OP) - FUNCT3_ADD: ALU_OUTPUT = op_a_i + op_b_i; - FUNCT3_SUB: ALU_OUTPUT = op_a_i - op_b_i; - FUNCT3_SLL: ALU_OUTPUT = op_a_i << op_b_i; - FUNCT3_SLT: ALU_OUTPUT = ($signed(op_a_i) < $signed(op_b_i)) ? 32'd1 : 32'd0; // if A < b return 1 else 0 SIGNED - FUNCT3_SLTU: ALU_OUTPUT = (op_a_i < op_b_i) ? 32'd1 : 32'd0; // if A < b return 1 else 0 UNSIGNED - FUNCT3_XOR: ALU_OUTPUT = op_a_i ^ op_b_i; // will XOR every individual bit - FUNCT3_SRL: ALU_OUTPUT = op_a_i >> op_b_i; - FUNCT3_OR: ALU_OUTPUT = op_a_i | op_b_i; - FUNCT3_AND: ALU_OUTPUT = op_a_i & op_b_i; - FUNCT7_SRA: ALU_OUTPUT = op_a_i >>> op_b_i; - // add mul signed and unsigned & signed unsigned divider + // Assumption that all Immediate versions of the instructions will be included in op_b_i sign extended already + // For shamt instructions, I need only the raw 5 bit unsigned shamt value, no zero extension or zero padding. see how decoder is interfacing to me + FUNCT3_ADD: ALU_OUTPUT_COMB = op_a_i + op_b_i; + + FUNCT3_SUB: ALU_OUTPUT_COMB = $signed(op_a_i) - $signed(op_b_i); + + FUNCT3_SLL: ALU_OUTPUT_COMB = op_a_i << op_b_i; + + FUNCT3_SLT: ALU_OUTPUT_COMB = ($signed(op_a_i) < $signed(op_b_i)) ? 32'd1 : 32'd0; // if A < b return 1 else 0 SIGNED + + FUNCT3_SLTU: ALU_OUTPUT_COMB = (op_a_i < op_b_i) ? 32'd1 : 32'd0; // if A < b return 1 else 0 UNSIGNED + + FUNCT3_XOR: ALU_OUTPUT_COMB = op_a_i ^ op_b_i; // will XOR every individual bit + + FUNCT3_SRL: ALU_OUTPUT_COMB = op_a_i >> op_b_i; + + FUNCT3_OR: ALU_OUTPUT_COMB = op_a_i | op_b_i; + + FUNCT3_AND: ALU_OUTPUT_COMB = op_a_i & op_b_i; + + FUNCT7_SRA: ALU_OUTPUT_COMB = op_a_i >>> op_b_i; + + FUNCT_XOR: ALU_OUTPUT_COMB = op_a_i ^ op_b_i; + + FUNCT_BEQ: branch_taken_o = ($signed(op_a_i) == $signed(op_b_i)) ? 32'd1 : 32'd0; + + FUNCT_BNE: branch_taken_o = ($signed(op_a_i) != $signed(op_b_i)) ? 32'd1 : 32'd0; + + FUNCT_BLT: branch_taken_o = ($signed(op_a_i) < $signed(op_b_i)) ? 32'd1 : 32'd0; + + FUNCT_BLTU: branch_taken_o = (op_a_i < op_b_i) ? 32'd1 : 32'd0; + + FUNCT_BGE: branch_taken_o = ($signed(op_a_i) >= $signed(op_b_i)) ? 32'd1 : 32'd0; + + FUNCT_BGEU: branch_taken_o = (op_a_i >= op_b_i) ? 32'd1 : 32'd0; + + FUNCT7_MUL: begin // Will return lower XLEN x XLEN bits in ALU_OUTPUT, same for signed/unsigned XLEN + MULTIPLY_REG = op_a_i * op_b_i; + ALU_OUTPUT_COMB = MULTIPLY_REG[31:0]; + end + + FUNCT7_MULH: begin + MULTIPLY_REG = $signed(op_a_i) * $signed(op_b_i); // Will return upper signed(XLEN) x signed(XLEN) bits in ALU_OUTPUT + ALU_OUTPUT_COMB = MULTIPLY_REG[63:32]; + + end + + FUNCT7_MULHSU: begin // Will return Signed(XLEN) x Unsigned(XLEN) upper bits + MULTIPLY_REG = $signed(op_a_i) * (op_b_i); // In the RISC-V spec, rs2 is multiplier, rs1 is multiplicand, im assuming rs1 is op_a_i and op_b_i is multiplicand + ALU_OUTPUT_COMB = MULTIPLY_REG[63:32]; + end + + FUNCT_MULHU: begin // will return return unsigned x unsigned upper XLEN bits + MULTIPLY_REG = op_a_i * op_b_i; + ALU_OUTPUT_COMB = MULTIPLY_REG[63:32]; + + end + + FUNCT_DIVU: begin + dividend = op_a_i; + divisor = op_b_i; + Division_START = (op_b_i != 32'd0) ? 1'b1 : 1'b0; // if no division by zero start division + ALU_OUTPUT_COMB = (op_b_i != 32'd0) ? quotient : 32'hFFFF_FFFF; // zero edge case ALU will output all ones + + end + + FUNCT_REMU: begin + dividend = op_a_i; + divisor = op_b_i; + Division_START = (op_b_i != 32'd0) ? 1'b1 : 1'b0; // if no division by zero start division + ALU_OUTPUT_COMB = (op_b_i != 32'd0) ? remainder : op_a_i; // zero edge case ALU will output dividend + + end + FUNCT_REM: begin + + signed_overflow = (op_a_i == 32'h8000_0000) && (op_b_i == 32'hFFFF_FFFF); // signed overflow will only occur with -1 and -2^31 + + dividend = (op_a_i[31] == 1'b1) ? ~op_a_i + 1'b1 : op_a_i; // convert to unsigned magnitude if negative + + divisor = (op_b_i[31] == 1'b1) ? ~op_b_i + 1'b1 : op_b_i; // convert to unsigned magnitude if negative + + Division_START = (op_b_i != 32'd0 && signed_overflow == 1'b0) ? 1'b1 : 1'b0; // start Division if no signed overflow or division by zero + + sign_bit = op_a_i[31]; // For remiander, the sign follows the dividend only + + result_fix = (sign_bit == 1'b1) ? ~remainder + 1'b1 : remainder; // sign fixing logic that will fix unsigned remainder coming out of divider + + if(op_b_i == 32'd0) begin + + ALU_OUTPUT_COMB = op_a_i; // ALU output stays the dividend if div by 0 + + end else if(signed_overflow) begin + + ALU_OUTPUT_COMB = 32'b0; // ALU will output 32'b0 if signed overflow + + end else begin + + ALU_OUTPUT_COMB = result_fix; // if no signed overflow or div by 0 assign remainder + + end + + end + + FUNCT_DIV: begin + + signed_overflow = (op_a_i == 32'h8000_0000) && (op_b_i == 32'hFFFF_FFFF); // signed overflow will only occur with -1 and -2^31 + + dividend = (op_a_i[31] == 1'b1) ? ~op_a_i + 1'b1 : op_a_i; // convert to unsigned magnitude if negative + + divisor = (op_b_i[31] == 1'b1) ? ~op_b_i + 1'b1 : op_b_i; // convert to unsigned magnitude if negative + + Division_START = (op_b_i != 32'd0 && signed_overflow == 1'b0) ? 1'b1 : 1'b0; // start Division if no signed overflow or division by zero + + sign_bit = op_a_i[31] ^ op_b_i[31]; // check sign of dividend and divisor see if quotient needs to be fixed + + result_fix = (sign_bit == 1'b1) ? ~quotient + 1'b1 : quotient; // sign fixing logic that will fix unsigned quotient coming out of divider + + if(op_b_i == 32'd0) begin // signed overflow and div by 0 cases + + ALU_OUTPUT_COMB = 32'hFFFF_FFFF; //ALU output stays -1 if div by zero + + end else if(signed_overflow) begin + + ALU_OUTPUT_COMB = 32'h8000_0000; //ALU output stays -2^31 if signed overflow + + end else begin + + ALU_OUTPUT_COMB = result_fix; // if no overflow or div by zero then ALU will be the result)fix + + end + + end + + default: begin + ALU_OUTPUT_COMB = 32'b0; // Defaults + MULTIPLY_REG = 64'b0; + branch_taken_o = 1'b0; + divisor = 32'b0; + dividend = 32'b0; + Division_START = 1'b0; + sign_bit = 1'b0; + result_fix = 32'b0; + signed_overflow = 1'b0; + end endcase From 7f752a5fb84ec6ddaf9e4337bcc012aeb6aca58f Mon Sep 17 00:00:00 2001 From: Gavin Wiese Date: Fri, 20 Feb 2026 14:51:04 -0500 Subject: [PATCH 10/20] Update plic.sv --- rtl/irq/plic.sv | 48 ++++++++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/rtl/irq/plic.sv b/rtl/irq/plic.sv index af74cb5..a2582a2 100644 --- a/rtl/irq/plic.sv +++ b/rtl/irq/plic.sv @@ -1,17 +1,20 @@ -module plic #( - parameter NSOURCES = 32, +`timescale 1ns / 1ps + +module PLIC #( + parameter NSOURCES = 8, parameter PRIO_WIDTH = 3, - parameter SRC_ID_WIDTH = 5 + parameter SRC_ID_WIDTH = 3 )( - input logic clk_i, - input logic rst_ni, - input logic [NSOURCES-1:0] src_i, // External interrupt sources + input logic clk_i, + input logic rst_ni, + input logic claim_req_i, + input logic complete_i, + input logic [NSOURCES-1:0] src_i, // External interrupt sources - input logic [NSOURCES*PRIO_WIDTH-1:0] priority_wdata, - input logic priority_we, - input logic [NSOURCES-1:0] enable_wdata, - input logic enable_we, - input logic claim_we, + input logic [NSOURCES*PRIO_WIDTH-1:0] priority_wdata, + input logic priority_we, + input logic [NSOURCES-1:0] enable_wdata, + input logic enable_we, output logic ext_irq_o, output logic [SRC_ID_WIDTH-1:0] claim_o @@ -28,8 +31,8 @@ module plic #( logic [PRIO_WIDTH-1:0] tempHighestValue; logic activeClaim; - assign claim_o = claim; - assign ext_irq_o = (tempHighestValue != 0); + assign claim_o = activeClaim ? (claim + 1'b1) : '0; + assign ext_irq_o = (!activeClaim) && (tempHighestValue != 0); // ------------------------- // Priority selector @@ -39,8 +42,7 @@ module plic #( highestPriorIndex = 0; for (int i = 0; i < NSOURCES; i++) begin - if (pending[i] && - priorities[i*PRIO_WIDTH +: PRIO_WIDTH] > tempHighestValue) begin + if (pending[i] && enable[i] && priorities[i*PRIO_WIDTH +: PRIO_WIDTH] > tempHighestValue) begin tempHighestValue = priorities[i*PRIO_WIDTH +: PRIO_WIDTH]; highestPriorIndex = i[SRC_ID_WIDTH-1:0]; end @@ -66,16 +68,21 @@ module plic #( if (enable_we) enable <= enable_wdata; - if (claim_we) - activeClaim <= 0; // Claim complete - // Pending interrupt latching for (int i = 0; i < NSOURCES; i++) begin - pending[i] <= pending[i] | (src_i[i] & enable[i]); + pending[i] <= pending[i]; + if(!(activeClaim && (i == claim))) begin + pending[i] <= pending[i] | src_i[i]; + end end + //Complete logic + if (complete_i && activeClaim) begin + activeClaim <= 0; + end + // Claim logic - if (!activeClaim && tempHighestValue != 0) begin + if (claim_req_i && !activeClaim && tempHighestValue != 0) begin claim <= highestPriorIndex; pending[highestPriorIndex] <= 0; activeClaim <= 1; @@ -83,3 +90,4 @@ module plic #( end end endmodule + From a0eb68b0ff482c08a66b62a15470eff45378a440 Mon Sep 17 00:00:00 2001 From: Gavin Wiese Date: Fri, 20 Feb 2026 14:54:46 -0500 Subject: [PATCH 11/20] Update plic_module_brief_v1.0.md --- docs/ip-briefs/plic_module_brief_v0.2.md | 49 +++++++++++++----------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/docs/ip-briefs/plic_module_brief_v0.2.md b/docs/ip-briefs/plic_module_brief_v0.2.md index 24f5a83..b0b4c65 100644 --- a/docs/ip-briefs/plic_module_brief_v0.2.md +++ b/docs/ip-briefs/plic_module_brief_v0.2.md @@ -1,16 +1,16 @@ -# PLIC - Module Brief (v0.3) +# PLIC - Module Brief (v1.0) **Owner:** Gavin Wiese **RTL:** rtl/irq/plic.sv ### Purpose & Role -The Platform-Level Interrupt Controller (PLIC) is placed near the CPU core. The PLIC manages and prioritizes external interrupt requests from up to 32 sources, forwarding only the highest-priority pending interrupt to the CPU. This allows the processor to efficiently handle asynchronous external events. +The Platform-Level Interrupt Controller (PLIC) is placed near the CPU core. The PLIC manages and prioritizes external interrupt requests from up to `NSOURCES` sources, forwarding only the highest-priority pending interrupt to the CPU. This allows the processor to efficiently handle asynchronous external events. ### Parameters -- Number of interrupt sources: 32 (`NSOURCES`) -- Priority field width per source: 3 bits (`PRIO_WIDTH`) -- Interrupt ID width for claim/complete operations: `$clog2(NSOURCES)` +- Number of interrupt sources: `NSOURCES` (default 8) +- Priority field width per source: `PRIO_WIDTH` (default 3 bits) +- Interrupt ID width: `SRC_ID_WIDTH` (default 3 bits) ### Interfaces (Ports) @@ -18,52 +18,57 @@ The Platform-Level Interrupt Controller (PLIC) is placed near the CPU core. The |----------------------|---------|-----------|----------------------------------------------------| | clk_i | in | 1 | System clock | | rst_ni | in | 1 | Active-low asynchronous reset | -| src_i | in | 32 | External interrupt sources | -| priority_wdata | in | 96 | Data to write to all priority registers (32 × 3) | +| claim_req_i | in | 1 | CPU claim request pulse | +| complete_i | in | 1 | CPU interrupt completion pulse | +| src_i | in | NSOURCES | External interrupt sources | +| priority_wdata | in | NSOURCES × PRIO_WIDTH | Data to write to all priority registers | | priority_we | in | 1 | Write enable for priority registers | -| enable_wdata | in | 32 | Data to write to enable register | +| enable_wdata | in | NSOURCES | Data to write to enable register | | enable_we | in | 1 | Write enable for enable register | -| claim_wdata | in | 5 | Claim complete input | -| claim_we | in | 1 | Write enable for claim completion | | ext_irq_o | out | 1 | Interrupt output to the CPU core | -| claim_o | out | 5 | Current claimed interrupt ID | +| claim_o | out | SRC_ID_WIDTH | Current claimed interrupt ID (1-based, 0 = none) | ### Reset/Init -An active-low asynchronous reset (`rst_ni`) is used for the PLIC. When reset is asserted (`rst_ni = 0`), all internal registers—including `priorities`, `enable`, `pending`, and `claim`—are cleared to 0, and the output signal `ext_irq_o` is deasserted. +An active-low asynchronous reset (`rst_ni`) is used for the PLIC. When reset is asserted (`rst_ni = 0`), all internal registers—including `priorities`, `enable`, `pending`, and claim state—are cleared to 0, and the output signal `ext_irq_o` is deasserted. ### Behavior and Timing -The PLIC continuously monitors the 32 `src_i` interrupt lines. When one or more enabled interrupts are pending, the highest-priority source is selected, and `ext_irq_o` is asserted to signal the CPU core. Once the CPU completes the interrupt (signaled via `claim_we`), the pending bit for that interrupt is cleared and `ext_irq_o` deasserts. All operations are synchronous with the system clock, and `ext_irq_o` asserts one clock cycle after the conditions are met. +The PLIC continuously monitors the `src_i` interrupt lines. When one or more enabled interrupts are pending with nonzero priority and no interrupt is currently in service, the highest-priority source is selected and `ext_irq_o` is asserted to signal the CPU core. + +When the CPU asserts `claim_req_i`, the PLIC outputs the highest-priority enabled pending interrupt ID on `claim_o` (1-based) and clears that interrupt’s pending bit. While an interrupt is in service, `ext_irq_o` remains deasserted. + +When the CPU signals completion via `complete_i`, the in-service state is cleared, allowing the next pending interrupt (if any) to be delivered. + +All operations are synchronous with the system clock. ### Programming Model -The PLIC provides three sets of registers controlled via simple write-enable/data inputs: +The PLIC provides two sets of registers controlled via simple write-enable/data inputs: - **`priority`** – Stores the priority of each interrupt source. Higher values indicate higher priority. Updated via `priority_wdata` and `priority_we`. - **`enable`** – Determines which interrupt sources are enabled. Updated via `enable_wdata` and `enable_we`. -- **`claim`** – Contains the currently claimed interrupt ID. Writing to this register with `claim_wdata` and `claim_we` signals completion, clearing the pending bit. -All registers are accessible through the `_we` / `_wdata` inputs in this bus-free implementation. +Claim and completion are handled via `claim_req_i` and `complete_i` handshake signals. ### Errors/IRQs | **IRQ** | **Source** | **Trigger** | **Clear** | |------------|-----------|----------------------------------|-------------------------------------| -| ext_irq_o | src_i | One or more enabled interrupts pending | Cleared when CPU signals completion via claim input | +| ext_irq_o | src_i | One or more enabled interrupts pending with priority > 0 and no active claim | Cleared while in service; may reassert after completion | The PLIC does not generate additional internal error signals; all interrupts come from external sources. ### Performance Targets -- `ext_irq_o` asserts within one clock cycle of a pending, enabled interrupt being detected. -- All internal registers (priority, enable, claim/complete, pending) update synchronously with the system clock. -- The PLIC can handle all 32 external sources without loss of pending interrupts. +- `ext_irq_o` asserts when an enabled pending interrupt with nonzero priority exists and no interrupt is currently in service. +- All internal registers (priority, enable, pending, claim state) update synchronously with the system clock. +- The PLIC can handle all `NSOURCES` external sources without loss of pending interrupts. ### Dependencies -The PLIC depends on `clk_i` to update internal registers and monitor interrupt sources, and on `rst_ni` to initialize registers. External interrupt lines (`src_i`) provide input events, and the PLIC drives the single interrupt output (`ext_irq_o`) to the CPU core. Register updates are controlled via `_we` / `_wdata` inputs. +The PLIC depends on `clk_i` to update internal registers and monitor interrupt sources, and on `rst_ni` to initialize registers. External interrupt lines (`src_i`) provide input events, and the PLIC drives the single interrupt output (`ext_irq_o`) to the CPU core. Register updates are controlled via `_we` / `_wdata` inputs, and interrupt servicing uses the `claim_req_i` / `complete_i` handshake. ### Verification Links -Verification for the PLIC is planned through simulation testbenches to confirm correct behavior of priority handling, enable bits, and the claim/complete mechanism. Testbenches will ensure that `ext_irq_o` asserts for the highest-priority pending interrupt, that pending bits are cleared after a claim/complete operation, and that the module responds correctly to reset (`rst_ni`). +Verification for the PLIC is planned through simulation testbenches to confirm correct behavior of priority handling, enable bits, and the claim/complete mechanism. Testbenches will ensure that `ext_irq_o` asserts for the highest-priority pending interrupt, that pending bits are cleared after a claim operation, and that the module responds correctly to reset (`rst_ni`). From f2f83305f428e2813eb6721015addc8a13ff36dc Mon Sep 17 00:00:00 2001 From: Divyesh Date: Fri, 20 Feb 2026 18:25:08 -0500 Subject: [PATCH 12/20] intial commit of ahb_to_axi.sv --- rtl/bus/bridges/ahb_to_axi.sv | 1 + 1 file changed, 1 insertion(+) diff --git a/rtl/bus/bridges/ahb_to_axi.sv b/rtl/bus/bridges/ahb_to_axi.sv index e69de29..dabed75 100644 --- a/rtl/bus/bridges/ahb_to_axi.sv +++ b/rtl/bus/bridges/ahb_to_axi.sv @@ -0,0 +1 @@ +//Divyesh \ No newline at end of file From 8987b0f549057b7362ff8ad680f42b6ef7b898db Mon Sep 17 00:00:00 2001 From: Divyesh Date: Fri, 20 Feb 2026 18:54:33 -0500 Subject: [PATCH 13/20] second commit --- rtl/bus/bridges/ahb_to_axi.sv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rtl/bus/bridges/ahb_to_axi.sv b/rtl/bus/bridges/ahb_to_axi.sv index dabed75..23a4add 100644 --- a/rtl/bus/bridges/ahb_to_axi.sv +++ b/rtl/bus/bridges/ahb_to_axi.sv @@ -1 +1 @@ -//Divyesh \ No newline at end of file +//Divyesh Narra \ No newline at end of file From 0b6c4b1e328a6d59afd13f007dd57ed1adfdeb11 Mon Sep 17 00:00:00 2001 From: Adrian Date: Thu, 26 Feb 2026 11:36:10 -0500 Subject: [PATCH 14/20] Updated division module moved enums outside the module and defined them as Typedef --- rtl/cpu/core/division.sv | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/rtl/cpu/core/division.sv b/rtl/cpu/core/division.sv index c2844b4..ab98c10 100644 --- a/rtl/cpu/core/division.sv +++ b/rtl/cpu/core/division.sv @@ -1,10 +1,15 @@ `timescale 1ns / 1ps -// Restoring division, divisor initially left-shifted by 32, quotient built MSB→LSB, divisor shifted right each iteration." +import rv32_pkg::*; +typedef enum {IDLE,STALL} state_t; + +typedef enum {GREATER_EQUAL_THAN_ZERO,LESS_THAN_ZERO} Test_remainder_flag_t; + +// Restoring division, divisor initially left-shifted by 32, quotient built MSB→LSB, divisor shifted right each iteration." module division -import rv32_pkg::*; + ( input logic clk, input logic rst, @@ -25,7 +30,9 @@ import rv32_pkg::*; - enum {IDLE,STALL} current_state, next_state; // Division FSM states 0 or 1 + state_t current_state, next_state; // Division FSM states 0 or 1 + + Test_remainder_flag_t Test_remainder_flag; // Test remainder 0 or 1 state always_ff @(posedge clk) begin // Division Stall FSM @@ -48,11 +55,7 @@ import rv32_pkg::*; end - - - - enum {GREATER_EQUAL_THAN_ZERO,LESS_THAN_ZERO} Test_remainder_flag; // Flags used for test comparison case - + // Test combinational logic interface that will be used for testing. logic signed [63:0] remainder_test_comparison; logic [63:0] remainder_test_mux; @@ -154,7 +157,8 @@ import rv32_pkg::*; end - + + end @@ -167,4 +171,4 @@ import rv32_pkg::*; -endmodule +endmodule \ No newline at end of file From 1e46f75d0fbf7f1dbd7ee98f4fcbd9bb09c2f7ed Mon Sep 17 00:00:00 2001 From: Nidal Rahman Date: Fri, 27 Feb 2026 11:57:00 -0500 Subject: [PATCH 15/20] Update axi_icache_port.sv --- rtl/bus/axi/axi_icache_port.sv | 45 ++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/rtl/bus/axi/axi_icache_port.sv b/rtl/bus/axi/axi_icache_port.sv index 09c81da..b75ccd2 100644 --- a/rtl/bus/axi/axi_icache_port.sv +++ b/rtl/bus/axi/axi_icache_port.sv @@ -8,7 +8,6 @@ module axi_icache_port #( parameter int unsigned AXI_USER_WIDTH = 1, - )( // TODO: Port set up ports @@ -16,28 +15,32 @@ module axi_icache_port #( input logic clk_i, input logic rst_ni + // icache valid request and address - input logic ic_req_valid_i, - input logic[AXI_ADDR_WIDTH-1:0] ic_addr_valid_i, + input logic ic_req_valid_i, + input logic[AXI_ADDR_WIDTH-1:0] ic_addr_valid_i, + input logic - // icache + // icache // axi address read signals - output logic axi_mem_ar_o, + output logic [AXI_ADDR_WIDTH-1:0] axi_mem_ar_o, output logic axi_ar_valid_o, input logic axi_ar_ready_i, + + // axi read data signals input logic axi_mem_r_i, input logic axi_r_ready_i, input logic axi_r_valid_i, - + input logic [AXI_ADDR_WIDTH*4-1:0] axi_mem_r_i, typedef enum [2:0] { - IDLE; // Do nothing, wait for i$ to miss - AR_SEND; // cache requested a line, put it on araddr and set ARVALID to high - R_COLLECT; // collect the requested data from the crossbar and send it to cache + IDLE, // Do nothing, wait for icache to miss + AR_SEND, // cache requested a line, put it on araddr and set ARVALID to high + R_COLLECT, // collect the requested data from the crossbar and send it to cache, once rlast is recieved, flip back to idle } icache_port_state_e; @@ -52,7 +55,29 @@ module axi_icache_port #( current_state <= next_state; end end - + + + // state transition logic + always_comb begin + next_state = current_state; + case (current_state) + IDLE: begin + if (conditions) next_state = AR_SEND; + + end + + AR_SEND: begin + if (conditions) next_state = R_COLLECT; + + end + + R_COLLECT: begin + if (conditions) next_state = IDLE; + + end + endcase + + end ); endmodule From 0c662b4db13bbe1a4b257cdccdf68d9d3e4eb48f Mon Sep 17 00:00:00 2001 From: Nidal Rahman Date: Fri, 27 Feb 2026 12:01:51 -0500 Subject: [PATCH 16/20] Silly deletions --- .gitignore | 3 +++ rtl/bus/axi/axi_icache_port.sv | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index e69de29..0fbc233 100644 --- a/.gitignore +++ b/.gitignore @@ -0,0 +1,3 @@ +venv/ +.venv/ +.DS_Store diff --git a/rtl/bus/axi/axi_icache_port.sv b/rtl/bus/axi/axi_icache_port.sv index b75ccd2..b38b7cd 100644 --- a/rtl/bus/axi/axi_icache_port.sv +++ b/rtl/bus/axi/axi_icache_port.sv @@ -9,7 +9,6 @@ module axi_icache_port #( )( - // TODO: Port set up ports // global clock and reset signals input logic clk_i, From 5d651439121f7ffe9a2f5fe885eaea1bef4f00f0 Mon Sep 17 00:00:00 2001 From: Adrian Date: Fri, 27 Feb 2026 18:23:49 -0500 Subject: [PATCH 17/20] Updated execute.sv moved the import rv32_pkg line above module --- rtl/cpu/core/execute.sv | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/rtl/cpu/core/execute.sv b/rtl/cpu/core/execute.sv index 84ad3f1..d43c835 100644 --- a/rtl/cpu/core/execute.sv +++ b/rtl/cpu/core/execute.sv @@ -8,13 +8,12 @@ 4) unsigned instructions still get signed extended and instructions like SLTU will compare raw bit pattern, so SLTU -1 > 32 is TRUE for example, and not interpret the sign bit unlike SLT which is signed 5) divide (div), divide unsigned (divu), remainder (rem), and remainder unsigned (remu), see pg 390 6) multiply (mul), multiply high(mulh), multiply high unsigned(mulhu) multiply high signed-unsigned(mulhsu) are supported 384 - - - */ -module execute import rv32_pkg::*; + +module execute + ( input logic clk, // Main clk input input logic rst, // Active-low asynchronous reset @@ -24,7 +23,7 @@ import rv32_pkg::*; input logic [4:0] ALU_OP, output logic [DATA_WIDTH-1:0] alu_res_o, // ALU result from procesing operands output logic branch_taken_o, // Control signal for whether branch should be taken - output logic state // used for stalling the pipeline when division module enters STALL state + output logic division_state // used for stalling the pipeline when division module enters STALL state //output logic [DATA_WIDTH-1:0] branch_target_o // Address for branch to redirect program counter deleted because decode will produce branch target in a registered state ); @@ -69,7 +68,6 @@ import rv32_pkg::*; logic [DATA_WIDTH-1:0] remainder; // mod logic sign_bit; logic signed_overflow; - logic state; // used for stalling the pipeline when division module enters STALL state division Unit( .clk(clk), @@ -80,7 +78,7 @@ import rv32_pkg::*; .remainder(remainder), .Division_DONE(Division_DONE), .quotient(quotient), - .state(state) + .state(division_state) ); //TODO: for division we have to add the stalling and only latch on to values when they are valid, right now they are always being driven, From 18d1892c69fffbd61c5249f824964f93cbaab6b9 Mon Sep 17 00:00:00 2001 From: Adrian Date: Fri, 27 Feb 2026 18:48:27 -0500 Subject: [PATCH 18/20] updated clk and reg signals updated clk and reg signals to clk_i and rst_ni --- rtl/cpu/core/division.sv | 15 +++++++-------- rtl/cpu/core/execute.sv | 14 +++++++------- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/rtl/cpu/core/division.sv b/rtl/cpu/core/division.sv index ab98c10..2f7eda7 100644 --- a/rtl/cpu/core/division.sv +++ b/rtl/cpu/core/division.sv @@ -1,4 +1,3 @@ -`timescale 1ns / 1ps import rv32_pkg::*; @@ -11,8 +10,8 @@ typedef enum {GREATER_EQUAL_THAN_ZERO,LESS_THAN_ZERO} Test_remainder_flag_t; module division ( - input logic clk, - input logic rst, + input logic clk_i, + input logic rst_ni, input logic Division_START, // Start Division input logic [31:0] dividend, // numerator input logic [31:0] divisor, // denominator @@ -35,8 +34,8 @@ module division Test_remainder_flag_t Test_remainder_flag; // Test remainder 0 or 1 state - always_ff @(posedge clk) begin // Division Stall FSM - if(rst==1'b0) begin // Active low reset + always_ff @(posedge clk_i) begin // Division Stall FSM + if(rst_ni == 1'b0) begin // Active low reset current_state <= IDLE; end else begin current_state <= next_state; @@ -97,8 +96,8 @@ module division end - always_ff @(posedge clk) begin - if(rst == 1'b0) begin + always_ff @(posedge clk_i) begin + if(rst_ni == 1'b0) begin dividend_reg <= 32'd0; divisor_reg <= 64'd0; remainder_reg <= 64'd0; @@ -143,7 +142,7 @@ module division end - always_ff @(posedge clk) begin + always_ff @(posedge clk_i) begin if(counter == 32'd33) begin $display("Quotient: %0d",quotient); diff --git a/rtl/cpu/core/execute.sv b/rtl/cpu/core/execute.sv index d43c835..b6984fe 100644 --- a/rtl/cpu/core/execute.sv +++ b/rtl/cpu/core/execute.sv @@ -1,4 +1,4 @@ -`timescale 1ns / 1ps + /* Assumptions: @@ -15,8 +15,8 @@ import rv32_pkg::*; module execute ( - input logic clk, // Main clk input - input logic rst, // Active-low asynchronous reset + input logic clk_i, // Main clk input + input logic rst_ni, // Active-low asynchronous reset input logic ctrl_i, // Control signals to execute input logic [DATA_WIDTH-1:0] op_a_i, // Register A operand (data) from RF input logic [DATA_WIDTH-1:0] op_b_i, // Register B operand (data) or sign extended immediate 32'b values @@ -49,8 +49,8 @@ module execute logic [DATA_WIDTH-1:0] ALU_OUTPUT_COMB; - always_ff @(posedge clk) begin - if(rst == 1'b0) + always_ff @(posedge rst_ni) begin + if(rst_ni == 1'b0) alu_res_o <= 32'd0; else begin alu_res_o <= ALU_OUTPUT_COMB; @@ -70,8 +70,8 @@ module execute logic signed_overflow; division Unit( - .clk(clk), - .rst(rst), + .clk_i(clk_i), + .rst_ni(rst_ni), .Division_START(Division_START), .dividend(dividend), .divisor(divisor), From a3f1fb3d0caf65e45add9b43cba5bfefffd932c0 Mon Sep 17 00:00:00 2001 From: Adrian Date: Sat, 28 Feb 2026 17:21:49 -0500 Subject: [PATCH 19/20] Added asynchronous reset, added stall output --- rtl/cpu/core/division.sv | 11 ++++++----- rtl/cpu/core/execute.sv | 11 ++++------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/rtl/cpu/core/division.sv b/rtl/cpu/core/division.sv index 2f7eda7..7eca5b4 100644 --- a/rtl/cpu/core/division.sv +++ b/rtl/cpu/core/division.sv @@ -17,7 +17,8 @@ module division input logic [31:0] divisor, // denominator output logic [63:0] remainder, // Mod output logic Division_DONE, // done flag - output logic [31:0] quotient // result + output logic [31:0] quotient, // result + output logic stall_o // outputting to stall the pipeline when high ); logic [31:0] dividend_reg; // internal registers driven by inputs @@ -26,15 +27,15 @@ module division logic [31:0] quotient_reg; logic [5:0] counter; logic Division_DONE_reg; - - state_t current_state, next_state; // Division FSM states 0 or 1 Test_remainder_flag_t Test_remainder_flag; // Test remainder 0 or 1 state + + assign stall_o = current_state; // used for stalling the pipeline - always_ff @(posedge clk_i) begin // Division Stall FSM + always_ff @(posedge clk_i or negedge rst_ni) begin // Division Stall FSM if(rst_ni == 1'b0) begin // Active low reset current_state <= IDLE; end else begin @@ -96,7 +97,7 @@ module division end - always_ff @(posedge clk_i) begin + always_ff @(posedge clk_i or negedge rst_ni) begin if(rst_ni == 1'b0) begin dividend_reg <= 32'd0; divisor_reg <= 64'd0; diff --git a/rtl/cpu/core/execute.sv b/rtl/cpu/core/execute.sv index b6984fe..800ba91 100644 --- a/rtl/cpu/core/execute.sv +++ b/rtl/cpu/core/execute.sv @@ -23,7 +23,7 @@ module execute input logic [4:0] ALU_OP, output logic [DATA_WIDTH-1:0] alu_res_o, // ALU result from procesing operands output logic branch_taken_o, // Control signal for whether branch should be taken - output logic division_state // used for stalling the pipeline when division module enters STALL state + output logic stall_o // used for stalling the pipeline when division module enters STALL state //output logic [DATA_WIDTH-1:0] branch_target_o // Address for branch to redirect program counter deleted because decode will produce branch target in a registered state ); @@ -49,7 +49,7 @@ module execute logic [DATA_WIDTH-1:0] ALU_OUTPUT_COMB; - always_ff @(posedge rst_ni) begin + always_ff @(posedge ctrl_i or negedge rst_ni) begin if(rst_ni == 1'b0) alu_res_o <= 32'd0; else begin @@ -66,7 +66,7 @@ module execute logic [DATA_WIDTH-1:0] quotient; //result logic [DATA_WIDTH-1:0] result_fix; // Will decide if quotient should be signed logic [DATA_WIDTH-1:0] remainder; // mod - logic sign_bit; + logic sign_bit; // used for fixing sign bit in division logic signed_overflow; division Unit( @@ -78,12 +78,9 @@ module execute .remainder(remainder), .Division_DONE(Division_DONE), .quotient(quotient), - .state(division_state) + .stall_o(stall_o) ); - //TODO: for division we have to add the stalling and only latch on to values when they are valid, right now they are always being driven, - // so garbage values are seen throughout the cycles - always_comb begin // ALU selection OPCODE ALU_OUTPUT_COMB = 32'b0; // Defaults From 3660ca41498f2786d79c0dce50dd20a08c38a592 Mon Sep 17 00:00:00 2001 From: Nidal Rahman Date: Fri, 27 Mar 2026 13:14:27 -0400 Subject: [PATCH 20/20] update the icache port file from local --- rtl/bus/axi/axi_icache_port.sv | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/rtl/bus/axi/axi_icache_port.sv b/rtl/bus/axi/axi_icache_port.sv index b38b7cd..589d224 100644 --- a/rtl/bus/axi/axi_icache_port.sv +++ b/rtl/bus/axi/axi_icache_port.sv @@ -1,6 +1,7 @@ -import interconnect_pkg; +// import interconnect_pkg; module axi_icache_port #( + // System AXI Parameters parameter int unsigned AXI_ADDR_WIDTH = 32, parameter int unsigned AXI_DATA_WIDTH = 64, @@ -18,23 +19,26 @@ module axi_icache_port #( // icache valid request and address input logic ic_req_valid_i, input logic[AXI_ADDR_WIDTH-1:0] ic_addr_valid_i, - input logic - // icache + // I$ miss logic + input logic icache_miss_ar, + input logic icache_miss, // axi address read signals output logic [AXI_ADDR_WIDTH-1:0] axi_mem_ar_o, output logic axi_ar_valid_o, input logic axi_ar_ready_i, + output logic [AXI_ADDR_WIDTH-1:0] ar_addr, - // axi read data signals + // TODO: figure out more needed parameters input logic axi_mem_r_i, input logic axi_r_ready_i, input logic axi_r_valid_i, input logic [AXI_ADDR_WIDTH*4-1:0] axi_mem_r_i, + input logic typedef enum [2:0] { IDLE, // Do nothing, wait for icache to miss @@ -57,21 +61,22 @@ module axi_icache_port #( // state transition logic + // TODO: finish the state transition logic always_comb begin next_state = current_state; case (current_state) IDLE: begin - if (conditions) next_state = AR_SEND; + if (icache_miss && ) next_state = AR_SEND; end AR_SEND: begin - if (conditions) next_state = R_COLLECT; + if () next_state = R_COLLECT; end R_COLLECT: begin - if (conditions) next_state = IDLE; + if () next_state = IDLE; end endcase