Files
IPA/rtl/data_cache/histogram_ctrl.v
Core_kingdom 79dee10db1 cache module
2025-08-26 16:53:22 +08:00

231 lines
9.6 KiB
Verilog
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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计算 --------------------------
// min0→255遍历找第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
// max255→0遍历找第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