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=Gray,1=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计算 -------------------------- // min:0→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 // max:255→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