4. 单通道3x3卷积计算单元
任务目标
实现一个单通道3x3卷积计算单元,对输入的3x3图像窗口与3x3卷积核执行乘累加运算,输出单个像素的卷积结果。本案例聚焦于卷积运算的核心计算逻辑,不涉及图像缓存、行缓冲或滑动窗口控制。
接口定义
| 信号 | 方向 | 位宽 | 说明 |
|---|---|---|---|
| clk | input | 1 | 时钟 |
| rst_n | input | 1 | 异步复位,低有效 |
| window_data | input | 9×8=72 | 3x3窗口像素,按行优先排列,每像素8bit无符号 |
| kernel_data | input | 9×8=72 | 3x3卷积核系数,按行优先排列,每系数8bit有符号(补码) |
| valid_in | input | 1 | 输入有效标志 |
| pixel_out | output | 16 | 卷积结果,有符号补码 |
| valid_out | output | 1 | 输出有效标志,延迟1拍 |
核心实现
采用两级流水线:第一级完成9个像素与系数的并行乘法,第二级将9个部分积相加得到最终结果。像素为无符号8bit,系数为有符号8bit,乘积为有符号16bit,9个乘积累加后最大位宽为16+4=20bit,但实际输出截断为16bit有符号数。
module conv3x3_single_channel (
input clk,
input rst_n,
input [71:0] window_data, // 9×8bit,行优先
input [71:0] kernel_data, // 9×8bit,有符号系数
input valid_in,
output reg [15:0] pixel_out,
output reg valid_out
);
// 拆分输入为9个独立像素和系数
wire [7:0] w [0:8];
wire [7:0] k [0:8];
genvar i;
generate
for (i = 0; i < 9; i = i + 1) begin : split_io
assign w[i] = window_data[i*8 +: 8];
assign k[i] = kernel_data[i*8 +: 8];
end
endgenerate
// 第一级:乘法
reg signed [15:0] mul_result [0:8];
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
for (int j = 0; j < 9; j = j + 1)
mul_result[j] <= 16'sd0;
end else if (valid_in) begin
for (int j = 0; j < 9; j = j + 1)
mul_result[j] <= $signed({1'b0, w[j]}) * $signed(k[j]);
end
end
// 第二级:累加
reg signed [19:0] sum_result;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
sum_result <= 20'sd0;
valid_out <= 1'b0;
end else begin
sum_result <= mul_result[0] + mul_result[1] + mul_result[2] +
mul_result[3] + mul_result[4] + mul_result[5] +
mul_result[6] + mul_result[7] + mul_result[8];
valid_out <= valid_in;
end
end
// 输出截断为16bit有符号
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
pixel_out <= 16'sd0;
else
pixel_out <= sum_result[15:0];
end
endmodule
运行与验证
Testbench要点:构造一个已知窗口和卷积核,手动计算期望结果,对比模块输出。
// 示例:3x3窗口全为1,卷积核全为1,期望结果=9
// 窗口数据:72'h01_01_01_01_01_01_01_01_01
// 核数据: 72'h01_01_01_01_01_01_01_01_01
// 期望输出:16'sd9
仿真步骤:
- 使用Vivado/ModelSim/Verilator等工具编译conv3x3_single_channel.v和对应testbench;
- 拉高valid_in一个周期,输入上述窗口和核数据;
- 观察valid_out拉高时pixel_out的值。
通过条件:valid_out为高时,pixel_out等于16'sd9。可进一步用随机窗口和核数据,在testbench中计算期望值并自动比对,若所有测试向量均匹配则验证通过。
注意事项
- 像素按无符号处理,在乘法前扩展1位0符号位;卷积核按有符号补码处理,支持负系数;
- 输出截断为16bit,若累加结果超出16bit范围会发生溢出,实际应用中需根据数据范围调整输出位宽或增加饱和处理;
- 流水线延迟为2个时钟周期(乘法1拍+累加1拍),valid_out与pixel_out同步对齐。