always @ (posedge clk or negedge rst_n) begin if(!rst_n) begin state <= ST_IDLE; end else case(state) ST_IDLE: begin if(valid_in) state <= ST_INIT; else state <= ST_IDLE; end ST_INIT: begin if(init_done) state <= ST_SAMPLE; else state <= ST_INIT; end ST_SAMPLE: begin if(bmp_write_done) state <= ST_COUNT; else state <= ST_SAMPLE; end ST_COUNT: begin if(count_done) state <= ST_UPDATE; else state <= ST_COUNT; end ST_UPDATE: begin if(update_done) state <= ST_WRITE_BMP; else state <= ST_UPDATE; end ST_WRITE_BMP: begin if(data_read_done) state <= ST_IDLE; else state <= ST_WRITE_BMP; end endcase end
always @ (posedge clk or negedge rst_n) begin if(!rst_n) begin count_wr_cen <= 1'b1; count_wr_addr <= 8'b0; count_wr_data <= 11'b0; count_rd_cen <= 1'b1; count_rd_addr <= 8'b0; init_done <= 1'b0; sample_cen <= 1'b1; sample_wen <= 1'b0; sample_addr <= 16'b0; //读地址计数器,d1应该是delay 1个周期 count_rd_addr_d1 <= 8'b0; count_done <= 1'b0; count <= 3'b0; count_sum <= 16'b0; update_done <= 1'b0; sample_rd_data_d1 <= 8'b0; sample_rd_data_d2 <= 8'b0; data_read_start <= 1'b0; data_read_done <= 1'b0; end else case(state) ST_IDLE: begin count_wr_cen <= 1'b0; end ST_INIT: begin // start to init count_wr_addr <= count_wr_addr + 1'b1; if(count_wr_addr == 255) begin // init done init_done <= 1'b1; // finish init count_wr_cen <= 1'b1; count_wr_addr <= 0; // start to sample sample_cen <= 1'b0; end end ST_SAMPLE: begin // sample
sample_addr <= sample_addr + 1'b1; if(bmp_write_done) begin //需要修改 sample_addr <= 1078; // 数据起始索引地址data_start_index,由BMP图片格式规定 sample_wen <= 1'b1; // start to count count <= count + 1'b1; end end ST_COUNT: begin // count count <= count + 1'b1; if(count == 5) count <= 0; case(count) // read the sample data 0: begin sample_cen <= 1'b0; sample_addr <= sample_addr + 1'b1; end // read the count 1: begin sample_cen <= 1'b1; end // count the data 2: begin count_rd_cen <= 1'b0; count_rd_addr <= sample_rd_data; end 3: begin count_rd_cen <= 1'b1; end // write back 4: begin count_wr_cen <= 1'b0; count_wr_data <= count_rd_data + 1'b1; count_wr_addr <= count_rd_addr; //需要修改 if(sample_addr == 41078) begin //读入的BMP图片的所有数据地址 file_read = $fread(bmp_data,bmp_file_read) sample_addr <= 0; count_done <= 1'b1; count_wr_addr <= 0; count_rd_cen <= 1'b0; count_rd_addr <= 0; count_wr_cen <= 1'b1; end end 5: begin count_wr_cen <= 1'b1; end endcase end ST_UPDATE: begin // read the count data count_rd_addr <= count_rd_addr + 1'b1; count_sum <= count_sum + count_rd_data; // update and write count_wr_cen <= count_rd_cen; count_rd_addr_d1 <= count_rd_addr; count_wr_addr <= count_rd_addr_d1; count_wr_data <= update_conut; if(count_wr_addr == 255) begin update_done <= 1'b1; count_rd_cen <= 1'b1; count_wr_cen <= 1'b1; // start to write bmp sample_cen <= 1'b0; sample_wen <= 1'b1; sample_addr <= 0; end
end ST_WRITE_BMP: begin //需要修改 if(sample_addr < 1078) begin // 地址小于1078时为BMP的头文件数据 sample_addr <= sample_addr + 1; sample_rd_data_d1 <= sample_rd_data; sample_rd_data_d2 <= sample_rd_data_d1; if(sample_addr == 1) data_read_start <= 1'b1; end else begin sample_addr <= sample_addr + 1; sample_rd_data_d1 <= sample_rd_data; sample_rd_data_d2 <= sample_rd_data_d1; count_rd_cen <= 1'b0; count_rd_addr <= sample_rd_data; //修改为400*400的结束数据,这个是200*200的 if(sample_addr == 41079) begin // 除BMP的头文件数据的其余数据 data_read_done <= 1'b1; data_read_start <= 1'b0; sample_cen <= 1'b1; count_rd_cen <= 1'b1; end end end endcase end
//======================<clock and reset>====================== initial begin clk = 1; forever #(`Clock/2) clk = ~clk; end
initial begin rst_n = 0; #(`Clock*20 + 1); rst_n = 1; end
// read the bmp data integer bmp_file_read; integer file_read; integer data_start_index; integer bmp_size;
initial begin bmp_file_read = $fopen(".\\picture_copy.bmp","rb"); file_read = $fread(bmp_data,bmp_file_read); // get the data start index data_start_index = {bmp_data[13], bmp_data[12], bmp_data[11], bmp_data[10]}; // get the bmp size bmp_size = {bmp_data[5], bmp_data[4], bmp_data[3], bmp_data[2]}; end
//======================<input signal>========================= initial begin end
integer index; always @ (posedge clk or negedge rst_n) begin if(!rst_n) begin index <= 0; image_write_done <= 0; bmp_write_done <= 0; point_data_in <= 0; valid_in <= 0; end // when index=data_start_index, it starts to process image else begin valid_in <= 1; if(init_done) begin if (index == data_start_index) begin image_write_done <= 1; index <= index + 1; point_data_in <= bmp_data[index]; end else if(index == bmp_size) bmp_write_done <= 1; else begin index <= index + 1; point_data_in <= bmp_data[index]; end end end end
// if not process image, select the point_data_out, else select point_data_in // assign bmp_data_out = image_write_done ? point_data_out : point_data_in; assign bmp_data_out = point_data_out; always @ (posedge clk or negedge rst_n) begin if(!rst_n) begin data_read_start_d1 <= 1'b0; end else data_read_start_d1 <= data_read_start; end
// write the bmp data integer bmp_file_write; initial begin bmp_file_write = $fopen(".\\picture_histogram_equalization.bmp","wb"); end // write the data every clock always @ (posedge clk) begin if(rst_n) begin // when index=0, not write if(data_read_start_d1) $fwrite(bmp_file_write, "%c", bmp_data_out); else if(data_read_done) begin $fclose(bmp_file_write); $fclose(bmp_file_read); $display("Write bmp file complete, Close the file"); $finish; end end end //======================<Module Instance>====================== histogram_equalization u_histogram_equalization ( .clk (clk), .rst_n (rst_n), .valid_in (valid_in), .image_write_done (image_write_done), .bmp_write_done (bmp_write_done), .point_data_in (point_data_in), .point_data_out (point_data_out), .init_done (init_done), .data_read_start (data_read_start), .data_read_done (data_read_done) );