diff --git a/lib/enc_dec/oh_bin/oh2bin.sv b/lib/enc_dec/oh_bin/oh2bin.sv new file mode 100644 index 0000000..754361a --- /dev/null +++ b/lib/enc_dec/oh_bin/oh2bin.sv @@ -0,0 +1,44 @@ + +// ============================================================= +// 模块名称:oh2bin +// 功能描述:参数化 one-hot 到二进制编码器 +// 参数: +// WIDTH - one-hot 输入宽度 +// AREA_OPT- 1: 面积优化,0: 频率优化 +// ============================================================= +module oh2bin #( + parameter WIDTH = 8, // one-hot 输入宽度 + parameter AREA_OPT = 1 // 1: 面积优化,0: 频率优化 +)( + input logic [WIDTH-1:0] oh, // one-hot 输入 + output logic [$clog2(WIDTH)-1:0] bin // 二进制输出 +); + + // ========================================================= + // 面积优化方案:使用for循环,优先节省面积 + // ========================================================= + generate + if (AREA_OPT) begin : gen_area_opt + always_comb begin + bin = '0; + for (int i = 0; i < WIDTH; i++) begin + if (oh[i]) bin = i[$clog2(WIDTH)-1:0]; + end + end + end else begin : gen_speed_opt + // ========================================================= + // 频率优化方案:并行掩码法,参考pulp-platform/common_cells实现 + // ========================================================= + for (genvar j = 0; j < $clog2(WIDTH); j++) begin : gen_jl + logic [WIDTH-1:0] tmp_mask; //xinb:bin每1bit的掩码,实际上取巧了。相当于是逆向思维。还可以正向编码,待补充. + for (genvar i = 0; i < WIDTH; i++) begin : gen_il + logic [$clog2(WIDTH)-1:0] tmp_i; + assign tmp_i = i[$clog2(WIDTH)-1:0]; + assign tmp_mask[i] = tmp_i[j]; + end + assign bin[j] = |(tmp_mask & oh); + end + end + endgenerate + +endmodule diff --git a/tb/enc_dec/oh_bin/oh2bin_tb.sv b/tb/enc_dec/oh_bin/oh2bin_tb.sv new file mode 100644 index 0000000..24b0857 --- /dev/null +++ b/tb/enc_dec/oh_bin/oh2bin_tb.sv @@ -0,0 +1,78 @@ +// ============================================================= +// 测试模块:oh2bin_tb +// 功能描述:onehot到bin编码器仿真测试,默认频率优化方案 +// 仿真时钟频率:1GHz,周期1ns +// ============================================================= +`timescale 1ns/1ps + +module oh2bin_tb; + parameter WIDTH = 8; + parameter BINW = $clog2(WIDTH); + + logic clk; + logic rst_n; + logic [WIDTH-1:0] oh; + logic [BINW-1:0] bin; + logic [BINW-1:0] bin_q; + + // 实例化被测模块,AREA_OPT=0为频率优化方案 + oh2bin #( + .WIDTH(WIDTH), + .AREA_OPT(0) + ) dut ( + .oh(oh), + .bin(bin) + ); + + // 时钟生成 + // 仿真时钟频率:1GHz,周期1ns + initial clk = 0; + always #0.5 clk = ~clk; // 1ns周期,1GHz + + // 采样输出 + always_ff @(posedge clk or negedge rst_n) begin + if (!rst_n) + bin_q <= '0; + else + bin_q <= bin; + end + + // 参考模型 + function [BINW-1:0] ref_oh2bin(input [WIDTH-1:0] oh_in); + integer i; + ref_oh2bin = '0; + for (i = 0; i < WIDTH; i = i + 1) begin + if (oh_in[i]) ref_oh2bin = i[BINW-1:0]; + end + endfunction + + initial begin + rst_n = 0; + oh = '0; + #20; + rst_n = 1; + $display("==== oh2bin 频率优化方案时序仿真 ===="); + for (int i = 0; i < WIDTH; i++) begin + @(negedge clk); + oh = '0; + oh[i] = 1'b1; + @(negedge clk); + if (bin_q !== ref_oh2bin(oh)) begin + $display("[ERROR] oh=%b, bin=%0d, ref=%0d", oh, bin_q, ref_oh2bin(oh)); + end else begin + $display("[PASS] oh=%b, bin=%0d", oh, bin_q); + end + end + // 非法输入测试 + @(negedge clk); + oh = '0; + @(negedge clk); + $display("[INFO] all zero input, bin=%0d", bin_q); + @(negedge clk); + oh = '1; + @(negedge clk); + $display("[INFO] all one input, bin=%0d", bin_q); + $display("==== 测试结束 ===="); + $finish; + end +endmodule diff --git a/tb/fifo/sync/fifo_sync_tb.sv b/tb/fifo/sync/fifo_sync_tb.sv index 600cbbb..3445741 100644 --- a/tb/fifo/sync/fifo_sync_tb.sv +++ b/tb/fifo/sync/fifo_sync_tb.sv @@ -1,4 +1,9 @@ +// ============================================================= +// 测试模块:fifo_sync_tb +// 功能描述:同步FIFO仿真测试 +// 仿真时钟频率:1GHz,周期0.5ns +// ============================================================= `timescale 1ns/1ps module fifo_sync_tb; @@ -37,9 +42,10 @@ module fifo_sync_tb; .err(err) ); + // 仿真时钟频率:1GHz,周期0.5ns // 时钟生成 initial clk = 0; - always #5 clk = ~clk; + always #0.25 clk = ~clk; // 0.5ns周期,1GHz // 复位 initial begin