Files
IPA/rtl/data_cache/histogram_ctrl.v

231 lines
9.6 KiB
Coq
Raw Permalink Normal View History

2025-08-26 16:53:22 +08:00
module histogram_ctrl #(
parameter HIST_RAM_DEPTH = 256,
parameter HIST_RAM_DATA_W = 1
) (
input wire clk,
input wire rst_n,
input wire hist_rst, // 直方图复位
input wire input_pixel_type, // 0=Gray1=RGB
input wire hist_wr_en_ch0, // CH0写使能
input wire [7:0] hist_wr_addr_ch0, // CH0写地址像素值0~255
input wire hist_wr_en_ch1, // CH1写使能
input wire [7:0] hist_wr_addr_ch1, // CH1写地址
input wire hist_wr_en_ch2, // CH2写使能
input wire [7:0] hist_wr_addr_ch2, // CH2写地址
input wire [15:0] histogram_low_num, // 低位数计算min
input wire [15:0] histogram_high_num,// 高位数计算max
input wire calc_en, // 计算使能
output reg calc_done, // 计算完成
output reg [7:0] dwidth_conv_min_ch0,
output reg [7:0] dwidth_conv_max_ch0,
output reg [7:0] dwidth_conv_min_ch1,
output reg [7:0] dwidth_conv_max_ch1,
output reg [7:0] dwidth_conv_min_ch2,
output reg [7:0] dwidth_conv_max_ch2
);
// 内部信号
reg [HIST_RAM_DATA_W-1:0] hist_ram_ch0 [HIST_RAM_DEPTH-1:0]; // CH0直方图RAM
reg [HIST_RAM_DATA_W-1:0] hist_ram_ch1 [HIST_RAM_DEPTH-1:0]; // CH1直方图RAM
reg [HIST_RAM_DATA_W-1:0] hist_ram_ch2 [HIST_RAM_DEPTH-1:0]; // CH2直方图RAM
reg [7:0] calc_addr; // 遍历地址0~255
reg [15:0] low_cnt_ch0; // CH0低位数计数器
reg [15:0] high_cnt_ch0; // CH0高位数计数器
reg [15:0] low_cnt_ch1; // CH1低位数计数器
reg [15:0] high_cnt_ch1; // CH1高位数计数器
reg [15:0] low_cnt_ch2; // CH2低位数计数器
reg [15:0] high_cnt_ch2; // CH2高位数计数器
reg calc_active; // 计算活跃标记
// 状态定义
localparam [1:0] S_HIST_IDLE = 2'b00;
localparam [1:0] S_HIST_CLEAR = 2'b01;
localparam [1:0] S_HIST_WRITE = 2'b10;
localparam [1:0] S_HIST_CALC = 2'b11;
reg [1:0] curr_hist_state;
reg [1:0] next_hist_state;
// 1. 状态机时序逻辑
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
curr_hist_state <= S_HIST_IDLE;
end else begin
curr_hist_state <= next_hist_state;
end
end
// 2. 状态机组合逻辑
always @(*) begin
next_hist_state = curr_hist_state;
case (curr_hist_state)
S_HIST_IDLE: begin
if (hist_rst) begin
next_hist_state = S_HIST_CLEAR;
end else if (hist_wr_en_ch0 || hist_wr_en_ch1 || hist_wr_en_ch2) begin
next_hist_state = S_HIST_WRITE;
end else if (calc_en) begin
next_hist_state = S_HIST_CALC;
end
end
S_HIST_CLEAR: begin
if (calc_addr == HIST_RAM_DEPTH - 1) begin
next_hist_state = S_HIST_IDLE;
end
end
S_HIST_WRITE: begin
if (hist_rst) begin
next_hist_state = S_HIST_CLEAR;
end else if (calc_en) begin
next_hist_state = S_HIST_CALC;
end
end
S_HIST_CALC: begin
if (calc_addr == HIST_RAM_DEPTH - 1) begin
next_hist_state = S_HIST_IDLE;
end
end
endcase
end
// 3. 直方图RAM复位/写逻辑
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
// 复位所有RAM
integer i;
for (i = 0; i < HIST_RAM_DEPTH; i = i+1) begin
hist_ram_ch0[i] <= 1'b0;
hist_ram_ch1[i] <= 1'b0;
hist_ram_ch2[i] <= 1'b0;
end
calc_addr <= 8'd0;
end else begin
case (curr_hist_state)
S_HIST_CLEAR: begin
// 清空RAM地址递增
hist_ram_ch0[calc_addr] <= 1'b0;
hist_ram_ch1[calc_addr] <= 1'b0;
hist_ram_ch2[calc_addr] <= 1'b0;
calc_addr <= calc_addr + 8'd1;
end
S_HIST_WRITE: begin
// CH0写始终有效
if (hist_wr_en_ch0) begin
hist_ram_ch0[hist_wr_addr_ch0] <= 1'b1; // 标记像素值存在
end
// CH1/CH2写仅RGB模式有效
if (hist_wr_en_ch1 && (input_pixel_type == 1'b1)) begin
hist_ram_ch1[hist_wr_addr_ch1] <= 1'b1;
end
if (hist_wr_en_ch2 && (input_pixel_type == 1'b1)) begin
hist_ram_ch2[hist_wr_addr_ch2] <= 1'b1;
end
calc_addr <= 8'd0;
end
S_HIST_CALC: begin
// 遍历地址递增
calc_addr <= calc_addr + 8'd1;
end
default: begin
calc_addr <= 8'd0;
end
endcase
end
end
// 4. 修复后的直方图min/max计算逻辑关键修复点
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
low_cnt_ch0 <= 16'd0;
high_cnt_ch0 <= 16'd0;
low_cnt_ch1 <= 16'd0;
high_cnt_ch1 <= 16'd0;
low_cnt_ch2 <= 16'd0;
high_cnt_ch2 <= 16'd0;
dwidth_conv_min_ch0 <= 8'd0;
dwidth_conv_max_ch0 <= 8'd255;
dwidth_conv_min_ch1 <= 8'd0;
dwidth_conv_max_ch1 <= 8'd255;
dwidth_conv_min_ch2 <= 8'd0;
dwidth_conv_max_ch2 <= 8'd255;
calc_done <= 1'b0;
calc_active <= 1'b0;
end else begin
calc_done <= 1'b0;
case (curr_hist_state)
S_HIST_CALC: begin
calc_active <= 1'b1;
// -------------------------- 关键修复1计算开始时强制清零计数器 --------------------------
if (calc_addr == 8'd0) begin // 遍历地址为0时计算起始清零所有计数器
low_cnt_ch0 <= 16'd0;
high_cnt_ch0 <= 16'd0;
low_cnt_ch1 <= 16'd0;
high_cnt_ch1 <= 16'd0;
low_cnt_ch2 <= 16'd0;
high_cnt_ch2 <= 16'd0;
end
// -------------------------- CH0计算 --------------------------
// min0255遍历找第histogram_low_num个1
if (low_cnt_ch0 < histogram_low_num && hist_ram_ch0[calc_addr] == 1'b1) begin
low_cnt_ch0 <= low_cnt_ch0 + 16'd1;
if (low_cnt_ch0 == histogram_low_num - 16'd1) begin
dwidth_conv_min_ch0 <= calc_addr;
end
end
// max2550遍历找第histogram_high_num个1
if (high_cnt_ch0 < histogram_high_num && hist_ram_ch0[255 - calc_addr] == 1'b1) begin
high_cnt_ch0 <= high_cnt_ch0 + 16'd1;
if (high_cnt_ch0 == histogram_high_num - 16'd1) begin
dwidth_conv_max_ch0 <= 255 - calc_addr;
end
end
// -------------------------- CH1计算仅RGB模式 --------------------------
if (input_pixel_type == 1'b1) begin
if (low_cnt_ch1 < histogram_low_num && hist_ram_ch1[calc_addr] == 1'b1) begin
low_cnt_ch1 <= low_cnt_ch1 + 16'd1;
if (low_cnt_ch1 == histogram_low_num - 16'd1) begin
dwidth_conv_min_ch1 <= calc_addr;
end
end
if (high_cnt_ch1 < histogram_high_num && hist_ram_ch1[255 - calc_addr] == 1'b1) begin
high_cnt_ch1 <= high_cnt_ch1 + 16'd1;
if (high_cnt_ch1 == histogram_high_num - 16'd1) begin
dwidth_conv_max_ch1 <= 255 - calc_addr;
end
end
end
// -------------------------- CH2计算仅RGB模式 --------------------------
if (input_pixel_type == 1'b1) begin
if (low_cnt_ch2 < histogram_low_num && hist_ram_ch2[calc_addr] == 1'b1) begin
low_cnt_ch2 <= low_cnt_ch2 + 16'd1;
if (low_cnt_ch2 == histogram_low_num - 16'd1) begin
dwidth_conv_min_ch2 <= calc_addr;
end
end
if (high_cnt_ch2 < histogram_high_num && hist_ram_ch2[255 - calc_addr] == 1'b1) begin
high_cnt_ch2 <= high_cnt_ch2 + 16'd1;
if (high_cnt_ch2 == histogram_high_num - 16'd1) begin
dwidth_conv_max_ch2 <= 255 - calc_addr;
end
end
end
// -------------------------- 遍历结束置位完成信号 --------------------------
if (calc_addr == HIST_RAM_DEPTH - 1) begin
calc_done <= 1'b1;
calc_active <= 1'b0;
end
end
default: begin
calc_active <= 1'b0;
calc_done <= 1'b0;
end
endcase
end
end
endmodule