208 lines
9.1 KiB
Coq
208 lines
9.1 KiB
Coq
![]() |
`timescale 1ns/1ps
|
|||
|
|
|||
|
// 直方图控制模块Testbench(修复标识符未声明问题)
|
|||
|
module tb_histogram_ctrl();
|
|||
|
|
|||
|
// -------------------------- 1. 参数定义(与待测试模块匹配) --------------------------
|
|||
|
parameter HIST_RAM_DEPTH = 256; // 直方图RAM深度(像素值0~255)
|
|||
|
parameter HIST_RAM_DATA_W = 1; // 直方图RAM数据位宽(1bit标记像素存在)
|
|||
|
parameter CLK_PERIOD = 10; // 时钟周期(10ns = 100MHz)
|
|||
|
parameter RAM_CLEAR_CYCLES = 256; // 直方图复位需遍历256个地址(256个时钟周期)
|
|||
|
|
|||
|
// -------------------------- 2. 信号定义(仅含模块接口信号,无内部信号引用) --------------------------
|
|||
|
reg clk; // 时钟
|
|||
|
reg rst_n; // 全局复位(低有效)
|
|||
|
reg hist_rst; // 直方图复位
|
|||
|
reg input_pixel_type; // 像素类型(0=Gray,1=RGB)
|
|||
|
// CH0 写信号(Gray模式有效/RGB模式R通道)
|
|||
|
reg hist_wr_en_ch0; // CH0写使能
|
|||
|
reg [7:0] hist_wr_addr_ch0; // CH0写地址(像素值0~255)
|
|||
|
// CH1 写信号(仅RGB模式G通道)
|
|||
|
reg hist_wr_en_ch1; // CH1写使能
|
|||
|
reg [7:0] hist_wr_addr_ch1; // CH1写地址
|
|||
|
// CH2 写信号(仅RGB模式B通道)
|
|||
|
reg hist_wr_en_ch2; // CH2写使能
|
|||
|
reg [7:0] hist_wr_addr_ch2; // CH2写地址
|
|||
|
// min/max计算配置
|
|||
|
reg [15:0] histogram_low_num; // 低位数(第N个有效像素作为min)
|
|||
|
reg [15:0] histogram_high_num; // 高位数(第N个有效像素作为max)
|
|||
|
reg calc_en; // 计算使能
|
|||
|
// 输出信号
|
|||
|
wire calc_done; // 计算完成
|
|||
|
wire [7:0] dwidth_conv_min_ch0;// CH0 min结果
|
|||
|
wire [7:0] dwidth_conv_max_ch0;// CH0 max结果
|
|||
|
wire [7:0] dwidth_conv_min_ch1;// CH1 min结果
|
|||
|
wire [7:0] dwidth_conv_max_ch1;// CH1 max结果
|
|||
|
wire [7:0] dwidth_conv_min_ch2;// CH2 min结果
|
|||
|
wire [7:0] dwidth_conv_max_ch2;// CH2 max结果
|
|||
|
|
|||
|
// -------------------------- 3. 生成时钟 --------------------------
|
|||
|
initial begin
|
|||
|
clk = 1'b0;
|
|||
|
forever #(CLK_PERIOD/2) clk = ~clk; // 5ns翻转,100MHz时钟
|
|||
|
end
|
|||
|
|
|||
|
// -------------------------- 4. 实例化待测试模块 --------------------------
|
|||
|
histogram_ctrl #(
|
|||
|
.HIST_RAM_DEPTH (HIST_RAM_DEPTH),
|
|||
|
.HIST_RAM_DATA_W (HIST_RAM_DATA_W)
|
|||
|
) u_histogram_ctrl (
|
|||
|
.clk (clk),
|
|||
|
.rst_n (rst_n),
|
|||
|
.hist_rst (hist_rst),
|
|||
|
.input_pixel_type (input_pixel_type),
|
|||
|
.hist_wr_en_ch0 (hist_wr_en_ch0),
|
|||
|
.hist_wr_addr_ch0 (hist_wr_addr_ch0),
|
|||
|
.hist_wr_en_ch1 (hist_wr_en_ch1),
|
|||
|
.hist_wr_addr_ch1 (hist_wr_addr_ch1),
|
|||
|
.hist_wr_en_ch2 (hist_wr_en_ch2),
|
|||
|
.hist_wr_addr_ch2 (hist_wr_addr_ch2),
|
|||
|
.histogram_low_num (histogram_low_num),
|
|||
|
.histogram_high_num (histogram_high_num),
|
|||
|
.calc_en (calc_en),
|
|||
|
.calc_done (calc_done),
|
|||
|
.dwidth_conv_min_ch0 (dwidth_conv_min_ch0),
|
|||
|
.dwidth_conv_max_ch0 (dwidth_conv_max_ch0),
|
|||
|
.dwidth_conv_min_ch1 (dwidth_conv_min_ch1),
|
|||
|
.dwidth_conv_max_ch1 (dwidth_conv_max_ch1),
|
|||
|
.dwidth_conv_min_ch2 (dwidth_conv_min_ch2),
|
|||
|
.dwidth_conv_max_ch2 (dwidth_conv_max_ch2)
|
|||
|
);
|
|||
|
|
|||
|
// -------------------------- 5. 生成FSDB波形文件(Verdi可查看) --------------------------
|
|||
|
initial begin
|
|||
|
$fsdbDumpfile("tb.fsdb"); // 波形文件命名为tb.fsdb
|
|||
|
$fsdbDumpvars(0, tb_histogram_ctrl); // Dump顶层及所有子模块信号
|
|||
|
$fsdbDumpMDA(0, tb_histogram_ctrl); // Dump内部RAM(hist_ram_ch0/1/2)内容
|
|||
|
end
|
|||
|
|
|||
|
// -------------------------- 6. 核心测试场景(无内部信号引用) --------------------------
|
|||
|
initial begin
|
|||
|
// --------------- 步骤1:初始复位(清除不定态) ---------------
|
|||
|
rst_n = 1'b0;
|
|||
|
hist_rst = 1'b0;
|
|||
|
input_pixel_type = 1'b0;
|
|||
|
hist_wr_en_ch0 = 1'b0;
|
|||
|
hist_wr_addr_ch0 = 8'd0;
|
|||
|
hist_wr_en_ch1 = 1'b0;
|
|||
|
hist_wr_addr_ch1 = 8'd0;
|
|||
|
hist_wr_en_ch2 = 1'b0;
|
|||
|
hist_wr_addr_ch2 = 8'd0;
|
|||
|
histogram_low_num = 16'd2; // 找第2个有效像素作为min(跳过1个噪声点)
|
|||
|
histogram_high_num = 16'd2; // 找第2个有效像素作为max(跳过1个噪声点)
|
|||
|
calc_en = 1'b0;
|
|||
|
|
|||
|
#(CLK_PERIOD * 5); // 复位保持5个时钟周期
|
|||
|
rst_n = 1'b1; // 释放全局复位
|
|||
|
#(CLK_PERIOD * 2); // 等待稳定
|
|||
|
|
|||
|
// --------------- 步骤2:测试直方图复位(替代原状态判断) ---------------
|
|||
|
$display("[%0t] Test 1: Histogram Reset", $time);
|
|||
|
hist_rst = 1'b1; // 触发直方图复位
|
|||
|
#(CLK_PERIOD); // 保持1个时钟周期确保状态切换
|
|||
|
hist_rst = 1'b0; // 释放复位
|
|||
|
#(CLK_PERIOD * RAM_CLEAR_CYCLES); // 等待复位完成(遍历256个地址)
|
|||
|
#(CLK_PERIOD * 2); // 额外等待2个周期稳定
|
|||
|
$display("[%0t] Test 1 Done: Histogram RAM Cleared", $time);
|
|||
|
|
|||
|
// --------------- 步骤3:灰度模式(Gray)写入与min/max计算 ---------------
|
|||
|
$display("[%0t] Test 2: Gray Mode (Write + Calc min/max)", $time);
|
|||
|
input_pixel_type = 1'b0; // 切换为Gray模式(仅CH0有效)
|
|||
|
|
|||
|
// 3.1 写入Gray数据(有效像素值:10、20、30、40、50)
|
|||
|
hist_wr_en_ch0 = 1'b1;#(CLK_PERIOD);
|
|||
|
hist_wr_addr_ch0 = 8'd10; #(CLK_PERIOD);
|
|||
|
hist_wr_addr_ch0 = 8'd20; #(CLK_PERIOD);
|
|||
|
hist_wr_addr_ch0 = 8'd30; #(CLK_PERIOD);
|
|||
|
hist_wr_addr_ch0 = 8'd40; #(CLK_PERIOD);
|
|||
|
hist_wr_addr_ch0 = 8'd50; #(CLK_PERIOD);
|
|||
|
hist_wr_en_ch0 = 1'b0; // 关闭写使能
|
|||
|
#(CLK_PERIOD * 2);
|
|||
|
|
|||
|
// 3.2 触发min/max计算(找第2个min=20,第2个max=40)
|
|||
|
calc_en = 1'b1;
|
|||
|
#(CLK_PERIOD);
|
|||
|
calc_en = 1'b0; // 释放计算使能
|
|||
|
wait(calc_done == 1'b1); // 用输出信号判断计算完成(无需内部状态)
|
|||
|
#(CLK_PERIOD);
|
|||
|
|
|||
|
// 打印结果(预期:min_ch0=20,max_ch0=40)
|
|||
|
$display("[%0t] Gray Mode Result: min_ch0=%0d, max_ch0=%0d (Expected: 20, 40)",
|
|||
|
$time, dwidth_conv_min_ch0, dwidth_conv_max_ch0);
|
|||
|
#(CLK_PERIOD * 2);
|
|||
|
|
|||
|
// --------------- 步骤4:RGB模式写入与min/max计算 ---------------
|
|||
|
$display("[%0t] Test 3: RGB Mode (Write + Calc min/max)", $time);
|
|||
|
// 直方图复位(用时间等待替代状态判断)
|
|||
|
hist_rst = 1'b1;
|
|||
|
#(CLK_PERIOD);
|
|||
|
hist_rst = 1'b0;
|
|||
|
#(CLK_PERIOD * RAM_CLEAR_CYCLES); // 等待复位完成
|
|||
|
input_pixel_type = 1'b1; // 切换为RGB模式(CH0=R,CH1=G,CH2=B)
|
|||
|
#(CLK_PERIOD * 2);
|
|||
|
|
|||
|
// 4.1 写入RGB数据(R:15、25、35;G:45、55、65;B:75、85、95)
|
|||
|
// 写R通道(CH0)
|
|||
|
hist_wr_en_ch0 = 1'b1;#(CLK_PERIOD);
|
|||
|
hist_wr_addr_ch0 = 8'd15; #(CLK_PERIOD);
|
|||
|
hist_wr_addr_ch0 = 8'd25; #(CLK_PERIOD);
|
|||
|
hist_wr_addr_ch0 = 8'd35; #(CLK_PERIOD);
|
|||
|
hist_wr_en_ch0 = 1'b0;
|
|||
|
|
|||
|
// 写G通道(CH1)
|
|||
|
hist_wr_en_ch1 = 1'b1;#(CLK_PERIOD);
|
|||
|
hist_wr_addr_ch1 = 8'd45; #(CLK_PERIOD);
|
|||
|
hist_wr_addr_ch1 = 8'd55; #(CLK_PERIOD);
|
|||
|
hist_wr_addr_ch1 = 8'd65; #(CLK_PERIOD);
|
|||
|
hist_wr_en_ch1 = 1'b0;
|
|||
|
|
|||
|
// 写B通道(CH2)
|
|||
|
hist_wr_en_ch2 = 1'b1;#(CLK_PERIOD);
|
|||
|
hist_wr_addr_ch2 = 8'd75; #(CLK_PERIOD);
|
|||
|
hist_wr_addr_ch2 = 8'd85; #(CLK_PERIOD);
|
|||
|
hist_wr_addr_ch2 = 8'd95; #(CLK_PERIOD);
|
|||
|
hist_wr_en_ch2 = 1'b0;
|
|||
|
#(CLK_PERIOD * 2);
|
|||
|
|
|||
|
// 4.2 触发RGB模式计算(预期:R=25/25,G=55/55,B=85/85)
|
|||
|
calc_en = 1'b1;
|
|||
|
#(CLK_PERIOD);
|
|||
|
calc_en = 1'b0;
|
|||
|
wait(calc_done == 1'b1); // 用输出信号判断完成
|
|||
|
#(CLK_PERIOD);
|
|||
|
|
|||
|
// 打印RGB结果
|
|||
|
$display("[%0t] RGB Mode Result: R(min=%0d, max=%0d), G(min=%0d, max=%0d), B(min=%0d, max=%0d) (Expected: R=25/25, G=55/55, B=85/85)",
|
|||
|
$time, dwidth_conv_min_ch0, dwidth_conv_max_ch0,
|
|||
|
dwidth_conv_min_ch1, dwidth_conv_max_ch1,
|
|||
|
dwidth_conv_min_ch2, dwidth_conv_max_ch2);
|
|||
|
#(CLK_PERIOD * 2);
|
|||
|
|
|||
|
// --------------- 步骤5:测试“写+计算”并行触发 ---------------
|
|||
|
$display("[%0t] Test 4: Trigger Write and Calc Simultaneously", $time);
|
|||
|
// 直方图复位
|
|||
|
hist_rst = 1'b1;
|
|||
|
#(CLK_PERIOD);
|
|||
|
hist_rst = 1'b0;
|
|||
|
#(CLK_PERIOD * RAM_CLEAR_CYCLES);
|
|||
|
input_pixel_type = 1'b0; // 回到Gray模式
|
|||
|
#(CLK_PERIOD * 2);
|
|||
|
|
|||
|
// 先写1个数据,再并行触发“写+计算”
|
|||
|
hist_wr_en_ch0 = 1'b1;
|
|||
|
hist_wr_addr_ch0 = 8'd5; #(CLK_PERIOD);
|
|||
|
calc_en = 1'b1; // 同时触发计算
|
|||
|
hist_wr_addr_ch0 = 8'd15; #(CLK_PERIOD);
|
|||
|
hist_wr_en_ch0 = 1'b0;
|
|||
|
calc_en = 1'b0;
|
|||
|
wait(calc_done == 1'b1); // 用输出信号判断完成
|
|||
|
#(CLK_PERIOD);
|
|||
|
$display("[%0t] Test 4 Done: Simultaneous Trigger OK", $time);
|
|||
|
|
|||
|
// --------------- 步骤6:测试完成,结束仿真 ---------------
|
|||
|
#(CLK_PERIOD * 5);
|
|||
|
$display("[%0t] All Tests Completed!", $time);
|
|||
|
$finish; // 结束仿真
|
|||
|
end
|
|||
|
|
|||
|
endmodule
|