From 3c224776202b789b5fb0b1d4a04afc26ab1a143d Mon Sep 17 00:00:00 2001 From: jeff-7 Date: Tue, 3 Mar 2026 00:02:25 -0500 Subject: [PATCH 01/30] Add Zbs single-bit operations implementation (RV32, SystemVerilog) --- src/ext/b/zbs.sv | 70 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 src/ext/b/zbs.sv diff --git a/src/ext/b/zbs.sv b/src/ext/b/zbs.sv new file mode 100644 index 00000000..bc98a5ff --- /dev/null +++ b/src/ext/b/zbs.sv @@ -0,0 +1,70 @@ +// Zbs: Single-Bit Operations (RV32) +// Implements the RV32 Zbs (Bit-Manipulation Single-Bit) instructions: +// - bclr / bclri : Clear bit +// - bset / bseti : Set bit +// - binv / binvi : Invert bit +// - bext / bexti : Extract bit (result placed in bit[0]) +// The decoder is responsible for selecting the correct operands: +// - For register-form instructions: +// reg2 = rs2 +// - For immediate-form instructions: +// reg2[4:0] = shamt +// Therefore, this module simply treats reg2[4:0] as the bit index. +// +// inst encoding (local mini-ALU selector): +// 3'b000 : bclr / bclri +// 3'b001 : bset / bseti +// 3'b010 : binv / binvi +// 3'b011 : bext / bexti +// 3'b100-111 : reserved +// +// Notes: +// - RV32 => XLEN = 32 +// - Bit index is masked to 5 bits (0–31) +// - All logic is purely combinational + +module zbs ( + input logic [31:0] reg1, // rs1 operand + input logic [31:0] reg2, // rs2 or immediate (index source) + input logic [2:0] inst, // operation selector + output logic [31:0] out // result +); + + // Extract bit index (only lower 5 bits used in RV32) + logic [4:0] index; + + // Bit mask for single-bit operations + logic [31:0] mask; + + // Combinational ALU logic + always_comb begin + + // reg2 may come from rs2 or immediate (handled externally) + index = reg2[4:0]; + + // Generate one-hot mask: 1 << index + mask = 32'h1 << index; + + // Perform selected single-bit operation + unique case (inst) + + // Clear selected bit + 3'b000: out = reg1 & ~mask; + + // Set selected bit + 3'b001: out = reg1 | mask; + + // Invert selected bit + 3'b010: out = reg1 ^ mask; + + // Extract selected bit into bit[0] + // Upper bits are zero + 3'b011: out = (reg1 >> index) & 32'h1; + + // Default safe output + default: out = 32'd0; + + endcase + end + +endmodule \ No newline at end of file From 180479630fc2dad25373a622923b0fb1d4fba756 Mon Sep 17 00:00:00 2001 From: jeff-7 Date: Tue, 3 Mar 2026 00:05:20 -0500 Subject: [PATCH 02/30] Ignore macOS .DS_Store --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 8738c930..08982cae 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,4 @@ out/** !out/.gitkeep build/** !build/.gitkeep +.DS_Store From 38ffa5d8d1e9c9c19079268ef35c8c81a23ee36d Mon Sep 17 00:00:00 2001 From: jeff-7 Date: Tue, 3 Mar 2026 00:42:31 -0500 Subject: [PATCH 03/30] Fix svlint style issues in Zbs --- src/ext/b/zbs.sv | 86 +++++++++++++++++++----------------------------- 1 file changed, 33 insertions(+), 53 deletions(-) diff --git a/src/ext/b/zbs.sv b/src/ext/b/zbs.sv index bc98a5ff..b7f3d7d2 100644 --- a/src/ext/b/zbs.sv +++ b/src/ext/b/zbs.sv @@ -1,70 +1,50 @@ // Zbs: Single-Bit Operations (RV32) -// Implements the RV32 Zbs (Bit-Manipulation Single-Bit) instructions: -// - bclr / bclri : Clear bit -// - bset / bseti : Set bit -// - binv / binvi : Invert bit -// - bext / bexti : Extract bit (result placed in bit[0]) -// The decoder is responsible for selecting the correct operands: -// - For register-form instructions: -// reg2 = rs2 -// - For immediate-form instructions: -// reg2[4:0] = shamt -// Therefore, this module simply treats reg2[4:0] as the bit index. // -// inst encoding (local mini-ALU selector): -// 3'b000 : bclr / bclri -// 3'b001 : bset / bseti -// 3'b010 : binv / binvi -// 3'b011 : bext / bexti -// 3'b100-111 : reserved +// Implements: +// - bclr / bclri +// - bset / bseti +// - binv / binvi +// - bext / bexti // -// Notes: -// - RV32 => XLEN = 32 -// - Bit index is masked to 5 bits (0–31) -// - All logic is purely combinational +// Design note: +// - This module is purely functional. +// - reg2[4:0] is treated as the bit index. +// - R/I distinction is handled in the decoder. module zbs ( - input logic [31:0] reg1, // rs1 operand - input logic [31:0] reg2, // rs2 or immediate (index source) - input logic [2:0] inst, // operation selector - output logic [31:0] out // result + input logic [31:0] reg1 , // rs1 operand + input logic [31:0] reg2 , // rs2 or immediate (bit index source) + input logic [1:0] inst , // operation selector + output logic [31:0] out // result ); - // Extract bit index (only lower 5 bits used in RV32) - logic [4:0] index; + logic [4:0] index ; + logic [31:0] mask ; - // Bit mask for single-bit operations - logic [31:0] mask; + always_comb + begin + index = reg2[4:0]; + mask = 32'h1 << index; - // Combinational ALU logic - always_comb begin - - // reg2 may come from rs2 or immediate (handled externally) - index = reg2[4:0]; + // Zbs operation selector + case (inst) - // Generate one-hot mask: 1 << index - mask = 32'h1 << index; + // 000 : bclr / bclri → clear selected bit + 3'b000 : out = reg1 & ~mask; - // Perform selected single-bit operation - unique case (inst) + // 001 : bset / bseti → set selected bit + 3'b001 : out = reg1 | mask; - // Clear selected bit - 3'b000: out = reg1 & ~mask; + // 010 : binv / binvi → invert selected bit + 3'b010 : out = reg1 ^ mask; - // Set selected bit - 3'b001: out = reg1 | mask; + // 011 : bext / bexti → extract selected bit (to bit[0]) + 3'b011 : out = (reg1 >> index) & 32'h1; - // Invert selected bit - 3'b010: out = reg1 ^ mask; + // others → safe default + default : out = 32'd0; - // Extract selected bit into bit[0] - // Upper bits are zero - 3'b011: out = (reg1 >> index) & 32'h1; - - // Default safe output - default: out = 32'd0; - - endcase - end + endcase + end endmodule \ No newline at end of file From 07a45567f4d6273b7319191523dbd611970e4b94 Mon Sep 17 00:00:00 2001 From: jeff-7 Date: Tue, 3 Mar 2026 00:48:43 -0500 Subject: [PATCH 04/30] Fix svlint issues --- src/ext/b/zbs.sv | 47 +++++++++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/src/ext/b/zbs.sv b/src/ext/b/zbs.sv index b7f3d7d2..45754c21 100644 --- a/src/ext/b/zbs.sv +++ b/src/ext/b/zbs.sv @@ -7,44 +7,43 @@ // - bext / bexti // // Design note: -// - This module is purely functional. -// - reg2[4:0] is treated as the bit index. -// - R/I distinction is handled in the decoder. +// - Purely combinational ALU block +// - reg2[4:0] used as bit index +// - R/I distinction handled in decoder module zbs ( - input logic [31:0] reg1 , // rs1 operand - input logic [31:0] reg2 , // rs2 or immediate (bit index source) - input logic [1:0] inst , // operation selector - output logic [31:0] out // result + input logic [31:0] reg1 , + input logic [31:0] reg2 , + input logic [1:0] inst , + output logic [31:0] out ); logic [4:0] index ; logic [31:0] mask ; always_comb - begin - index = reg2[4:0]; - mask = 32'h1 << index; + index = reg2[4:0] ; - // Zbs operation selector - case (inst) + always_comb + mask = 32'h1 << index ; + + always_comb + case (inst) - // 000 : bclr / bclri → clear selected bit - 3'b000 : out = reg1 & ~mask; + // 00 : bclr + 2'b00 : out = reg1 & ~mask ; - // 001 : bset / bseti → set selected bit - 3'b001 : out = reg1 | mask; + // 01 : bset + 2'b01 : out = reg1 | mask ; - // 010 : binv / binvi → invert selected bit - 3'b010 : out = reg1 ^ mask; + // 10 : binv + 2'b10 : out = reg1 ^ mask ; - // 011 : bext / bexti → extract selected bit (to bit[0]) - 3'b011 : out = (reg1 >> index) & 32'h1; + // 11 : bext + 2'b11 : out = (reg1 >> index) & 32'h1 ; - // others → safe default - default : out = 32'd0; + default : out = 32'd0 ; - endcase - end + endcase endmodule \ No newline at end of file From c627fe2f6acc45119d485ffe71f75e3d0a2a9e49 Mon Sep 17 00:00:00 2001 From: jeff-7 Date: Tue, 3 Mar 2026 01:05:16 -0500 Subject: [PATCH 05/30] Fix final svlint whitespace issues --- src/ext/b/zbs.sv | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/ext/b/zbs.sv b/src/ext/b/zbs.sv index 45754c21..7444576f 100644 --- a/src/ext/b/zbs.sv +++ b/src/ext/b/zbs.sv @@ -11,38 +11,38 @@ // - reg2[4:0] used as bit index // - R/I distinction handled in decoder -module zbs ( - input logic [31:0] reg1 , - input logic [31:0] reg2 , - input logic [1:0] inst , +module zbs( + input logic [31:0] reg1, + input logic [31:0] reg2, + input logic [1:0] inst, output logic [31:0] out ); - logic [4:0] index ; - logic [31:0] mask ; + logic [4:0] index; + logic [31:0] mask; always_comb - index = reg2[4:0] ; + index = reg2[4:0]; always_comb - mask = 32'h1 << index ; + mask = 32'h1 << index; always_comb - case (inst) + case(inst) // 00 : bclr - 2'b00 : out = reg1 & ~mask ; + 2'b00: out = reg1 & ~mask; // 01 : bset - 2'b01 : out = reg1 | mask ; + 2'b01: out = reg1 | mask; // 10 : binv - 2'b10 : out = reg1 ^ mask ; + 2'b10: out = reg1 ^ mask; // 11 : bext - 2'b11 : out = (reg1 >> index) & 32'h1 ; + 2'b11: out = (reg1 >> index) & 32'h1; - default : out = 32'd0 ; + default: out = 32'd0; endcase From 227077b3fcf4893273e63d0edfd92f6e89eee826 Mon Sep 17 00:00:00 2001 From: jeff-7 Date: Tue, 3 Mar 2026 01:05:32 -0500 Subject: [PATCH 06/30] Force CI From 41fd19edcec47a3fa7226e191a1b83103c372b74 Mon Sep 17 00:00:00 2001 From: jeff-7 Date: Tue, 3 Mar 2026 01:07:51 -0500 Subject: [PATCH 07/30] Fix final svlint whitespace issues --- src/ext/b/zbs.sv | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/ext/b/zbs.sv b/src/ext/b/zbs.sv index 7444576f..af93df66 100644 --- a/src/ext/b/zbs.sv +++ b/src/ext/b/zbs.sv @@ -12,10 +12,10 @@ // - R/I distinction handled in decoder module zbs( - input logic [31:0] reg1, - input logic [31:0] reg2, - input logic [1:0] inst, - output logic [31:0] out + input logic [31:0] reg1, // rs1 operand + input logic [31:0] reg2, // rs2 or immediate (bit index source) + input logic [1:0] inst, // operation selector + output logic [31:0] out // result ); logic [4:0] index; @@ -30,18 +30,19 @@ module zbs( always_comb case(inst) - // 00 : bclr + // 00 : bclr / bclri → clear selected bit 2'b00: out = reg1 & ~mask; - // 01 : bset + // 01 : bset / bseti → set selected bit 2'b01: out = reg1 | mask; - // 10 : binv + // 10 : binv / binvi → invert selected bit 2'b10: out = reg1 ^ mask; - // 11 : bext + // 11 : bext / bexti → extract selected bit (to bit[0]) 2'b11: out = (reg1 >> index) & 32'h1; + // others → safe default default: out = 32'd0; endcase From 9bcdeb1837fa6b0bd56ef413710c814efeb7388d Mon Sep 17 00:00:00 2001 From: jeff-7 Date: Tue, 3 Mar 2026 01:08:19 -0500 Subject: [PATCH 08/30] Force CI From 9c900385f1ccc0392c5821dc98aa00bb7bc7b266 Mon Sep 17 00:00:00 2001 From: jeff-7 Date: Tue, 3 Mar 2026 01:14:36 -0500 Subject: [PATCH 09/30] Fix comma-leading and keyword spacing --- src/ext/b/zbs.sv | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/ext/b/zbs.sv b/src/ext/b/zbs.sv index af93df66..b3d39e82 100644 --- a/src/ext/b/zbs.sv +++ b/src/ext/b/zbs.sv @@ -11,11 +11,11 @@ // - reg2[4:0] used as bit index // - R/I distinction handled in decoder -module zbs( - input logic [31:0] reg1, // rs1 operand - input logic [31:0] reg2, // rs2 or immediate (bit index source) - input logic [1:0] inst, // operation selector - output logic [31:0] out // result +module zbs ( + input logic [31:0] reg1 , // rs1 operand + input logic [31:0] reg2 , // rs2 or immediate (bit index source) + input logic [1:0] inst , // operation selector + output logic [31:0] out ); logic [4:0] index; @@ -28,7 +28,7 @@ module zbs( mask = 32'h1 << index; always_comb - case(inst) + case (inst) // 00 : bclr / bclri → clear selected bit 2'b00: out = reg1 & ~mask; From 533d464466180f5a12be41ddf4629f3685e944d5 Mon Sep 17 00:00:00 2001 From: jeff-7 Date: Tue, 3 Mar 2026 01:14:51 -0500 Subject: [PATCH 10/30] Force CI From a897b446ecab14839f9cff4537e5fc9d9a5f77d6 Mon Sep 17 00:00:00 2001 From: jeff-7 Date: Tue, 3 Mar 2026 01:21:14 -0500 Subject: [PATCH 11/30] Fix comma-leading and keyword spacing --- src/ext/b/zbs.sv | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ext/b/zbs.sv b/src/ext/b/zbs.sv index b3d39e82..b49adf0d 100644 --- a/src/ext/b/zbs.sv +++ b/src/ext/b/zbs.sv @@ -12,10 +12,10 @@ // - R/I distinction handled in decoder module zbs ( - input logic [31:0] reg1 , // rs1 operand - input logic [31:0] reg2 , // rs2 or immediate (bit index source) - input logic [1:0] inst , // operation selector - output logic [31:0] out + input logic [31:0] reg1 // rs1 operand + , input logic [31:0] reg2 // rs2 or immediate (bit index source) + , input logic [1:0] inst // operation selector + , output logic [31:0] out //result ); logic [4:0] index; From 4a918f29d72e3e5b51316d44b7df94d8ead073fd Mon Sep 17 00:00:00 2001 From: jeff-7 Date: Fri, 6 Mar 2026 01:31:32 -0500 Subject: [PATCH 12/30] Replace parameter with localparam in params.svh --- src/ext/b/zbs.sv | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/src/ext/b/zbs.sv b/src/ext/b/zbs.sv index b49adf0d..e0d8c9fc 100644 --- a/src/ext/b/zbs.sv +++ b/src/ext/b/zbs.sv @@ -1,31 +1,30 @@ -// Zbs: Single-Bit Operations (RV32) +// ----------------------------------------------------------------------------- +// Zbs Extension – Single-Bit Instructions (RV32) +// Reference: +// RISC-V Bitmanip Extension Specification v1.0.0 +// Section 5.4 – Zbs (Single-Bit Instructions) // -// Implements: -// - bclr / bclri -// - bset / bseti -// - binv / binvi -// - bext / bexti -// -// Design note: -// - Purely combinational ALU block -// - reg2[4:0] used as bit index -// - R/I distinction handled in decoder +// Notes: +// - Purely combinational logic +// - Bit index = reg2[4:0] +// - R/I distinction handled in decode stage +// ----------------------------------------------------------------------------- module zbs ( - input logic [31:0] reg1 // rs1 operand - , input logic [31:0] reg2 // rs2 or immediate (bit index source) - , input logic [1:0] inst // operation selector - , output logic [31:0] out //result + input data_t reg1 // rs1 operand + , input data_t reg2 // rs2 or immediate (bit index source) + , input logic [1:0] inst // operation selector + , output data_t out //result ); logic [4:0] index; - logic [31:0] mask; + data_t mask; always_comb index = reg2[4:0]; always_comb - mask = 32'h1 << index; + mask = data_t'(32'h1) << index; always_comb case (inst) @@ -40,10 +39,10 @@ module zbs ( 2'b10: out = reg1 ^ mask; // 11 : bext / bexti → extract selected bit (to bit[0]) - 2'b11: out = (reg1 >> index) & 32'h1; + 2'b11: out = (reg1 >> index) & data_t'(32'h1); // others → safe default - default: out = 32'd0; + default: out = '0; endcase From f8678c9be949869f15cb975f8414651409a5de97 Mon Sep 17 00:00:00 2001 From: SenseiPrimexus Date: Sat, 14 Mar 2026 20:47:54 -0400 Subject: [PATCH 13/30] Add Zbs instruction testbench with assertions and randomized tests --- test/zbs_tb.sv | 134 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 test/zbs_tb.sv diff --git a/test/zbs_tb.sv b/test/zbs_tb.sv new file mode 100644 index 00000000..00cc29b9 --- /dev/null +++ b/test/zbs_tb.sv @@ -0,0 +1,134 @@ +`timescale 1ns/1ns +`include "test/utils.svh" + +module zbs_tb; + +logic [31:0] reg1; +logic [31:0] reg2; +logic [2:0] inst; +logic [31:0] out; + +logic [31:0] expected; + +zbs uut ( + .reg1(reg1), + .reg2(reg2), + .inst(inst), + .out(out) +); + +initial begin + + // -------- bclr test -------- + reg1 = 32'b1010; + reg2 = 32'd1; // clear bit 1 + inst = 3'b000; + #10; + + expected = reg1 & ~(32'h1 << reg2[4:0]); + + assert(out == expected) + else $fatal("bclr failed: expected %b got %b", expected, out); + + + // -------- bset test -------- + reg1 = 32'b1110; + reg2 = 32'd0; // set bit 0 + inst = 3'b001; + #10; + + expected = reg1 | (32'h1 << reg2[4:0]); + + assert(out == expected) + else $fatal("bset failed: expected %b got %b", expected, out); + + + // -------- binv test -------- + reg1 = 32'b1010; + reg2 = 32'd1; + inst = 3'b010; + #10; + + expected = reg1 ^ (32'h1 << reg2[4:0]); + + assert(out == expected) + else $fatal("binv failed: expected %b got %b", expected, out); + + + // -------- bext test -------- + reg1 = 32'b1010; + reg2 = 32'd3; + inst = 3'b011; + #10; + + expected = (reg1 >> reg2[4:0]) & 32'h1; + + assert(out == expected) + else $fatal("bext failed: expected %b got %b", expected, out); + + // -------- Edge Cases --------- + + // Bit 0 boundary + reg1 = 32'hFFFFFFFF; + reg2 = 32'd0; + inst = 3'b000; // bclr + #10; + + expected = reg1 & ~(32'h1 << reg2[4:0]); + + assert(out == expected) + else $fatal("corner case bit0 failed"); + + + // Bit 31 boundary + reg1 = 32'hFFFFFFFF; + reg2 = 32'd31; + inst = 3'b000; // bclr + #10; + + expected = reg1 & ~(32'h1 << reg2[4:0]); + + assert(out == expected) + else $fatal("corner case bit31 failed"); + + + // ----------- Randomized Testing (Experimental) ----------- + + + repeat (1000) begin + + reg1 = $urandom; + reg2 = $urandom % 32; + inst = $urandom % 4; + + #1; + + case(inst) + + 3'b000: expected = reg1 & ~(32'h1 << reg2[4:0]); + + 3'b001: expected = reg1 | (32'h1 << reg2[4:0]); + + 3'b010: expected = reg1 ^ (32'h1 << reg2[4:0]); + + 3'b011: expected = (reg1 >> reg2[4:0]) & 32'h1; + + default: expected = 32'd0; + + endcase + + assert(out == expected) + else $fatal("random test failed: inst=%0d reg1=%h reg2=%d expected=%h got=%h", + inst, reg1, reg2, expected, out); + + end + + $display("All tests passed!"); + + $finish; + +end + +`SETUP_VCD_DUMP(zbs_tb) + +endmodule \ No newline at end of file From 50f5aee5720fd97107aeda599a3ac90ac4787b34 Mon Sep 17 00:00:00 2001 From: SenseiPrimexus Date: Sun, 15 Mar 2026 15:29:22 -0400 Subject: [PATCH 14/30] Match bit width in bext comparison --- test/zbs_tb.sv | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/zbs_tb.sv b/test/zbs_tb.sv index 00cc29b9..3b740edc 100644 --- a/test/zbs_tb.sv +++ b/test/zbs_tb.sv @@ -61,7 +61,7 @@ initial begin inst = 3'b011; #10; - expected = (reg1 >> reg2[4:0]) & 32'h1; + expected = {31'b0, reg1[reg2[4:0]]}; assert(out == expected) else $fatal("bext failed: expected %b got %b", expected, out); @@ -111,7 +111,7 @@ initial begin 3'b010: expected = reg1 ^ (32'h1 << reg2[4:0]); - 3'b011: expected = (reg1 >> reg2[4:0]) & 32'h1; + 3'b011: expected = {31'b0, reg1[reg2[4:0]]}; default: expected = 32'd0; From de0a360946d517cf10a6611f5a2d1ca0c147ef19 Mon Sep 17 00:00:00 2001 From: SenseiPrimexus Date: Sun, 15 Mar 2026 15:49:19 -0400 Subject: [PATCH 15/30] Fix: Resolve svlint style violations --- test/zbs_tb.sv | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/test/zbs_tb.sv b/test/zbs_tb.sv index 3b740edc..6ed9e2aa 100644 --- a/test/zbs_tb.sv +++ b/test/zbs_tb.sv @@ -11,9 +11,9 @@ logic [31:0] out; logic [31:0] expected; zbs uut ( - .reg1(reg1), - .reg2(reg2), - .inst(inst), + .reg1(reg1), + .reg2(reg2), + .inst(inst), .out(out) ); @@ -27,7 +27,7 @@ initial begin expected = reg1 & ~(32'h1 << reg2[4:0]); - assert(out == expected) + assert (out == expected) else $fatal("bclr failed: expected %b got %b", expected, out); @@ -39,7 +39,7 @@ initial begin expected = reg1 | (32'h1 << reg2[4:0]); - assert(out == expected) + assert (out == expected) else $fatal("bset failed: expected %b got %b", expected, out); @@ -51,7 +51,7 @@ initial begin expected = reg1 ^ (32'h1 << reg2[4:0]); - assert(out == expected) + assert (out == expected) else $fatal("binv failed: expected %b got %b", expected, out); @@ -63,7 +63,7 @@ initial begin expected = {31'b0, reg1[reg2[4:0]]}; - assert(out == expected) + assert (out == expected) else $fatal("bext failed: expected %b got %b", expected, out); // -------- Edge Cases --------- @@ -76,7 +76,7 @@ initial begin expected = reg1 & ~(32'h1 << reg2[4:0]); - assert(out == expected) + assert (out == expected) else $fatal("corner case bit0 failed"); @@ -88,13 +88,12 @@ initial begin expected = reg1 & ~(32'h1 << reg2[4:0]); - assert(out == expected) + assert (out == expected) else $fatal("corner case bit31 failed"); // ----------- Randomized Testing (Experimental) ----------- - repeat (1000) begin reg1 = $urandom; @@ -117,7 +116,7 @@ initial begin endcase - assert(out == expected) + assert (out == expected) else $fatal("random test failed: inst=%0d reg1=%h reg2=%d expected=%h got=%h", inst, reg1, reg2, expected, out); From 0894e45add9724a54f079f66cfc2dc8c882e42a1 Mon Sep 17 00:00:00 2001 From: Boris Date: Sun, 22 Mar 2026 17:33:48 +0000 Subject: [PATCH 16/30] fix svlint infractions --- test/zbs_tb.sv | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/test/zbs_tb.sv b/test/zbs_tb.sv index 6ed9e2aa..cfe9407f 100644 --- a/test/zbs_tb.sv +++ b/test/zbs_tb.sv @@ -10,11 +10,11 @@ logic [31:0] out; logic [31:0] expected; -zbs uut ( - .reg1(reg1), - .reg2(reg2), - .inst(inst), - .out(out) +zbs uut + ( .reg1 ( reg1 ) + , .reg2 ( reg2 ) + , .inst ( inst ) + , .out ( out ) ); initial begin @@ -93,7 +93,7 @@ initial begin // ----------- Randomized Testing (Experimental) ----------- - + repeat (1000) begin reg1 = $urandom; @@ -102,7 +102,7 @@ initial begin #1; - case(inst) + case (inst) 3'b000: expected = reg1 & ~(32'h1 << reg2[4:0]); @@ -116,9 +116,9 @@ initial begin endcase - assert (out == expected) - else $fatal("random test failed: inst=%0d reg1=%h reg2=%d expected=%h got=%h", - inst, reg1, reg2, expected, out); + assert (out == expected) else + $fatal("random test failed: inst=%0d reg1=%h reg2=%d expected=%h got=%h" + , inst, reg1, reg2, expected, out); end @@ -130,4 +130,4 @@ end `SETUP_VCD_DUMP(zbs_tb) -endmodule \ No newline at end of file +endmodule From cf2d643ec885fef421bba7dd841f4e87fa08ca46 Mon Sep 17 00:00:00 2001 From: SenseiPrimexus Date: Sun, 10 May 2026 14:16:27 -0400 Subject: [PATCH 17/30] Refactor zbs to use ALUM enum and Update testbench accordingly --- src/ext/b/zbs.sv | 10 +++++----- src/types.svh | 4 ++++ test/zbs_tb.sv | 24 ++++++++++++------------ 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/src/ext/b/zbs.sv b/src/ext/b/zbs.sv index e0d8c9fc..a9b94124 100644 --- a/src/ext/b/zbs.sv +++ b/src/ext/b/zbs.sv @@ -13,7 +13,7 @@ module zbs ( input data_t reg1 // rs1 operand , input data_t reg2 // rs2 or immediate (bit index source) - , input logic [1:0] inst // operation selector + , input alu_control_t inst // operation selector , output data_t out //result ); @@ -30,16 +30,16 @@ module zbs ( case (inst) // 00 : bclr / bclri → clear selected bit - 2'b00: out = reg1 & ~mask; + ALU_CONTROL_BCLR: out = reg1 & ~mask; // 01 : bset / bseti → set selected bit - 2'b01: out = reg1 | mask; + ALU_CONTROL_BSET: out = reg1 | mask; // 10 : binv / binvi → invert selected bit - 2'b10: out = reg1 ^ mask; + ALU_CONTROL_BINV: out = reg1 ^ mask; // 11 : bext / bexti → extract selected bit (to bit[0]) - 2'b11: out = (reg1 >> index) & data_t'(32'h1); + ALU_CONTROL_BEXT: out = (reg1 >> index) & data_t'(32'h1); // others → safe default default: out = '0; diff --git a/src/types.svh b/src/types.svh index 295e1d33..9c6e7882 100644 --- a/src/types.svh +++ b/src/types.svh @@ -34,6 +34,10 @@ typedef enum logic [3:0] , ALU_CONTROL_SRA = 4'b0111 , ALU_CONTROL_OR = 4'b1000 , ALU_CONTROL_AND = 4'b1001 + , ALU_CONTROL_BCLR = 4'b1010 + , ALU_CONTROL_BSET = 4'b1011 + , ALU_CONTROL_BINV = 4'b1100 + , ALU_CONTROL_BEXT = 4'b1101 } alu_control_t; // represents the possible input sources for the first operand of the ALU as selected by the Control diff --git a/test/zbs_tb.sv b/test/zbs_tb.sv index cfe9407f..09c0f753 100644 --- a/test/zbs_tb.sv +++ b/test/zbs_tb.sv @@ -5,7 +5,7 @@ module zbs_tb; logic [31:0] reg1; logic [31:0] reg2; -logic [2:0] inst; +alu_control_t inst; logic [31:0] out; logic [31:0] expected; @@ -22,7 +22,7 @@ initial begin // -------- bclr test -------- reg1 = 32'b1010; reg2 = 32'd1; // clear bit 1 - inst = 3'b000; + inst = ALU_CONTROL_BCLR; #10; expected = reg1 & ~(32'h1 << reg2[4:0]); @@ -34,7 +34,7 @@ initial begin // -------- bset test -------- reg1 = 32'b1110; reg2 = 32'd0; // set bit 0 - inst = 3'b001; + inst = ALU_CONTROL_BSET; #10; expected = reg1 | (32'h1 << reg2[4:0]); @@ -46,7 +46,7 @@ initial begin // -------- binv test -------- reg1 = 32'b1010; reg2 = 32'd1; - inst = 3'b010; + inst = ALU_CONTROL_BINV; #10; expected = reg1 ^ (32'h1 << reg2[4:0]); @@ -58,7 +58,7 @@ initial begin // -------- bext test -------- reg1 = 32'b1010; reg2 = 32'd3; - inst = 3'b011; + inst = ALU_CONTROL_BEXT; #10; expected = {31'b0, reg1[reg2[4:0]]}; @@ -71,7 +71,7 @@ initial begin // Bit 0 boundary reg1 = 32'hFFFFFFFF; reg2 = 32'd0; - inst = 3'b000; // bclr + inst = ALU_CONTROL_BCLR; // bclr #10; expected = reg1 & ~(32'h1 << reg2[4:0]); @@ -83,7 +83,7 @@ initial begin // Bit 31 boundary reg1 = 32'hFFFFFFFF; reg2 = 32'd31; - inst = 3'b000; // bclr + inst = ALU_CONTROL_BCLR; // bclr #10; expected = reg1 & ~(32'h1 << reg2[4:0]); @@ -98,19 +98,19 @@ initial begin reg1 = $urandom; reg2 = $urandom % 32; - inst = $urandom % 4; + inst = alu_control_t'((4'b1010) + ($urandom % 4)); #1; case (inst) - 3'b000: expected = reg1 & ~(32'h1 << reg2[4:0]); + ALU_CONTROL_BCLR: expected = reg1 & ~(32'h1 << reg2[4:0]); - 3'b001: expected = reg1 | (32'h1 << reg2[4:0]); + ALU_CONTROL_BSET: expected = reg1 | (32'h1 << reg2[4:0]); - 3'b010: expected = reg1 ^ (32'h1 << reg2[4:0]); + ALU_CONTROL_BINV: expected = reg1 ^ (32'h1 << reg2[4:0]); - 3'b011: expected = {31'b0, reg1[reg2[4:0]]}; + ALU_CONTROL_BEXT: expected = {31'b0, reg1[reg2[4:0]]}; default: expected = 32'd0; From aa712ce3c401598b2542b3f13e3c58017e5ad1f7 Mon Sep 17 00:00:00 2001 From: SenseiPrimexus Date: Sun, 10 May 2026 14:45:25 -0400 Subject: [PATCH 18/30] Fix: End of line svlint --- src/ext/b/zbs.sv | 4 ++-- test/zbs_tb.sv | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ext/b/zbs.sv b/src/ext/b/zbs.sv index a9b94124..fc738fc1 100644 --- a/src/ext/b/zbs.sv +++ b/src/ext/b/zbs.sv @@ -13,7 +13,7 @@ module zbs ( input data_t reg1 // rs1 operand , input data_t reg2 // rs2 or immediate (bit index source) - , input alu_control_t inst // operation selector + , input alu_control_t inst // operation selector , output data_t out //result ); @@ -46,4 +46,4 @@ module zbs ( endcase -endmodule \ No newline at end of file +endmodule diff --git a/test/zbs_tb.sv b/test/zbs_tb.sv index 09c0f753..47f8a91e 100644 --- a/test/zbs_tb.sv +++ b/test/zbs_tb.sv @@ -130,4 +130,5 @@ end `SETUP_VCD_DUMP(zbs_tb) + endmodule From 50cfcd4ac25719e2c1d232fed5a2472ae013716e Mon Sep 17 00:00:00 2001 From: SenseiPrimexus Date: Sun, 10 May 2026 14:59:44 -0400 Subject: [PATCH 19/30] fix svlint infractions --- src/ext/b/zbs.sv | 18 ++++++++--------- test/zbs_tb.sv | 50 ++++++++++++++++++++++++++++-------------------- 2 files changed, 37 insertions(+), 31 deletions(-) diff --git a/src/ext/b/zbs.sv b/src/ext/b/zbs.sv index fc738fc1..ee44b403 100644 --- a/src/ext/b/zbs.sv +++ b/src/ext/b/zbs.sv @@ -20,30 +20,28 @@ module zbs ( logic [4:0] index; data_t mask; - always_comb + always_comb begin index = reg2[4:0]; - - always_comb mask = data_t'(32'h1) << index; - always_comb - case (inst) + case ( inst ) - // 00 : bclr / bclri → clear selected bit + // bclr / bclri → clear selected bit ALU_CONTROL_BCLR: out = reg1 & ~mask; - // 01 : bset / bseti → set selected bit + // bset / bseti → set selected bit ALU_CONTROL_BSET: out = reg1 | mask; - // 10 : binv / binvi → invert selected bit + // binv / binvi → invert selected bit ALU_CONTROL_BINV: out = reg1 ^ mask; - // 11 : bext / bexti → extract selected bit (to bit[0]) + // bext / bexti → extract selected bit (to bit[0]) ALU_CONTROL_BEXT: out = (reg1 >> index) & data_t'(32'h1); - // others → safe default + // safe default default: out = '0; endcase + end endmodule diff --git a/test/zbs_tb.sv b/test/zbs_tb.sv index 47f8a91e..f36780d1 100644 --- a/test/zbs_tb.sv +++ b/test/zbs_tb.sv @@ -27,8 +27,8 @@ initial begin expected = reg1 & ~(32'h1 << reg2[4:0]); - assert (out == expected) - else $fatal("bclr failed: expected %b got %b", expected, out); + assert (out == expected) else + $fatal("bclr failed: expected %b got %b", expected, out); // -------- bset test -------- @@ -39,8 +39,8 @@ initial begin expected = reg1 | (32'h1 << reg2[4:0]); - assert (out == expected) - else $fatal("bset failed: expected %b got %b", expected, out); + assert (out == expected) else + $fatal("bset failed: expected %b got %b", expected, out); // -------- binv test -------- @@ -51,8 +51,8 @@ initial begin expected = reg1 ^ (32'h1 << reg2[4:0]); - assert (out == expected) - else $fatal("binv failed: expected %b got %b", expected, out); + assert (out == expected) else + $fatal("binv failed: expected %b got %b", expected, out); // -------- bext test -------- @@ -63,8 +63,8 @@ initial begin expected = {31'b0, reg1[reg2[4:0]]}; - assert (out == expected) - else $fatal("bext failed: expected %b got %b", expected, out); + assert (out == expected) else + $fatal("bext failed: expected %b got %b", expected, out); // -------- Edge Cases --------- @@ -76,8 +76,8 @@ initial begin expected = reg1 & ~(32'h1 << reg2[4:0]); - assert (out == expected) - else $fatal("corner case bit0 failed"); + assert (out == expected) else + $fatal("corner case bit0 failed"); // Bit 31 boundary @@ -88,29 +88,37 @@ initial begin expected = reg1 & ~(32'h1 << reg2[4:0]); - assert (out == expected) - else $fatal("corner case bit31 failed"); + assert (out == expected) else + $fatal("corner case bit31 failed"); // ----------- Randomized Testing (Experimental) ----------- repeat (1000) begin - reg1 = $urandom; - reg2 = $urandom % 32; - inst = alu_control_t'((4'b1010) + ($urandom % 4)); + reg1 = $urandom; + reg2 = $urandom % 32; - #1; + // pick a Zbs operation without arithmetic on enums to avoid width expansion + case ($urandom % 4) + 0: inst = ALU_CONTROL_BCLR; + 1: inst = ALU_CONTROL_BSET; + 2: inst = ALU_CONTROL_BINV; + 3: inst = ALU_CONTROL_BEXT; + default: inst = ALU_CONTROL_BCLR; + endcase - case (inst) + #1; - ALU_CONTROL_BCLR: expected = reg1 & ~(32'h1 << reg2[4:0]); + case ( inst ) - ALU_CONTROL_BSET: expected = reg1 | (32'h1 << reg2[4:0]); + ALU_CONTROL_BCLR: expected = reg1 & ~(32'h1 << reg2[4:0]); - ALU_CONTROL_BINV: expected = reg1 ^ (32'h1 << reg2[4:0]); + ALU_CONTROL_BSET: expected = reg1 | (32'h1 << reg2[4:0]); - ALU_CONTROL_BEXT: expected = {31'b0, reg1[reg2[4:0]]}; + ALU_CONTROL_BINV: expected = reg1 ^ (32'h1 << reg2[4:0]); + + ALU_CONTROL_BEXT: expected = {31'b0, reg1[reg2[4:0]]}; default: expected = 32'd0; From 7f292e1852da57deab296b55b989027c71100589 Mon Sep 17 00:00:00 2001 From: SenseiPrimexus Date: Sun, 10 May 2026 15:01:10 -0400 Subject: [PATCH 20/30] fix svlint infractions --- test/zbs_tb.sv | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/zbs_tb.sv b/test/zbs_tb.sv index f36780d1..b322a26a 100644 --- a/test/zbs_tb.sv +++ b/test/zbs_tb.sv @@ -39,8 +39,8 @@ initial begin expected = reg1 | (32'h1 << reg2[4:0]); - assert (out == expected) else - $fatal("bset failed: expected %b got %b", expected, out); + assert (out == expected) else + $fatal("bset failed: expected %b got %b", expected, out); // -------- binv test -------- From 53184be034121a9f5f46c7ca4e20f7afa18fa981 Mon Sep 17 00:00:00 2001 From: SenseiPrimexus Date: Mon, 1 Jun 2026 18:40:20 -0400 Subject: [PATCH 21/30] Refactor zbs module and update testbench formatting for clarity --- src/ext/b/zbs.sv | 4 ++-- test/zbs_tb.sv | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ext/b/zbs.sv b/src/ext/b/zbs.sv index ee44b403..b2b1be87 100644 --- a/src/ext/b/zbs.sv +++ b/src/ext/b/zbs.sv @@ -20,7 +20,7 @@ module zbs ( logic [4:0] index; data_t mask; - always_comb begin + always_comb index = reg2[4:0]; mask = data_t'(32'h1) << index; @@ -42,6 +42,6 @@ module zbs ( default: out = '0; endcase - end + endmodule diff --git a/test/zbs_tb.sv b/test/zbs_tb.sv index b322a26a..f36780d1 100644 --- a/test/zbs_tb.sv +++ b/test/zbs_tb.sv @@ -39,8 +39,8 @@ initial begin expected = reg1 | (32'h1 << reg2[4:0]); - assert (out == expected) else - $fatal("bset failed: expected %b got %b", expected, out); + assert (out == expected) else + $fatal("bset failed: expected %b got %b", expected, out); // -------- binv test -------- From 33c44a9ad8ae01e5d07246bee9b1a3523d4e030b Mon Sep 17 00:00:00 2001 From: SenseiPrimexus Date: Tue, 21 Jul 2026 23:19:29 -0400 Subject: [PATCH 22/30] Include Zbs ALU decoder using the current B extension structure and Fix small lint issues --- src/ALU_ALUdecoder/ALU.sv | 6 +- src/Instruction_Decode/Instruction_Decode.sv | 30 +++--- src/ext/b/decoder.sv | 48 ++++++++- src/ext/b/types.svh | 4 + src/ext/b/zbs.sv | 4 +- test/zbs_decoder_tb.sv | 108 +++++++++++++++++++ test/zbs_tb.sv | 6 +- 7 files changed, 183 insertions(+), 23 deletions(-) create mode 100644 test/zbs_decoder_tb.sv diff --git a/src/ALU_ALUdecoder/ALU.sv b/src/ALU_ALUdecoder/ALU.sv index c24d3da7..e7e88e70 100644 --- a/src/ALU_ALUdecoder/ALU.sv +++ b/src/ALU_ALUdecoder/ALU.sv @@ -20,9 +20,13 @@ always_comb ALU_CONTROL_SRA: out = $signed(a) >>> b[4:0]; ALU_CONTROL_OR: out = a | b; ALU_CONTROL_AND: out = a & b; + ALU_CONTROL_BCLR: out = a & ~(data_t'(32'd1) << b[4:0]); + ALU_CONTROL_BSET: out = a | (data_t'(32'd1) << b[4:0]); + ALU_CONTROL_BINV: out = a ^ (data_t'(32'd1) << b[4:0]); + ALU_CONTROL_BEXT: out = (a >> b[4:0]) & data_t'(32'd1); default: out = 32'b0; endcase assign zeroE = (out == 0); -endmodule \ No newline at end of file +endmodule diff --git a/src/Instruction_Decode/Instruction_Decode.sv b/src/Instruction_Decode/Instruction_Decode.sv index 734b1e5e..83638a24 100644 --- a/src/Instruction_Decode/Instruction_Decode.sv +++ b/src/Instruction_Decode/Instruction_Decode.sv @@ -14,17 +14,15 @@ module Instruction_Decode ); alu_op_t alu_op; - // reg [2:0] funct3; - // reg [6:0] funct7; - wire [3:0] state; + alu_control_t base_alu_control; +`ifdef UTOSS_RISCV_ENABLE_B_EXT + logic [3:0] ext_b_alu_control; +`endif assign opcode = instr[6:0]; //combinational logic for extracting funct3 and funct7[5] for ALU Decoder input - reg [2:0] default_funct3; - reg [6:0] default_funct7; - always @(*) begin funct3 = 3'b000; @@ -131,21 +129,21 @@ module Instruction_Decode ( .funct3(funct3) , .funct7(funct7) , .alu_op(alu_op) - , .alu_control(ALUControl) + , .alu_control(base_alu_control) ); `ifdef UTOSS_RISCV_ENABLE_B_EXT - - ext__b__types::b_alu_control_t b_alu_control; - - ext__b__decoder u_ext__b__decoder - ( .funct3 ( funct3 ) - , .funct7 ( funct7 ) - , .opcode ( opcode ) - , .rd ( rd ) - , .b_alu_control ( b_alu_control ) + ext__b__decoder instanceBExtDec + ( .funct3 ( funct3 ) + , .funct7 ( funct7 ) + , .opcode ( opcode ) + , .rd ( rd ) + , .b_alu_control ( ext_b_alu_control ) ); + assign ALUControl = (ext_b_alu_control != 4'b0000) ? ext_b_alu_control : base_alu_control; +`else + assign ALUControl = base_alu_control; `endif endmodule diff --git a/src/ext/b/decoder.sv b/src/ext/b/decoder.sv index f6965702..c6b89267 100644 --- a/src/ext/b/decoder.sv +++ b/src/ext/b/decoder.sv @@ -12,8 +12,13 @@ module ext__b__decoder localparam bit [6:0] FUNCT7_ZBA = 7'b0010000; localparam bit [6:0] FUNCT7_ZBB = 7'b0100000; + localparam bit [6:0] FUNCT7_ZBS_BSET = 7'b0010100; + localparam bit [6:0] FUNCT7_ZBS_BCLR = 7'b0100100; + localparam bit [6:0] FUNCT7_ZBS_BINV = 7'b0110100; + + always_comb begin + b_alu_control = B_ALU_CTRL__NONE; - always_comb case (opcode) 7'b0110011: case (funct7) @@ -33,12 +38,51 @@ module ext__b__decoder default: b_alu_control = B_ALU_CTRL__NONE; endcase - // TODO: Implement zbs into ALU decoder, also confirm what zbb instructions are being implemented. + FUNCT7_ZBS_BSET: + if (funct3 == 3'b001) begin + b_alu_control = B_ALU_CTRL__BSET; + end + + FUNCT7_ZBS_BCLR: + case (funct3) + 3'b001: b_alu_control = B_ALU_CTRL__BCLR; + 3'b101: b_alu_control = B_ALU_CTRL__BEXT; + default: b_alu_control = B_ALU_CTRL__NONE; + endcase + + FUNCT7_ZBS_BINV: + if (funct3 == 3'b001) begin + b_alu_control = B_ALU_CTRL__BINV; + end + default: b_alu_control = B_ALU_CTRL__NONE; endcase + 7'b0010011: + case (funct7) + FUNCT7_ZBS_BSET: + if (funct3 == 3'b001) begin + b_alu_control = B_ALU_CTRL__BSET; + end + + FUNCT7_ZBS_BCLR: + case (funct3) + 3'b001: b_alu_control = B_ALU_CTRL__BCLR; + 3'b101: b_alu_control = B_ALU_CTRL__BEXT; + default: b_alu_control = B_ALU_CTRL__NONE; + endcase + + FUNCT7_ZBS_BINV: + if (funct3 == 3'b001) begin + b_alu_control = B_ALU_CTRL__BINV; + end + + default: b_alu_control = B_ALU_CTRL__NONE; + endcase + default: b_alu_control = B_ALU_CTRL__NONE; endcase + end endmodule diff --git a/src/ext/b/types.svh b/src/ext/b/types.svh index 86f8ec4e..5adf82ec 100644 --- a/src/ext/b/types.svh +++ b/src/ext/b/types.svh @@ -11,6 +11,10 @@ package ext__b__types; , B_ALU_CTRL__ANDN = 4'b0100 , B_ALU_CTRL__ORN = 4'b0101 , B_ALU_CTRL__XNOR = 4'b0110 + , B_ALU_CTRL__BCLR = 4'b1010 + , B_ALU_CTRL__BSET = 4'b1011 + , B_ALU_CTRL__BINV = 4'b1100 + , B_ALU_CTRL__BEXT = 4'b1101 } b_alu_control_t; endpackage; diff --git a/src/ext/b/zbs.sv b/src/ext/b/zbs.sv index b2b1be87..ba8f39e0 100644 --- a/src/ext/b/zbs.sv +++ b/src/ext/b/zbs.sv @@ -20,9 +20,10 @@ module zbs ( logic [4:0] index; data_t mask; - always_comb + always_comb begin index = reg2[4:0]; mask = data_t'(32'h1) << index; + out = '0; case ( inst ) @@ -42,6 +43,7 @@ module zbs ( default: out = '0; endcase + end endmodule diff --git a/test/zbs_decoder_tb.sv b/test/zbs_decoder_tb.sv new file mode 100644 index 00000000..ac31af72 --- /dev/null +++ b/test/zbs_decoder_tb.sv @@ -0,0 +1,108 @@ +`timescale 1ns/1ns +`include "src/types.svh" +`include "test/utils.svh" + +module zbs_decoder_tb; + + logic [31:0] instr; + opcode_t opcode; + logic [3:0] alu_control; + imm_t imm_ext; + logic [2:0] funct3; + logic [6:0] funct7; + logic [4:0] rd; + logic [4:0] rs1; + logic [4:0] rs2; + + function automatic logic [31:0] make_r_zbs + ( input logic [6:0] funct7_i + , input logic [2:0] funct3_i + , input logic [4:0] rs2_i + , input logic [4:0] rs1_i + , input logic [4:0] rd_i + ); + return {funct7_i, rs2_i, rs1_i, funct3_i, rd_i, 7'b0110011}; + endfunction + + function automatic logic [31:0] make_i_zbs + ( input logic [6:0] funct7_i + , input logic [4:0] shamt_i + , input logic [4:0] rs1_i + , input logic [4:0] rd_i + , input logic [2:0] funct3_i + ); + return {funct7_i, shamt_i, rs1_i, funct3_i, rd_i, 7'b0010011}; + endfunction + + Instruction_Decode uut + ( .instr ( instr ) + , .opcode ( opcode ) + , .ALUControl ( alu_control ) + , .imm_ext ( imm_ext ) + , .funct3 ( funct3 ) + , .funct7 ( funct7 ) + , .rd ( rd ) + , .rs1 ( rs1 ) + , .rs2 ( rs2 ) + ); + + initial begin + instr = 32'd0; + #1; + + instr = 32'h00000013; // addi x0, x0, 0 + #1; + assert (alu_control == ALU_CONTROL_ADD) else + $fatal(1, "base decode sanity check failed: got %0h", alu_control); + +`ifdef UTOSS_RISCV_ENABLE_B_EXT + instr = make_r_zbs(7'b0010100, 3'b001, 5'd3, 5'd2, 5'd1); // bset + #1; + assert (alu_control == ALU_CONTROL_BSET) else + $fatal(1, "bset decode failed: got %0h", alu_control); + + instr = make_r_zbs(7'b0100100, 3'b001, 5'd3, 5'd2, 5'd1); // bclr + #1; + assert (alu_control == ALU_CONTROL_BCLR) else + $fatal(1, "bclr decode failed: got %0h", alu_control); + + instr = make_r_zbs(7'b0110100, 3'b001, 5'd3, 5'd2, 5'd1); // binv + #1; + assert (alu_control == ALU_CONTROL_BINV) else + $fatal(1, "binv decode failed: got %0h", alu_control); + + instr = make_r_zbs(7'b0100100, 3'b101, 5'd3, 5'd2, 5'd1); // bext + #1; + assert (alu_control == ALU_CONTROL_BEXT) else + $fatal(1, "bext decode failed: got %0h", alu_control); + + instr = make_i_zbs(7'b0010100, 5'd3, 5'd2, 5'd1, 3'b001); // bseti + #1; + assert (alu_control == ALU_CONTROL_BSET) else + $fatal(1, "bseti decode failed: got %0h", alu_control); + + instr = make_i_zbs(7'b0100100, 5'd3, 5'd2, 5'd1, 3'b001); // bclri + #1; + assert (alu_control == ALU_CONTROL_BCLR) else + $fatal(1, "bclri decode failed: got %0h", alu_control); + + instr = make_i_zbs(7'b0110100, 5'd3, 5'd2, 5'd1, 3'b001); // binvi + #1; + assert (alu_control == ALU_CONTROL_BINV) else + $fatal(1, "binvi decode failed: got %0h", alu_control); + + instr = make_i_zbs(7'b0100100, 5'd3, 5'd2, 5'd1, 3'b101); // bexti + #1; + assert (alu_control == ALU_CONTROL_BEXT) else + $fatal(1, "bexti decode failed: got %0h", alu_control); +`else + $display("B extension is disabled; Zbs integration checks were skipped."); +`endif + + $display("Zbs decode tests passed!"); + $finish; + end + + `SETUP_VCD_DUMP(zbs_decoder_tb) + +endmodule diff --git a/test/zbs_tb.sv b/test/zbs_tb.sv index f36780d1..2e31e1b8 100644 --- a/test/zbs_tb.sv +++ b/test/zbs_tb.sv @@ -64,7 +64,7 @@ initial begin expected = {31'b0, reg1[reg2[4:0]]}; assert (out == expected) else - $fatal("bext failed: expected %b got %b", expected, out); + $fatal("bext failed: expected %b got %b", expected, out); // -------- Edge Cases --------- @@ -77,7 +77,7 @@ initial begin expected = reg1 & ~(32'h1 << reg2[4:0]); assert (out == expected) else - $fatal("corner case bit0 failed"); + $fatal("corner case bit0 failed"); // Bit 31 boundary @@ -89,7 +89,7 @@ initial begin expected = reg1 & ~(32'h1 << reg2[4:0]); assert (out == expected) else - $fatal("corner case bit31 failed"); + $fatal("corner case bit31 failed"); // ----------- Randomized Testing (Experimental) ----------- From 2672eaac5255ae6eb216b9fec5ffa82f442ffa52 Mon Sep 17 00:00:00 2001 From: SenseiPrimexus Date: Tue, 21 Jul 2026 23:39:26 -0400 Subject: [PATCH 23/30] Rename ZBS function identifiers to ZBB in decoder module for consistency --- src/ext/b/decoder.sv | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/ext/b/decoder.sv b/src/ext/b/decoder.sv index b0d26c74..05cff5a0 100644 --- a/src/ext/b/decoder.sv +++ b/src/ext/b/decoder.sv @@ -23,9 +23,9 @@ module ext__b__decoder localparam bit [6:0] FUNCT7_ZBB_ROTATE = 7'b0110000; localparam bit [6:0] FUNCT7_ZBB_ORCB = 7'b0010100; localparam bit [6:0] FUNCT7_ZBB_REV8 = 7'b0110100; - localparam bit [6:0] FUNCT7_ZBS_BSET = 7'b0010100; - localparam bit [6:0] FUNCT7_ZBS_BCLR = 7'b0100100; - localparam bit [6:0] FUNCT7_ZBS_BINV = 7'b0110100; + localparam bit [6:0] FUNCT7_ZBB__BSET = 7'b0010100; + localparam bit [6:0] FUNCT7_ZBB__BCLR = 7'b0100100; + localparam bit [6:0] FUNCT7_ZBB__BINV = 7'b0110100; always_comb begin b_alu_control = B_ALU_CTRL__NONE; @@ -75,19 +75,19 @@ module ext__b__decoder default: b_alu_control = B_ALU_CTRL__NONE; endcase - FUNCT7_ZBS_BSET: + FUNCT7_ZBB__BSET: if (funct3 == 3'b001) begin b_alu_control = B_ALU_CTRL__BSET; end - FUNCT7_ZBS_BCLR: + FUNCT7_ZBB__BCLR: case (funct3) 3'b001: b_alu_control = B_ALU_CTRL__BCLR; 3'b101: b_alu_control = B_ALU_CTRL__BEXT; default: b_alu_control = B_ALU_CTRL__NONE; endcase - FUNCT7_ZBS_BINV: + FUNCT7_ZBB__BINV: if (funct3 == 3'b001) begin b_alu_control = B_ALU_CTRL__BINV; end @@ -132,19 +132,19 @@ module ext__b__decoder default: b_alu_control = B_ALU_CTRL__NONE; endcase - FUNCT7_ZBS_BSET: + FUNCT7_ZBB__BSET: if (funct3 == 3'b001) begin b_alu_control = B_ALU_CTRL__BSET; end - FUNCT7_ZBS_BCLR: + FUNCT7_ZBB__BCLR: case (funct3) 3'b001: b_alu_control = B_ALU_CTRL__BCLR; 3'b101: b_alu_control = B_ALU_CTRL__BEXT; default: b_alu_control = B_ALU_CTRL__NONE; endcase - FUNCT7_ZBS_BINV: + FUNCT7_ZBB__BINV: if (funct3 == 3'b001) begin b_alu_control = B_ALU_CTRL__BINV; end From 34a6019ad92e3ded6b942fae08de8c447c7a2f8e Mon Sep 17 00:00:00 2001 From: SenseiPrimexus Date: Tue, 21 Jul 2026 23:44:03 -0400 Subject: [PATCH 24/30] Update zbs to match zbb and zba style and Fix lint issues --- src/ext/b/zbs.sv | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/src/ext/b/zbs.sv b/src/ext/b/zbs.sv index 4e533662..3e762112 100644 --- a/src/ext/b/zbs.sv +++ b/src/ext/b/zbs.sv @@ -11,21 +11,13 @@ module zbs import ext__b__types::*; - logic [4:0] index; - data_t mask; - - always_comb begin - index = reg2[4:0]; - mask = data_t'(32'h1) << index; - out = '0; - + always_comb case (b_alu_control) - B_ALU_CTRL__BCLR: out = reg1 & ~mask; - B_ALU_CTRL__BSET: out = reg1 | mask; - B_ALU_CTRL__BINV: out = reg1 ^ mask; - B_ALU_CTRL__BEXT: out = (reg1 >> index) & data_t'(32'h1); + B_ALU_CTRL__BCLR: out = reg1 & ~(data_t'(32'h1) << reg2[4:0]); + B_ALU_CTRL__BSET: out = reg1 | (data_t'(32'h1) << reg2[4:0]); + B_ALU_CTRL__BINV: out = reg1 ^ (data_t'(32'h1) << reg2[4:0]); + B_ALU_CTRL__BEXT: out = (reg1 >> reg2[4:0]) & data_t'(32'h1); default: out = '0; endcase - end endmodule From 2572551a473596c6d9c98ec1aabc75cd15704416 Mon Sep 17 00:00:00 2001 From: SenseiPrimexus Date: Tue, 21 Jul 2026 23:50:56 -0400 Subject: [PATCH 25/30] Removed the zbs ALU usages to fix undefined variable --- src/modules/ALU_ALUdecoder/ALU.sv | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/modules/ALU_ALUdecoder/ALU.sv b/src/modules/ALU_ALUdecoder/ALU.sv index 358fc3de..e41bf328 100644 --- a/src/modules/ALU_ALUdecoder/ALU.sv +++ b/src/modules/ALU_ALUdecoder/ALU.sv @@ -22,10 +22,6 @@ always_comb ALU_CONTROL_SRA: out = $signed(a) >>> b[4:0]; ALU_CONTROL_OR: out = a | b; ALU_CONTROL_AND: out = a & b; - ALU_CONTROL_BCLR: out = a & ~(data_t'(32'd1) << b[4:0]); - ALU_CONTROL_BSET: out = a | (data_t'(32'd1) << b[4:0]); - ALU_CONTROL_BINV: out = a ^ (data_t'(32'd1) << b[4:0]); - ALU_CONTROL_BEXT: out = (a >> b[4:0]) & data_t'(32'd1); default: out = 32'b0; endcase From fcec24e0c4a0d13ba0e5b85707da4196ccaff347 Mon Sep 17 00:00:00 2001 From: SenseiPrimexus Date: Wed, 22 Jul 2026 00:23:27 -0400 Subject: [PATCH 26/30] Refactor always_comb blocks in Instruction_Decode module for svlint check --- .../Instruction_Decode/Instruction_Decode.sv | 82 ++++++++----------- 1 file changed, 35 insertions(+), 47 deletions(-) diff --git a/src/modules/Instruction_Decode/Instruction_Decode.sv b/src/modules/Instruction_Decode/Instruction_Decode.sv index 6c3a044a..f1a64eeb 100644 --- a/src/modules/Instruction_Decode/Instruction_Decode.sv +++ b/src/modules/Instruction_Decode/Instruction_Decode.sv @@ -23,27 +23,21 @@ module Instruction_Decode assign opcode = opcode_t'(instr[6:0]); // combinational logic for extracting funct3 and funct7 for ALU decoder input - always_comb begin - funct3 = 3'b000; - funct7 = 7'b0; - + always_comb case (opcode) - OPCODE_OP, OPCODE_OP_IMM: begin - funct3 = instr[14:12]; - funct7 = instr[31:25]; - end - - OPCODE_LOAD, OPCODE_STORE, OPCODE_BRANCH: begin - funct3 = instr[14:12]; - end + OPCODE_OP, OPCODE_OP_IMM: funct3 = instr[14:12]; + OPCODE_LOAD, OPCODE_STORE, OPCODE_BRANCH: funct3 = instr[14:12]; + default: funct3 = 3'b000; + endcase - default: begin - end + always_comb + case (opcode) + OPCODE_OP, OPCODE_OP_IMM: funct7 = instr[31:25]; + default: funct7 = 7'b0; endcase - end // determine ALU op based on opcode - always_comb begin + always_comb case (opcode) OPCODE_OP: alu_op = ALU_OP__REGISTER_OPERATION; OPCODE_LOAD: alu_op = ALU_OP__ADD; @@ -55,43 +49,38 @@ module Instruction_Decode OPCODE_MISC_MEM: alu_op = ALU_OP__UNSET; default: alu_op = ALU_OP__UNSET; endcase - end - - // extract rd, rs1, rs2 from 32-bit instruction - always_comb begin - rd = 5'b00000; - rs1 = 5'b00000; - rs2 = 5'b00000; + always_comb case (opcode) - OPCODE_OP: begin - rd = instr[11:7]; - rs1 = instr[19:15]; - rs2 = instr[24:20]; - end - - OPCODE_OP_IMM, OPCODE_LOAD, OPCODE_JALR: begin - rd = instr[11:7]; - rs1 = instr[19:15]; - rs2 = instr[24:20]; - end - - OPCODE_STORE, OPCODE_BRANCH: begin - rs1 = instr[19:15]; - rs2 = instr[24:20]; - end + OPCODE_OP, + OPCODE_OP_IMM, + OPCODE_LOAD, + OPCODE_JALR, + OPCODE_AUIPC, + OPCODE_LUI, + OPCODE_JAL: rd = instr[11:7]; + default: rd = 5'b00000; + endcase - OPCODE_AUIPC, OPCODE_LUI, OPCODE_JAL: begin - rd = instr[11:7]; - end + always_comb + case (opcode) + OPCODE_OP: rs1 = instr[19:15]; + OPCODE_OP_IMM, OPCODE_LOAD, OPCODE_JALR: rs1 = instr[19:15]; + OPCODE_STORE, OPCODE_BRANCH: rs1 = instr[19:15]; + default: rs1 = 5'b00000; + endcase - default: begin - end + always_comb + case (opcode) + OPCODE_OP: rs2 = instr[24:20]; + OPCODE_OP_IMM, OPCODE_LOAD, OPCODE_JALR: rs2 = instr[24:20]; + OPCODE_STORE, OPCODE_BRANCH: rs2 = instr[24:20]; + default: rs2 = 5'b00000; endcase - end + // immediate decode - always_comb begin + always_comb case (opcode) OPCODE_OP_IMM: imm_ext = {{20{instr[31]}}, instr[31:20]}; OPCODE_LOAD: imm_ext = {{20{instr[31]}}, instr[31:20]}; @@ -103,7 +92,6 @@ module Instruction_Decode OPCODE_LUI: imm_ext = {instr[31:12], 12'h000}; default: imm_ext = 32'b0; endcase - end ALUdecoder instanceALUDec ( .funct3 ( funct3 ) From 7556100140ffa9f3c34d6a0791572c95662684a5 Mon Sep 17 00:00:00 2001 From: SenseiPrimexus Date: Wed, 22 Jul 2026 01:10:44 -0400 Subject: [PATCH 27/30] Fix lint issues --- src/ext/b/decoder.sv | 104 +++++++----------- .../Instruction_Decode/Instruction_Decode.sv | 14 +-- 2 files changed, 48 insertions(+), 70 deletions(-) diff --git a/src/ext/b/decoder.sv b/src/ext/b/decoder.sv index 05cff5a0..b3164a4c 100644 --- a/src/ext/b/decoder.sv +++ b/src/ext/b/decoder.sv @@ -27,9 +27,7 @@ module ext__b__decoder localparam bit [6:0] FUNCT7_ZBB__BCLR = 7'b0100100; localparam bit [6:0] FUNCT7_ZBB__BINV = 7'b0110100; - always_comb begin - b_alu_control = B_ALU_CTRL__NONE; - + always_comb case (opcode) 7'b0110011: case (funct7) @@ -76,9 +74,8 @@ module ext__b__decoder endcase FUNCT7_ZBB__BSET: - if (funct3 == 3'b001) begin + if (funct3 == 3'b001) b_alu_control = B_ALU_CTRL__BSET; - end FUNCT7_ZBB__BCLR: case (funct3) @@ -88,72 +85,53 @@ module ext__b__decoder endcase FUNCT7_ZBB__BINV: - if (funct3 == 3'b001) begin + if (funct3 == 3'b001) b_alu_control = B_ALU_CTRL__BINV; - end default: b_alu_control = B_ALU_CTRL__NONE; endcase 7'b0010011: - case (funct7) - 7'b0110000: - case (funct3) - 3'b001: - case (rs2) - 5'b00100: b_alu_control = B_ALU_CTRL__SEXTB; - 5'b00101: b_alu_control = B_ALU_CTRL__SEXTH; - 5'b00000: b_alu_control = B_ALU_CTRL__CLZ; - 5'b00001: b_alu_control = B_ALU_CTRL__CTZ; - 5'b00010: b_alu_control = B_ALU_CTRL__CPOP; - default: b_alu_control = B_ALU_CTRL__NONE; - endcase - 3'b101: b_alu_control = B_ALU_CTRL__RORI; - default: b_alu_control = B_ALU_CTRL__NONE; - endcase - - FUNCT7_ZBB_ORCB: - case (funct3) - 3'b101: - case (rs2) - 5'b00111: b_alu_control = B_ALU_CTRL__ORCB; - default: b_alu_control = B_ALU_CTRL__NONE; - endcase - default: b_alu_control = B_ALU_CTRL__NONE; - endcase - - FUNCT7_ZBB_REV8: - case (funct3) - 3'b101: - case (rs2) - 5'b11000: b_alu_control = B_ALU_CTRL__REV8; - default: b_alu_control = B_ALU_CTRL__NONE; - endcase - default: b_alu_control = B_ALU_CTRL__NONE; - endcase - - FUNCT7_ZBB__BSET: - if (funct3 == 3'b001) begin - b_alu_control = B_ALU_CTRL__BSET; - end - - FUNCT7_ZBB__BCLR: - case (funct3) - 3'b001: b_alu_control = B_ALU_CTRL__BCLR; - 3'b101: b_alu_control = B_ALU_CTRL__BEXT; - default: b_alu_control = B_ALU_CTRL__NONE; - endcase - - FUNCT7_ZBB__BINV: - if (funct3 == 3'b001) begin - b_alu_control = B_ALU_CTRL__BINV; - end - - default: b_alu_control = B_ALU_CTRL__NONE; - endcase + if (funct7 == 7'b0110000) begin + case (funct3) + 3'b001: + case (rs2) + 5'b00100: b_alu_control = B_ALU_CTRL__SEXTB; + 5'b00101: b_alu_control = B_ALU_CTRL__SEXTH; + 5'b00000: b_alu_control = B_ALU_CTRL__CLZ; + 5'b00001: b_alu_control = B_ALU_CTRL__CTZ; + 5'b00010: b_alu_control = B_ALU_CTRL__CPOP; + default: b_alu_control = B_ALU_CTRL__NONE; + endcase + 3'b101: b_alu_control = B_ALU_CTRL__RORI; + default: b_alu_control = B_ALU_CTRL__NONE; + endcase + end + else if (funct7 == FUNCT7_ZBB_ORCB) begin + case (funct3) + 3'b101: + case (rs2) + 5'b00111: b_alu_control = B_ALU_CTRL__ORCB; + default: b_alu_control = B_ALU_CTRL__NONE; + endcase + default: b_alu_control = B_ALU_CTRL__NONE; + endcase + end + else if (funct7 == FUNCT7_ZBB_REV8) begin + case (funct3) + 3'b101: + case (rs2) + 5'b11000: b_alu_control = B_ALU_CTRL__REV8; + default: b_alu_control = B_ALU_CTRL__NONE; + endcase + default: b_alu_control = B_ALU_CTRL__NONE; + endcase + end + else begin + b_alu_control = B_ALU_CTRL__NONE; + end default: b_alu_control = B_ALU_CTRL__NONE; endcase - end endmodule diff --git a/src/modules/Instruction_Decode/Instruction_Decode.sv b/src/modules/Instruction_Decode/Instruction_Decode.sv index f1a64eeb..6089cf0b 100644 --- a/src/modules/Instruction_Decode/Instruction_Decode.sv +++ b/src/modules/Instruction_Decode/Instruction_Decode.sv @@ -52,13 +52,13 @@ module Instruction_Decode always_comb case (opcode) - OPCODE_OP, - OPCODE_OP_IMM, - OPCODE_LOAD, - OPCODE_JALR, - OPCODE_AUIPC, - OPCODE_LUI, - OPCODE_JAL: rd = instr[11:7]; + OPCODE_OP + , OPCODE_OP_IMM + , OPCODE_LOAD + , OPCODE_JALR + , OPCODE_AUIPC + , OPCODE_LUI + , OPCODE_JAL: rd = instr[11:7]; default: rd = 5'b00000; endcase From 17a966450698c8d4f5f2add0ea2fd69934e060ee Mon Sep 17 00:00:00 2001 From: SenseiPrimexus Date: Wed, 22 Jul 2026 01:28:43 -0400 Subject: [PATCH 28/30] Introduce more test cases to zbs_decoder and fix lint issues --- src/ext/b/decoder.sv | 80 ++++++++++++++++++++++-------------------- test/zbs_decoder_tb.sv | 44 ++++++++++++++++++----- 2 files changed, 77 insertions(+), 47 deletions(-) diff --git a/src/ext/b/decoder.sv b/src/ext/b/decoder.sv index b3164a4c..d8eeddc5 100644 --- a/src/ext/b/decoder.sv +++ b/src/ext/b/decoder.sv @@ -76,6 +76,8 @@ module ext__b__decoder FUNCT7_ZBB__BSET: if (funct3 == 3'b001) b_alu_control = B_ALU_CTRL__BSET; + else + b_alu_control = B_ALU_CTRL__NONE; FUNCT7_ZBB__BCLR: case (funct3) @@ -87,49 +89,51 @@ module ext__b__decoder FUNCT7_ZBB__BINV: if (funct3 == 3'b001) b_alu_control = B_ALU_CTRL__BINV; + else + b_alu_control = B_ALU_CTRL__NONE; default: b_alu_control = B_ALU_CTRL__NONE; endcase 7'b0010011: - if (funct7 == 7'b0110000) begin - case (funct3) - 3'b001: - case (rs2) - 5'b00100: b_alu_control = B_ALU_CTRL__SEXTB; - 5'b00101: b_alu_control = B_ALU_CTRL__SEXTH; - 5'b00000: b_alu_control = B_ALU_CTRL__CLZ; - 5'b00001: b_alu_control = B_ALU_CTRL__CTZ; - 5'b00010: b_alu_control = B_ALU_CTRL__CPOP; - default: b_alu_control = B_ALU_CTRL__NONE; - endcase - 3'b101: b_alu_control = B_ALU_CTRL__RORI; - default: b_alu_control = B_ALU_CTRL__NONE; - endcase - end - else if (funct7 == FUNCT7_ZBB_ORCB) begin - case (funct3) - 3'b101: - case (rs2) - 5'b00111: b_alu_control = B_ALU_CTRL__ORCB; - default: b_alu_control = B_ALU_CTRL__NONE; - endcase - default: b_alu_control = B_ALU_CTRL__NONE; - endcase - end - else if (funct7 == FUNCT7_ZBB_REV8) begin - case (funct3) - 3'b101: - case (rs2) - 5'b11000: b_alu_control = B_ALU_CTRL__REV8; - default: b_alu_control = B_ALU_CTRL__NONE; - endcase - default: b_alu_control = B_ALU_CTRL__NONE; - endcase - end - else begin - b_alu_control = B_ALU_CTRL__NONE; - end + case (funct7) + 7'b0110000: + case (funct3) + 3'b001: + case (rs2) + 5'b00100: b_alu_control = B_ALU_CTRL__SEXTB; + 5'b00101: b_alu_control = B_ALU_CTRL__SEXTH; + 5'b00000: b_alu_control = B_ALU_CTRL__CLZ; + 5'b00001: b_alu_control = B_ALU_CTRL__CTZ; + 5'b00010: b_alu_control = B_ALU_CTRL__CPOP; + default: b_alu_control = B_ALU_CTRL__NONE; + endcase + 3'b101: b_alu_control = B_ALU_CTRL__RORI; + default: b_alu_control = B_ALU_CTRL__NONE; + endcase + + FUNCT7_ZBB_ORCB: + case (funct3) + 3'b101: + case (rs2) + 5'b00111: b_alu_control = B_ALU_CTRL__ORCB; + default: b_alu_control = B_ALU_CTRL__NONE; + endcase + default: b_alu_control = B_ALU_CTRL__NONE; + endcase + + FUNCT7_ZBB_REV8: + case (funct3) + 3'b101: + case (rs2) + 5'b11000: b_alu_control = B_ALU_CTRL__REV8; + default: b_alu_control = B_ALU_CTRL__NONE; + endcase + default: b_alu_control = B_ALU_CTRL__NONE; + endcase + + default: b_alu_control = B_ALU_CTRL__NONE; + endcase default: b_alu_control = B_ALU_CTRL__NONE; endcase diff --git a/test/zbs_decoder_tb.sv b/test/zbs_decoder_tb.sv index 258b1419..6dca6435 100644 --- a/test/zbs_decoder_tb.sv +++ b/test/zbs_decoder_tb.sv @@ -8,14 +8,16 @@ module zbs_decoder_tb; import ext__b__types::*; logic [31:0] instr; - wire opcode_t opcode; - wire [3:0] alu_control; - wire imm_t imm_ext; - wire [2:0] funct3; - wire [4:0] rd; - wire [4:0] rs1; - wire [4:0] rs2; - wire b_alu_control_t b_alu_control; + logic [3:0] alu_control; + opcode_t opcode; + imm_t imm_ext; + logic [2:0] funct3; + logic [4:0] rd; + logic [4:0] rs1; + logic [4:0] rs2; +`ifdef UTOSS_RISCV_ENABLE_B_EXT + b_alu_control_t b_alu_control; +`endif function automatic logic [31:0] make_r_zbs ( input logic [6:0] funct7_i @@ -39,8 +41,8 @@ module zbs_decoder_tb; Instruction_Decode uut ( .instr ( instr ) - , .opcode ( opcode ) , .ALUControl ( alu_control ) + , .opcode ( opcode ) , .imm_ext ( imm_ext ) , .funct3 ( funct3 ) , .rd ( rd ) @@ -57,12 +59,34 @@ module zbs_decoder_tb; instr = 32'h00000013; // addi x0, x0, 0 #1; + assert (opcode == OPCODE_OP_IMM) else + $fatal(1, "opcode decode failed for addi: got %0h", opcode); assert (alu_control == ALU_CONTROL_ADD) else $fatal(1, "base decode sanity check failed: got %0h", alu_control); + assert (imm_ext == 32'h0) else + $fatal(1, "imm decode failed for addi: got %0h", imm_ext); + assert (funct3 == 3'b000) else + $fatal(1, "funct3 decode failed for addi: got %0h", funct3); + assert (rd == 5'h0) else + $fatal(1, "rd decode failed for addi: got %0h", rd); + assert (rs1 == 5'h0) else + $fatal(1, "rs1 decode failed for addi: got %0h", rs1); + assert (rs2 == 5'h0) else + $fatal(1, "rs2 decode failed for addi: got %0h", rs2); `ifdef UTOSS_RISCV_ENABLE_B_EXT instr = make_r_zbs(7'b0010100, 3'b001, 5'd3, 5'd2, 5'd1); // bset #1; + assert (opcode == OPCODE_OP) else + $fatal(1, "opcode decode failed for bset: got %0h", opcode); + assert (funct3 == 3'b001) else + $fatal(1, "funct3 decode failed for bset: got %0h", funct3); + assert (rd == 5'd1) else + $fatal(1, "rd decode failed for bset: got %0h", rd); + assert (rs1 == 5'd2) else + $fatal(1, "rs1 decode failed for bset: got %0h", rs1); + assert (rs2 == 5'd3) else + $fatal(1, "rs2 decode failed for bset: got %0h", rs2); assert (b_alu_control == B_ALU_CTRL__BSET) else $fatal(1, "bset decode failed: got %0h", b_alu_control); @@ -83,6 +107,8 @@ module zbs_decoder_tb; instr = make_i_zbs(7'b0010100, 5'd3, 5'd2, 5'd1, 3'b001); // bseti #1; + assert (opcode == OPCODE_OP_IMM) else + $fatal(1, "opcode decode failed for bseti: got %0h", opcode); assert (b_alu_control == B_ALU_CTRL__BSET) else $fatal(1, "bseti decode failed: got %0h", b_alu_control); From 0e3deeedb886b310f3d3c5ac890aa59cd8d98b7a Mon Sep 17 00:00:00 2001 From: SenseiPrimexus Date: Wed, 22 Jul 2026 01:44:46 -0400 Subject: [PATCH 29/30] Refactor zbs module to change reg2 type to logic [4:0] and update testbench accordingly --- src/ext/b/zbs.sv | 10 ++-- test/zbs_tb.sv | 127 ++++++++++++++++++----------------------------- 2 files changed, 54 insertions(+), 83 deletions(-) diff --git a/src/ext/b/zbs.sv b/src/ext/b/zbs.sv index 3e762112..c14acc68 100644 --- a/src/ext/b/zbs.sv +++ b/src/ext/b/zbs.sv @@ -4,7 +4,7 @@ module zbs ( input data_t reg1 - , input data_t reg2 + , input logic [4:0] reg2 , input ext__b__types::b_alu_control_t b_alu_control , output data_t out ); @@ -13,10 +13,10 @@ module zbs always_comb case (b_alu_control) - B_ALU_CTRL__BCLR: out = reg1 & ~(data_t'(32'h1) << reg2[4:0]); - B_ALU_CTRL__BSET: out = reg1 | (data_t'(32'h1) << reg2[4:0]); - B_ALU_CTRL__BINV: out = reg1 ^ (data_t'(32'h1) << reg2[4:0]); - B_ALU_CTRL__BEXT: out = (reg1 >> reg2[4:0]) & data_t'(32'h1); + B_ALU_CTRL__BCLR: out = reg1 & ~(data_t'(32'h1) << reg2); + B_ALU_CTRL__BSET: out = reg1 | (data_t'(32'h1) << reg2); + B_ALU_CTRL__BINV: out = reg1 ^ (data_t'(32'h1) << reg2); + B_ALU_CTRL__BEXT: out = (reg1 >> reg2) & data_t'(32'h1); default: out = '0; endcase diff --git a/test/zbs_tb.sv b/test/zbs_tb.sv index a9539d41..ffa80bc8 100644 --- a/test/zbs_tb.sv +++ b/test/zbs_tb.sv @@ -3,25 +3,22 @@ `include "src/ext/b/types.svh" module zbs_tb; - -import ext__b__types::*; - -logic [31:0] reg1; -logic [31:0] reg2; -b_alu_control_t b_alu_control; -logic [31:0] out; - -logic [31:0] expected; - -zbs uut - ( .reg1 ( reg1 ) - , .reg2 ( reg2 ) - , .b_alu_control ( b_alu_control ) - , .out ( out ) - ); - -initial begin - + import ext__b__types::*; + + logic [31:0] reg1; + logic [31:0] reg2; + b_alu_control_t b_alu_control; + logic [31:0] out; + logic [31:0] expected; + + zbs uut + ( .reg1 ( reg1 ) + , .reg2 ( reg2[4:0] ) + , .b_alu_control ( b_alu_control ) + , .out ( out ) + ); + + initial begin // -------- bclr test -------- reg1 = 32'b1010; reg2 = 32'd1; // clear bit 1 @@ -29,10 +26,8 @@ initial begin #10; expected = reg1 & ~(32'h1 << reg2[4:0]); - assert (out == expected) else - $fatal("bclr failed: expected %b got %b", expected, out); - + $fatal("bclr failed: expected %b got %b", expected, out); // -------- bset test -------- reg1 = 32'b1110; @@ -41,11 +36,9 @@ initial begin #10; expected = reg1 | (32'h1 << reg2[4:0]); - - assert (out == expected) else + assert (out == expected) else $fatal("bset failed: expected %b got %b", expected, out); - // -------- binv test -------- reg1 = 32'b1010; reg2 = 32'd1; @@ -53,10 +46,8 @@ initial begin #10; expected = reg1 ^ (32'h1 << reg2[4:0]); - assert (out == expected) else - $fatal("binv failed: expected %b got %b", expected, out); - + $fatal("binv failed: expected %b got %b", expected, out); // -------- bext test -------- reg1 = 32'b1010; @@ -65,81 +56,61 @@ initial begin #10; expected = {31'b0, reg1[reg2[4:0]]}; - assert (out == expected) else $fatal("bext failed: expected %b got %b", expected, out); - // -------- Edge Cases --------- - - // Bit 0 boundary + // -------- Edge Cases -------- reg1 = 32'hFFFFFFFF; reg2 = 32'd0; - b_alu_control = B_ALU_CTRL__BCLR; // bclr + b_alu_control = B_ALU_CTRL__BCLR; #10; expected = reg1 & ~(32'h1 << reg2[4:0]); - assert (out == expected) else $fatal("corner case bit0 failed"); - - // Bit 31 boundary reg1 = 32'hFFFFFFFF; reg2 = 32'd31; - b_alu_control = B_ALU_CTRL__BCLR; // bclr + b_alu_control = B_ALU_CTRL__BCLR; #10; expected = reg1 & ~(32'h1 << reg2[4:0]); - assert (out == expected) else $fatal("corner case bit31 failed"); - // ----------- Randomized Testing (Experimental) ----------- - repeat (1000) begin - - reg1 = $urandom; - reg2 = $urandom % 32; - - // pick a Zbs operation without arithmetic on enums to avoid width expansion - case ($urandom % 4) - 0: b_alu_control = B_ALU_CTRL__BCLR; - 1: b_alu_control = B_ALU_CTRL__BSET; - 2: b_alu_control = B_ALU_CTRL__BINV; - 3: b_alu_control = B_ALU_CTRL__BEXT; - default: b_alu_control = B_ALU_CTRL__BCLR; - endcase - - #1; - - case (b_alu_control) - - B_ALU_CTRL__BCLR: expected = reg1 & ~(32'h1 << reg2[4:0]); - - B_ALU_CTRL__BSET: expected = reg1 | (32'h1 << reg2[4:0]); - - B_ALU_CTRL__BINV: expected = reg1 ^ (32'h1 << reg2[4:0]); - - B_ALU_CTRL__BEXT: expected = {31'b0, reg1[reg2[4:0]]}; - - default: expected = 32'd0; - - endcase - - assert (out == expected) else - $fatal("random test failed: b_alu_control=%0d reg1=%h reg2=%d expected=%h got=%h" - , b_alu_control, reg1, reg2, expected, out); - + reg1 = $urandom; + reg2 = $urandom % 32; + + // pick a Zbs operation without arithmetic on enums to avoid width expansion + case ($urandom % 4) + 0: b_alu_control = B_ALU_CTRL__BCLR; + 1: b_alu_control = B_ALU_CTRL__BSET; + 2: b_alu_control = B_ALU_CTRL__BINV; + 3: b_alu_control = B_ALU_CTRL__BEXT; + default: b_alu_control = B_ALU_CTRL__BCLR; + endcase + + #1; + + case (b_alu_control) + B_ALU_CTRL__BCLR: expected = reg1 & ~(32'h1 << reg2[4:0]); + B_ALU_CTRL__BSET: expected = reg1 | (32'h1 << reg2[4:0]); + B_ALU_CTRL__BINV: expected = reg1 ^ (32'h1 << reg2[4:0]); + B_ALU_CTRL__BEXT: expected = {31'b0, reg1[reg2[4:0]]}; + default: expected = 32'd0; + endcase + + assert (out == expected) else + $fatal("random test failed: b_alu_control=%0d reg1=%h reg2=%d expected=%h got=%h" + , b_alu_control, reg1, reg2, expected, out); end $display("All tests passed!"); - $finish; + end -end - -`SETUP_VCD_DUMP(zbs_tb) - + `SETUP_VCD_DUMP(zbs_tb) endmodule From 205208bdc1f0a4313360281cab2bd8826733f7cc Mon Sep 17 00:00:00 2001 From: SenseiPrimexus Date: Wed, 22 Jul 2026 02:37:55 -0400 Subject: [PATCH 30/30] Add b_alu_control cases for BSET, BINV, and BCLR in ext__b__decoder --- src/ext/b/decoder.sv | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/ext/b/decoder.sv b/src/ext/b/decoder.sv index d8eeddc5..0de6c880 100644 --- a/src/ext/b/decoder.sv +++ b/src/ext/b/decoder.sv @@ -119,6 +119,7 @@ module ext__b__decoder 5'b00111: b_alu_control = B_ALU_CTRL__ORCB; default: b_alu_control = B_ALU_CTRL__NONE; endcase + 3'b001: b_alu_control = B_ALU_CTRL__BSET; default: b_alu_control = B_ALU_CTRL__NONE; endcase @@ -129,6 +130,14 @@ module ext__b__decoder 5'b11000: b_alu_control = B_ALU_CTRL__REV8; default: b_alu_control = B_ALU_CTRL__NONE; endcase + 3'b001: b_alu_control = B_ALU_CTRL__BINV; + default: b_alu_control = B_ALU_CTRL__NONE; + endcase + + FUNCT7_ZBB__BCLR: + case (funct3) + 3'b001: b_alu_control = B_ALU_CTRL__BCLR; + 3'b101: b_alu_control = B_ALU_CTRL__BEXT; default: b_alu_control = B_ALU_CTRL__NONE; endcase