From 6c2e786d395eff665d3992c11113609527d0862b Mon Sep 17 00:00:00 2001 From: bpain Date: Tue, 19 May 2026 18:42:20 -0700 Subject: [PATCH 1/2] added riscV decoder probably bad --- src/riscV_decoder.sv | 244 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 244 insertions(+) create mode 100644 src/riscV_decoder.sv diff --git a/src/riscV_decoder.sv b/src/riscV_decoder.sv new file mode 100644 index 0000000..d7ea3a8 --- /dev/null +++ b/src/riscV_decoder.sv @@ -0,0 +1,244 @@ +`default_nettype none +`timescale 1ns/1ns + +// INSTRUCTION DECODER +// > Decodes an instruction into the control signals necessary to execute it +// > Each core has it's own decoder +module decoder ( + input wire clk, + input wire reset, + + input reg [2:0] core_state, + input reg [31:0] instruction, + + // Instruction Signals + output reg [3:0] decoded_rd_address, + output reg [3:0] decoded_rs_address, //rs == rs1 in RISC-V spec + output reg [3:0] decoded_rt_address, + output reg [2:0] decoded_nzp, + output reg [7:0] decoded_immediate, + + // Control Signals + output reg decoded_reg_write_enable, // Enable writing to a register + output reg decoded_mem_read_enable, // Enable reading from memory + output reg decoded_mem_write_enable, // Enable writing to memory + output reg decoded_nzp_write_enable, // Enable writing to NZP register + output reg [1:0] decoded_reg_input_mux, // Select input to register + output reg [3:0] decoded_alu_arithmetic_mux, // Select arithmetic operation + output reg decoded_alu_output_mux, // Select operation in ALU + output reg decoded_pc_mux, // Select source of next PC + + //added outputs for new control signals + output logic [1:0] BYTE_SEL, + output logic SIGN, + output logic [2:0] IMM_SEL, + output logic BRANCH, + output logic [2:0] BR_TYPE, + output logic JUMP, + //could combine into one signal + output logic SPLIT, + output logic JOINT, + output logic BAR, + // + + // Return (finished executing thread) + output reg decoded_ret +); + + assign func3[2:0] = instruction[14:12]; + + localparam + AUIPC = 7'b0010111, + JAL = 7'b1101111, + JALR = 7'b1100111, + LUI = 7'b0110111, + BTYPE = 7'b1100011, + LOAD = 7'b0000011, + STORE = 7'b0100011, + OP_IMM = 7'b0010011, + OP = 7'b0110011, + VORTEX = 7'b0001011, + + + always @(posedge clk) begin + if (reset) begin + decoded_rd_address <= 0; + decoded_rs_address <= 0; + decoded_rt_address <= 0; + decoded_immediate <= 0; + decoded_nzp <= 0; + decoded_reg_write_enable <= 0; + decoded_mem_read_enable <= 0; + decoded_mem_write_enable <= 0; + // decoded_nzp_write_enable <= 0; + decoded_reg_input_mux <= 0; + decoded_alu_arithmetic_mux <= 0; + decoded_alu_output_mux <= 0; + decoded_pc_mux <= 0; + decoded_ret <= 0; + + BYTE_SEL <= 2'b00; + SIGN <= 1'b0; + IMM_SEL <= 3'b000; + BRANCH <= 1'b0; + BR_TYPE <= 3'b000; + JUMP <= 1'b0; + + end else begin + // Decode when core_state = DECODE + if (core_state == 3'b010) begin + // Get instruction signals from instruction every time + decoded_rd_address <= instruction[11:8]; + decoded_rs_address <= instruction[7:4]; + decoded_rt_address <= instruction[3:0]; + decoded_immediate <= instruction[7:0]; + decoded_nzp <= instruction[11:9]; + + // Control signals reset on every decode and set conditionally by instruction + decoded_reg_write_enable <= 0; + decoded_mem_read_enable <= 0; + decoded_mem_write_enable <= 0; + decoded_nzp_write_enable <= 0; + decoded_reg_input_mux <= 0; + decoded_alu_arithmetic_mux <= 0; + decoded_alu_output_mux <= 0; + decoded_pc_mux <= 0; + decoded_ret <= 0; + // Set the control signals for each instruction + case (instruction[6:0]) + JAL: begin + decoded_pc_mux <= 1; // Jump to immediate + JUMP <= 1; // Set jump signal for JAL instruction + IMM_SEL <= 3'b010; // Set immediate type to J-type + decoded_reg_write_enable <= 1; // Write return address to rd + decoded_reg_input_mux <= 2'b00; // Input to register is PC+4 + end + JALR: begin + JUMP <= 1; // Set jump signal for JALR instruction + IMM_SEL <= 3'b000; // Set immediate type to I-type + decoded_pc_mux <= 3; // Jump to rs + immediate + decoded_reg_write_enable <= 1; // Write return address to rd + decoded_reg_input_mux <= 2'b00; // Input to register is PC+4 + end + LUI: begin + IMM_SEL <= 3'b011; // Set immediate type to U-type + //decoded_pc_mux <= 0; // No change to PC + decoded_reg_write_enable <= 1; // Write to rd + decoded_reg_input_mux <= 2'b11; // Input to register is u-type immediate + decoded_alu_output_mux <= 1; // ALU outputs u-type immediate (lui-copy) + end + AUIPC: begin + //decoded_pc_mux <= 0; // No change to PC + decoded_reg_write_enable <= 1; // Write to rd + decoded_reg_input_mux <= 2'b11; // Input to register is u-type immediate + decoded_alu_output_mux <= 0; // ALU outputs pc + u-type immediate + end + + BTYPE: begin + //decoded_pc_mux <= 1; // Jump to immediate if branch taken --> add smthing in if we're not doing pure masking for divergence + decoded_pc_mux <= 2; // Conditional branch to immediate + IMM_SEL <= 3'b001; // Set immediate type to B-type + BRANCH <= 1; // Set branch signal for branch instructions + BR_TYPE <= func3; // Set branch type based on func3 + end + LOAD: begin + decoded_mem_read_enable <= 1; // Read from memory + decoded_reg_write_enable <= 1; // Write to register + decoded_reg_input_mux <= 2'b01; // Input to register is memory output + IMM_SEL = 3'b000; // I-Type + case(FUNC3) + 3'b000: begin // LB + BYTE_SEL = 2'b00; + SIGN = 1'b1; + end + 3'b001: begin // LH + BYTE_SEL = 2'b01; + SIGN = 1'b1; + end + 3'b010: begin // LW + BYTE_SEL = 2'b10; + SIGN = 1'b1; + end + 3'b011: begin // LBU + BYTE_SEL = 2'b00; + SIGN = 1'b0; + end + 3'b100: begin //LHU + BYTE_SEL = 2'b01; + SIGN = 1'b0; + end + default: begin // default = LW + BYTE_SEL = 2'b10; + SIGN = 1'b1; + end + endcase + end + STORE: begin + decoded_mem_write_enable <= 1; // Write to memory + IMM_SEL <= 3'b010; // Set immediate type to S-type + case(FUNC3) + 3'b000: begin // SB + BYTE_SEL = 2'b00; + end + 3'b001: begin // SH + BYTE_SEL = 2'b01; + end + 3'b010: begin // SW + BYTE_SEL = 2'b10; + end + default: begin + BYTE_SEL = 2'b10; // SW + end + endcase + end + OP_IMM: begin + decoded_reg_write_enable <= 1; // Write to register + decoded_reg_input_mux <= 2'b10; // Input to register is ALU output + decoded_alu_arithmetic_mux <= instruction[14:12]; // Select arithmetic operation based on funct3 + if (instruction[14:12] == 3'b001 || instruction[14:12] == 3'b101) begin + decoded_alu_arithmetic_mux <= {instruction[30], func3}; // Select shift operation based on funct3 and funct7 + end + end + OP: begin + decoded_reg_write_enable <= 1; // Write to register + decoded_reg_input_mux <= 2'b10; // Input to register is ALU output + decoded_alu_arithmetic_mux <= {instruction[30], instruction[14:12]}; // Select arithmetic operation based on funct3 and funct7 + end + VORTEX: begin + case(func3) + TMC: begin + // No clue what we doing with this one + decoded_nzp_write_enable <= 1; // Write to NZP register to set predicate based on TMC instruction + end + WSPAWN: begin + // don't handle here + end + SPLIT: begin + // No control signals to set for split instruction in this implementation, but we could set some if needed + SPLIT <= 1; + decoded_rs_address <= instruction[7:4]; // Use rs field to specify number of threads in new warp for split instruction + decoded_rd_address <= instruction[11:8]; // Use rd field to specify warp ID for new warp in split instruction + end + JOINT: begin + // No control signals to set for joint instruction in this implementation, but we could set some if needed + JOINT <= 1; + end + BAR: begin + // No control signals to set for barrier instruction in this implementation, but we could set some if needed + BAR <= 1; + end + PRED: begin + // No control signals to set for predication instruction in this implementation, but we could set some if needed + decoded_nzp_write_enable <= 1; // Write to NZP register to set predicate for predication instruction + end + RET: begin + decoded_ret <= 1; // Signal to return (end thread) + end + default: begin ; end + endcase + end + endcase + end + end + end +endmodule From 6ee66f45cfbe2efbd8b41eeb421c9117094f91f0 Mon Sep 17 00:00:00 2001 From: bpain Date: Tue, 19 May 2026 19:14:58 -0700 Subject: [PATCH 2/2] realized I should probably lint it --- src/riscV_decoder.sv | 84 ++++++++++++++++++++++---------------------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/src/riscV_decoder.sv b/src/riscV_decoder.sv index d7ea3a8..17fd7ab 100644 --- a/src/riscV_decoder.sv +++ b/src/riscV_decoder.sv @@ -4,7 +4,7 @@ // INSTRUCTION DECODER // > Decodes an instruction into the control signals necessary to execute it // > Each core has it's own decoder -module decoder ( +module riscV_decoder ( input wire clk, input wire reset, @@ -26,7 +26,7 @@ module decoder ( output reg [1:0] decoded_reg_input_mux, // Select input to register output reg [3:0] decoded_alu_arithmetic_mux, // Select arithmetic operation output reg decoded_alu_output_mux, // Select operation in ALU - output reg decoded_pc_mux, // Select source of next PC + output reg [1:0]decoded_pc_mux, // Select source of next PC //added outputs for new control signals output logic [1:0] BYTE_SEL, @@ -38,14 +38,15 @@ module decoder ( //could combine into one signal output logic SPLIT, output logic JOINT, - output logic BAR, + output logic BAR // // Return (finished executing thread) - output reg decoded_ret + // output reg decoded_ret ); - assign func3[2:0] = instruction[14:12]; + wire [2:0] func3; + assign func3 = instruction[14:12]; localparam AUIPC = 7'b0010111, @@ -57,10 +58,11 @@ module decoder ( STORE = 7'b0100011, OP_IMM = 7'b0010011, OP = 7'b0110011, - VORTEX = 7'b0001011, + VORTEX = 7'b0001011; + localparam TMC_OP = 3'b000, SPLIT_OP = 3'b010, JOIN_OP = 3'b011, BAR_OP = 3'b100, PRED_OP = 3'b101; - always @(posedge clk) begin + always_ff @(posedge clk ) begin if (reset) begin decoded_rd_address <= 0; decoded_rs_address <= 0; @@ -75,7 +77,6 @@ module decoder ( decoded_alu_arithmetic_mux <= 0; decoded_alu_output_mux <= 0; decoded_pc_mux <= 0; - decoded_ret <= 0; BYTE_SEL <= 2'b00; SIGN <= 1'b0; @@ -103,7 +104,6 @@ module decoder ( decoded_alu_arithmetic_mux <= 0; decoded_alu_output_mux <= 0; decoded_pc_mux <= 0; - decoded_ret <= 0; // Set the control signals for each instruction case (instruction[6:0]) JAL: begin @@ -116,7 +116,7 @@ module decoder ( JALR: begin JUMP <= 1; // Set jump signal for JALR instruction IMM_SEL <= 3'b000; // Set immediate type to I-type - decoded_pc_mux <= 3; // Jump to rs + immediate + decoded_pc_mux <= 2'b11; // Jump to rs + immediate decoded_reg_write_enable <= 1; // Write return address to rd decoded_reg_input_mux <= 2'b00; // Input to register is PC+4 end @@ -136,7 +136,7 @@ module decoder ( BTYPE: begin //decoded_pc_mux <= 1; // Jump to immediate if branch taken --> add smthing in if we're not doing pure masking for divergence - decoded_pc_mux <= 2; // Conditional branch to immediate + decoded_pc_mux <= 2'b10; // Conditional branch to immediate IMM_SEL <= 3'b001; // Set immediate type to B-type BRANCH <= 1; // Set branch signal for branch instructions BR_TYPE <= func3; // Set branch type based on func3 @@ -145,56 +145,56 @@ module decoder ( decoded_mem_read_enable <= 1; // Read from memory decoded_reg_write_enable <= 1; // Write to register decoded_reg_input_mux <= 2'b01; // Input to register is memory output - IMM_SEL = 3'b000; // I-Type - case(FUNC3) + IMM_SEL <= 3'b000; // I-Type + case(func3) 3'b000: begin // LB - BYTE_SEL = 2'b00; - SIGN = 1'b1; + BYTE_SEL <= 2'b00; + SIGN <= 1'b1; end 3'b001: begin // LH - BYTE_SEL = 2'b01; - SIGN = 1'b1; + BYTE_SEL <= 2'b01; + SIGN <= 1'b1; end 3'b010: begin // LW - BYTE_SEL = 2'b10; - SIGN = 1'b1; + BYTE_SEL <= 2'b10; + SIGN <= 1'b1; end 3'b011: begin // LBU - BYTE_SEL = 2'b00; - SIGN = 1'b0; + BYTE_SEL <= 2'b00; + SIGN <= 1'b0; end 3'b100: begin //LHU - BYTE_SEL = 2'b01; - SIGN = 1'b0; + BYTE_SEL <= 2'b01; + SIGN <= 1'b0; end default: begin // default = LW - BYTE_SEL = 2'b10; - SIGN = 1'b1; + BYTE_SEL <= 2'b10; + SIGN <= 1'b1; end endcase end STORE: begin decoded_mem_write_enable <= 1; // Write to memory IMM_SEL <= 3'b010; // Set immediate type to S-type - case(FUNC3) + case(func3) 3'b000: begin // SB - BYTE_SEL = 2'b00; + BYTE_SEL <= 2'b00; end 3'b001: begin // SH - BYTE_SEL = 2'b01; + BYTE_SEL <= 2'b01; end 3'b010: begin // SW - BYTE_SEL = 2'b10; + BYTE_SEL <= 2'b10; end default: begin - BYTE_SEL = 2'b10; // SW + BYTE_SEL <= 2'b10; // SW end endcase end OP_IMM: begin decoded_reg_write_enable <= 1; // Write to register decoded_reg_input_mux <= 2'b10; // Input to register is ALU output - decoded_alu_arithmetic_mux <= instruction[14:12]; // Select arithmetic operation based on funct3 + decoded_alu_arithmetic_mux <= {1'b0, instruction[14:12]}; // Select arithmetic operation based on funct3 if (instruction[14:12] == 3'b001 || instruction[14:12] == 3'b101) begin decoded_alu_arithmetic_mux <= {instruction[30], func3}; // Select shift operation based on funct3 and funct7 end @@ -206,37 +206,37 @@ module decoder ( end VORTEX: begin case(func3) - TMC: begin + TMC_OP: begin // No clue what we doing with this one decoded_nzp_write_enable <= 1; // Write to NZP register to set predicate based on TMC instruction end - WSPAWN: begin - // don't handle here - end - SPLIT: begin + // WSPAWN_OP: begin + // // don't handle here + // end + SPLIT_OP: begin // No control signals to set for split instruction in this implementation, but we could set some if needed SPLIT <= 1; decoded_rs_address <= instruction[7:4]; // Use rs field to specify number of threads in new warp for split instruction decoded_rd_address <= instruction[11:8]; // Use rd field to specify warp ID for new warp in split instruction end - JOINT: begin + JOIN_OP: begin // No control signals to set for joint instruction in this implementation, but we could set some if needed JOINT <= 1; end - BAR: begin + BAR_OP: begin // No control signals to set for barrier instruction in this implementation, but we could set some if needed BAR <= 1; end - PRED: begin + PRED_OP: begin // No control signals to set for predication instruction in this implementation, but we could set some if needed decoded_nzp_write_enable <= 1; // Write to NZP register to set predicate for predication instruction end - RET: begin - decoded_ret <= 1; // Signal to return (end thread) - end default: begin ; end endcase end + default: begin + // For unrecognized instructions, keep all control signals at default (mostly 0) + end endcase end end