Files
common/rtl/base/bit_ops.sv
T
maksyuki a542f1ee57 feat: enhance validation and error handling in RTL modules
- Added geometry validation for BIT_WIDTH, WORD_DEPTH, and ADDR_WIDTH in tech_ram, tech_ram_bm, tech_regfile, and tech_regfile_bm modules to ensure proper configurations.
- Implemented address range checks in tech_ram, tech_ram_bm, tech_regfile, and tech_regfile_bm modules to prevent out-of-bounds access.
- Improved error messages for unsupported access types in regfield module, including validation for DATA_WIDTH.
- Added DATA_WIDTH validation in spill_register module to ensure positive values.
- Refactored APB4AXI4Master and APB4Master classes to streamline constructor definitions and improve readability.
- Enhanced AXI4Master class with additional burst address calculations and legality checks for read/write operations.
- Updated read/write tasks in AXI4Master to include error handling for response mismatches and illegal burst conditions.
- Simplified the filtering of reference data in rd_check task of AXI4Master to improve clarity and maintainability.
- Cleaned up the TestBase class constructor for consistency and clarity.
2026-08-03 20:10:19 +08:00

108 lines
2.8 KiB
Systemverilog

// Copyright (c) 2026 Yuchi Miao <miaoyuchi@ict.ac.cn>
// SPDX-License-Identifier: MulanPSL-2.0
// Small combinational primitives intentionally have no external dependency.
module bit_count #(
parameter int WIDTH = 32,
parameter int COUNT_WIDTH = $clog2(WIDTH + 1)
) (
input logic [ WIDTH-1:0] value_i,
output logic [COUNT_WIDTH-1:0] count_o
);
initial begin
if (WIDTH < 1 || COUNT_WIDTH < $clog2(WIDTH + 1)) begin
$fatal(1, "bit_count: WIDTH must be positive and COUNT_WIDTH sufficient");
end
end
always_comb begin
count_o = '0;
for (int unsigned bit_idx = 0; bit_idx < WIDTH; bit_idx++) begin
count_o = count_o + value_i[bit_idx];
end
end
endmodule
module leading_zero_count #(
parameter int WIDTH = 32,
parameter int COUNT_WIDTH = $clog2(WIDTH + 1)
) (
input logic [ WIDTH-1:0] value_i,
output logic [COUNT_WIDTH-1:0] count_o,
output logic all_zero_o
);
logic s_seen_one;
initial begin
if (WIDTH < 1 || COUNT_WIDTH < $clog2(WIDTH + 1)) begin
$fatal(1, "leading_zero_count: WIDTH must be positive and COUNT_WIDTH sufficient");
end
end
always_comb begin
count_o = '0;
s_seen_one = 1'b0;
for (int bit_idx = WIDTH - 1; bit_idx >= 0; bit_idx--) begin
if (!s_seen_one && value_i[bit_idx]) begin
s_seen_one = 1'b1;
end else if (!s_seen_one) begin
count_o = count_o + 1'b1;
end
end
all_zero_o = !s_seen_one;
end
endmodule
module onehot_check #(
parameter int WIDTH = 32,
parameter bit ALLOW_ZERO = 1'b0
) (
input logic [WIDTH-1:0] value_i,
output logic valid_o
);
initial begin
if (WIDTH < 1) $fatal(1, "onehot_check: WIDTH must be positive");
end
always_comb begin
valid_o = (value_i != '0) && ((value_i & (value_i - 1'b1)) == '0);
if (ALLOW_ZERO && value_i == '0) begin
valid_o = 1'b1;
end
end
endmodule
module onehot_to_index #(
parameter int WIDTH = 32,
parameter int INDEX_WIDTH = (WIDTH > 1) ? $clog2(WIDTH) : 1
) (
input logic [ WIDTH-1:0] value_i,
output logic [INDEX_WIDTH-1:0] index_o,
output logic valid_o
);
logic [WIDTH-1:0] s_onehot;
initial begin
if (WIDTH < 1 || INDEX_WIDTH < ((WIDTH > 1) ? $clog2(WIDTH) : 1)) begin
$fatal(1, "onehot_to_index: WIDTH must be positive and INDEX_WIDTH sufficient");
end
end
onehot_check #(
.WIDTH (WIDTH),
.ALLOW_ZERO(1'b0)
) u_onehot_check (
.value_i(value_i),
.valid_o(valid_o)
);
assign s_onehot = value_i;
always_comb begin
index_o = '0;
for (int unsigned bit_idx = 0; bit_idx < WIDTH; bit_idx++) begin
if (s_onehot[bit_idx]) begin
index_o = INDEX_WIDTH'(bit_idx);
end
end
end
endmodule