赞
踩
来源:Hack电子
该FPGA项目旨在详细展示如何使用Verilog处理图像,从Verilog中读取输入位图图像(.bmp),处理并将处理结果写入Verilog中的输出位图图像。提供了用于读取图像、图像处理和写入图像的完整 Verilog 代码 。
在这个FPGA Verilog项目中,一些简单的处理操作都是在Verilog中实现的,比如反相、亮度控制和阈值操作。图像处理操作由“parameter.v”文件选择,然后将处理后的图像数据写入位图图像 output.bmp 以供验证。所述图像读取Verilog代码作为图像传感器/摄像机的模型的Verilog,它可以是用于在实时的功能验证真正有用的操作FPGA图像处理项目。当您想查看 BMP 格式的输出图像时,图像写入部分对于测试也非常有用。在这个项目中,我在阅读部分添加了一些简单的图像处理代码来制作图像处理的示例,但是您可以轻松地将其删除以获得原始图像数据。学生提出的所有相关问题都在本文底部得到解答。首先,Verilog 不能直接读取图像。要在 Verilog 中读取 .bmp 图像,需要将图像从位图格式转换为十六进制格式。下面是将位图图像转换为 .hex 文件的 Matlab 示例代码。输入图像大小为 768x512,图像 .hex 文件包括位图图像的 R、G、B 数据。
- b=imread('kodim24.bmp'); % 24-bit BMP image RGB888
-
- k=1;
- for i=512:-1:1 % image is written from the last row to the first row
- for j=1:768
- a(k)=b(i,j,1);
- a(k+1)=b(i,j,2);
- a(k+2)=b(i,j,3);
- k=k+3;
- end
- end
- fid = fopen('kodim24.hex', 'wt');
- fprintf(fid, '%x\n', a);
- disp('Text file write done');disp(' ');
- fclose(fid);
要读取图像十六进制数据文件,Verilog 使用以下命令:或readmemb 如果图像数据在二进制文本文件中。读取图像.hex 文件后,将RGB 图像数据保存到内存中并读出进行处理。
下面是图像读取和处理部分的Verilog代码:
- /***************************************************** *****************************/
- /******************** 模块用于读取和处理图像 **************/
- /***************************** ****************************************************/
- /******************************************************************************/
- /****************** Module for reading and processing image **************/
- /******************************************************************************/
- `include "parameter.v" // Include definition file
- // fpga4student.com: FPGA projects for students
- // FPGA project: Image processing in Verilog
- module image_read
- #(
- parameter WIDTH = 768, // Image width
- HEIGHT = 512, // Image height
- INFILE = "./img/kodim01.hex", // image file
- START_UP_DELAY = 100, // Delay during start up time
- HSYNC_DELAY = 160,// Delay between HSYNC pulses
- VALUE= 100, // value for Brightness operation
- THRESHOLD= 90, // Threshold value for Threshold operation
- SIGN=1 // Sign value using for brightness operation
- // SIGN = 0: Brightness subtraction
- // SIGN = 1: Brightness addition
- )
- (
- input HCLK, // clock
- input HRESETn, // Reset (active low)
- output VSYNC, // Vertical synchronous pulse
- // This signal is often a way to indicate that one entire image is transmitted.
- // Just create and is not used, will be used once a video or many images are transmitted.
- output reg HSYNC, // Horizontal synchronous pulse
- // An HSYNC indicates that one line of the image is transmitted.
- // Used to be a horizontal synchronous signals for writing bmp file.
- output reg [7:0] DATA_R0, // 8 bit Red data (even)
- output reg [7:0] DATA_G0, // 8 bit Green data (even)
- output reg [7:0] DATA_B0, // 8 bit Blue data (even)
- output reg [7:0] DATA_R1, // 8 bit Red data (odd)
- output reg [7:0] DATA_G1, // 8 bit Green data (odd)
- output reg [7:0] DATA_B1, // 8 bit Blue data (odd)
- // Process and transmit 2 pixels in parallel to make the process faster, you can modify to transmit 1 pixels or more if needed
- output ctrl_done // Done flag
- );
- //-------------------------------------------------
- // Internal Signals
- //-------------------------------------------------
- parameter sizeOfWidth = 8; // data width
- parameter sizeOfLengthReal = 1179648; // image data : 1179648 bytes: 512 * 768 *3
- // local parameters for FSM
- localparam ST_IDLE = 2'b00,// idle state
- ST_VSYNC = 2'b01,// state for creating vsync
- ST_HSYNC = 2'b10,// state for creating hsync
- ST_DATA = 2'b11;// state for data processing
- reg [1:0] cstate, // current state
- nstate; // next state
- reg start; // start signal: trigger Finite state machine beginning to operate
- reg HRESETn_d; // delayed reset signal: use to create start signal
- reg ctrl_vsync_run; // control signal for vsync counter
- reg [8:0] ctrl_vsync_cnt; // counter for vsync
- reg ctrl_hsync_run; // control signal for hsync counter
- reg [8:0] ctrl_hsync_cnt; // counter for hsync
- reg ctrl_data_run; // control signal for data processing
- reg [7 : 0] total_memory [0 : sizeOfLengthReal-1];// memory to store 8-bit data image
- // temporary memory to save image data : size will be WIDTH*HEIGHT*3
- integer temp_BMP [0 : WIDTH*HEIGHT*3 - 1];
- integer org_R [0 : WIDTH*HEIGHT - 1]; // temporary storage for R component
- integer org_G [0 : WIDTH*HEIGHT - 1]; // temporary storage for G component
- integer org_B [0 : WIDTH*HEIGHT - 1]; // temporary storage for B component
- // counting variables
- integer i, j;
- // temporary signals for calculation: details in the paper.
- integer tempR0,tempR1,tempG0,tempG1,tempB0,tempB1; // temporary variables in contrast and brightness operation
- integer value,value1,value2,value4;// temporary variables in invert and threshold operation
- reg [ 9:0] row; // row index of the image
- reg [10:0] col; // column index of the image
- reg [18:0] data_count; // data counting for entire pixels of the image
- //-------------------------------------------------//
- // -------- Reading data from input file ----------//
- //-------------------------------------------------//
- initial begin
- $readmemh(INFILE,total_memory,0,sizeOfLengthReal-1); // read file from INFILE
- end
- // use 3 intermediate signals RGB to save image data
- always@(start) begin
- if(start == 1'b1) begin
- for(i=0; i<WIDTH*HEIGHT*3 ; i=i+1) begin
- temp_BMP[i] = total_memory[i+0][7:0];
- end
-
- for(i=0; i<HEIGHT; i=i+1) begin
- for(j=0; j<WIDTH; j=j+1) begin
- // Matlab code writes image from the last row to the first row
- // Verilog code does the same in reading to correctly save image pixels into 3 separate RGB mem
- org_R[WIDTH*i+j] = temp_BMP[WIDTH*3*(HEIGHT-i-1)+3*j+0]; // save Red component
- org_G[WIDTH*i+j] = temp_BMP[WIDTH*3*(HEIGHT-i-1)+3*j+1];// save Green component
- org_B[WIDTH*i+j] = temp_BMP[WIDTH*3*(HEIGHT-i-1)+3*j+2];// save Blue component
- end
- end
- end
- end
- //----------------------------------------------------//
- // ---Begin to read image file once reset was high ---//
- // ---by creating a starting pulse (start)------------//
- //----------------------------------------------------//
- always@(posedge HCLK, negedge HRESETn)
- begin
- if(!HRESETn) begin
- start <= 0;
- HRESETn_d <= 0;
- end
- else begin // ______
- HRESETn_d <= HRESETn; // | |
- if(HRESETn == 1'b1 && HRESETn_d == 1'b0) // __0___| 1 |___0____ : starting pulse
- start <= 1'b1;
- else
- start <= 1'b0;
- end
- end
- //-----------------------------------------------------------------------------------------------//
- // Finite state machine for reading RGB888 data from memory and creating hsync and vsync pulses --//
- //-----------------------------------------------------------------------------------------------//
- always@(posedge HCLK, negedge HRESETn)
- begin
- if(~HRESETn) begin
- cstate <= ST_IDLE;
- end
- else begin
- cstate <= nstate; // update next state
- end
- end
- //-----------------------------------------//
- //--------- State Transition --------------//
- //-----------------------------------------//
- // IDLE . VSYNC . HSYNC . DATA
- always @(*) begin
- case(cstate)
- ST_IDLE: begin
- if(start)
- nstate = ST_VSYNC;
- else
- nstate = ST_IDLE;
- end
- ST_VSYNC: begin
- if(ctrl_vsync_cnt == START_UP_DELAY)
- nstate = ST_HSYNC;
- else
- nstate = ST_VSYNC;
- end
- ST_HSYNC: begin
- if(ctrl_hsync_cnt == HSYNC_DELAY)
- nstate = ST_DATA;
- else
- nstate = ST_HSYNC;
- end
- ST_DATA: begin
- if(ctrl_done)
- nstate = ST_IDLE;
- else begin
- if(col == WIDTH - 2)
- nstate = ST_HSYNC;
- else
- nstate = ST_DATA;
- end
- end
- endcase
- end
- // ------------------------------------------------------------------- //
- // --- counting for time period of vsync, hsync, data processing ---- //
- // ------------------------------------------------------------------- //
- always @(*) begin
- ctrl_vsync_run = 0;
- ctrl_hsync_run = 0;
- ctrl_data_run = 0;
- case(cstate)
- ST_VSYNC: begin ctrl_vsync_run = 1; end // trigger counting for vsync
- ST_HSYNC: begin ctrl_hsync_run = 1; end // trigger counting for hsync
- ST_DATA: begin ctrl_data_run = 1; end // trigger counting for data processing
- endcase
- end
- // counters for vsync, hsync
- always@(posedge HCLK, negedge HRESETn)
- begin
- if(~HRESETn) begin
- ctrl_vsync_cnt <= 0;
- ctrl_hsync_cnt <= 0;
- end
- else begin
- if(ctrl_vsync_run)
- ctrl_vsync_cnt <= ctrl_vsync_cnt + 1; // counting for vsync
- else
- ctrl_vsync_cnt <= 0;
-
- if(ctrl_hsync_run)
- ctrl_hsync_cnt <= ctrl_hsync_cnt + 1; // counting for hsync
- else
- ctrl_hsync_cnt <= 0;
- end
- end
- // counting column and row index for reading memory
- always@(posedge HCLK, negedge HRESETn)
- begin
- if(~HRESETn) begin
- row <= 0;
- col <= 0;
- end
- else begin
- if(ctrl_data_run) begin
- if(col == WIDTH - 2) begin
- row <= row + 1;
- end
- if(col == WIDTH - 2)
- col <= 0;
- else
- col <= col + 2; // reading 2 pixels in parallel
- end
- end
- end
- //-------------------------------------------------//
- //----------------Data counting---------- ---------//
- //-------------------------------------------------//
- always@(posedge HCLK, negedge HRESETn)
- begin
- if(~HRESETn) begin
- data_count <= 0;
- end
- else begin
- if(ctrl_data_run)
- data_count <= data_count + 1;
- end
- end
- assign VSYNC = ctrl_vsync_run;
- assign ctrl_done = (data_count == 196607)? 1'b1: 1'b0; // done flag
- //-------------------------------------------------//
- //------------- Image processing ---------------//
- //-------------------------------------------------//
- always @(*) begin
-
- HSYNC = 1'b0;
- DATA_R0 = 0;
- DATA_G0 = 0;
- DATA_B0 = 0;
- DATA_R1 = 0;
- DATA_G1 = 0;
- DATA_B1 = 0;
- if(ctrl_data_run) begin
-
- HSYNC = 1'b1;
- `ifdef BRIGHTNESS_OPERATION
- /**************************************/
- /* BRIGHTNESS ADDITION OPERATION */
- /**************************************/
- if(SIGN == 1) begin
- // R0
- tempR0 = org_R[WIDTH * row + col ] + VALUE;
- if (tempR0 > 255)
- DATA_R0 = 255;
- else
- DATA_R0 = org_R[WIDTH * row + col ] + VALUE;
- // R1
- tempR1 = org_R[WIDTH * row + col+1 ] + VALUE;
- if (tempR1 > 255)
- DATA_R1 = 255;
- else
- DATA_R1 = org_R[WIDTH * row + col+1 ] + VALUE;
- // G0
- tempG0 = org_G[WIDTH * row + col ] + VALUE;
- if (tempG0 > 255)
- DATA_G0 = 255;
- else
- DATA_G0 = org_G[WIDTH * row + col ] + VALUE;
- tempG1 = org_G[WIDTH * row + col+1 ] + VALUE;
- if (tempG1 > 255)
- DATA_G1 = 255;
- else
- DATA_G1 = org_G[WIDTH * row + col+1 ] + VALUE;
- // B
- tempB0 = org_B[WIDTH * row + col ] + VALUE;
- if (tempB0 > 255)
- DATA_B0 = 255;
- else
- DATA_B0 = org_B[WIDTH * row + col ] + VALUE;
- tempB1 = org_B[WIDTH * row + col+1 ] + VALUE;
- if (tempB1 > 255)
- DATA_B1 = 255;
- else
- DATA_B1 = org_B[WIDTH * row + col+1 ] + VALUE;
- end
- else begin
- /**************************************/
- /* BRIGHTNESS SUBTRACTION OPERATION */
- /**************************************/
- // R0
- tempR0 = org_R[WIDTH * row + col ] - VALUE;
- if (tempR0 < 0)
- DATA_R0 = 0;
- else
- DATA_R0 = org_R[WIDTH * row + col ] - VALUE;
- // R1
- tempR1 = org_R[WIDTH * row + col+1 ] - VALUE;
- if (tempR1 < 0)
- DATA_R1 = 0;
- else
- DATA_R1 = org_R[WIDTH * row + col+1 ] - VALUE;
- // G0
- tempG0 = org_G[WIDTH * row + col ] - VALUE;
- if (tempG0 < 0)
- DATA_G0 = 0;
- else
- DATA_G0 = org_G[WIDTH * row + col ] - VALUE;
- tempG1 = org_G[WIDTH * row + col+1 ] - VALUE;
- if (tempG1 < 0)
- DATA_G1 = 0;
- else
- DATA_G1 = org_G[WIDTH * row + col+1 ] - VALUE;
- // B
- tempB0 = org_B[WIDTH * row + col ] - VALUE;
- if (tempB0 < 0)
- DATA_B0 = 0;
- else
- DATA_B0 = org_B[WIDTH * row + col ] - VALUE;
- tempB1 = org_B[WIDTH * row + col+1 ] - VALUE;
- if (tempB1 < 0)
- DATA_B1 = 0;
- else
- DATA_B1 = org_B[WIDTH * row + col+1 ] - VALUE;
- end
- `endif
- /**************************************/
- /* INVERT_OPERATION */
- /**************************************/
- `ifdef INVERT_OPERATION
- value2 = (org_B[WIDTH * row + col ] + org_R[WIDTH * row + col ] +org_G[WIDTH * row + col ])/3;
- DATA_R0=255-value2;
- DATA_G0=255-value2;
- DATA_B0=255-value2;
- value4 = (org_B[WIDTH * row + col+1 ] + org_R[WIDTH * row + col+1 ] +org_G[WIDTH * row + col+1 ])/3;
- DATA_R1=255-value4;
- DATA_G1=255-value4;
- DATA_B1=255-value4;
- `endif
- /**************************************/
- /********THRESHOLD OPERATION *********/
- /**************************************/
- `ifdef THRESHOLD_OPERATION
- value = (org_R[WIDTH * row + col ]+org_G[WIDTH * row + col ]+org_B[WIDTH * row + col ])/3;
- if(value > THRESHOLD) begin
- DATA_R0=255;
- DATA_G0=255;
- DATA_B0=255;
- end
- else begin
- DATA_R0=0;
- DATA_G0=0;
- DATA_B0=0;
- end
- value1 = (org_R[WIDTH * row + col+1 ]+org_G[WIDTH * row + col+1 ]+org_B[WIDTH * row + col+1 ])/3;
- if(value1 > THRESHOLD) begin
- DATA_R1=255;
- DATA_G1=255;
- DATA_B1=255;
- end
- else begin
- DATA_R1=0;
- DATA_G1=0;
- DATA_B1=0;
- end
- `endif
- end
- end
- endmodule

“parameter.v”文件也是定义输入输出文件的路径和名称。对图像进行处理后,需要将处理后的数据写入输出图像进行验证。
以下Verilog代码是将处理后的图像数据写入位图图像进行验证:
- /******************** 写入.bmp图像的模块************/
- /********** ****************************************************/
- module image_write #(parameter
- WIDTH = 768, // Image width
- HEIGHT = 512, // Image height
- INFILE = "output.bmp", // Output image
- BMP_HEADER_NUM = 54 // Header for bmp image
- )
- (
- input HCLK, // Clock input
- HRESETn, // Reset active low
- input hsync, // Hsync pulse
- input [7:0] DATA_WRITE_R0, // Red 8-bit data (odd)
- input [7:0] DATA_WRITE_G0, // Green 8-bit data (odd)
- input [7:0] DATA_WRITE_B0, // Blue 8-bit data (odd)
- input [7:0] DATA_WRITE_R1, // Red 8-bit data (even)
- input [7:0] DATA_WRITE_G1, // Green 8-bit data (even)
- input [7:0] DATA_WRITE_B1, // Blue 8-bit data (even)
- output reg Write_Done
- );
- // fpga4student.com FPGA projects, Verilog projects, VHDL projects
- //-----------------------------------//
- //-------Header data for bmp image-----//
- //-------------------------------------//
- // Windows BMP files begin with a 54-byte header
- initial begin
- BMP_header[ 0] = 66;BMP_header[28] =24;
- BMP_header[ 1] = 77;BMP_header[29] = 0;
- BMP_header[ 2] = 54;BMP_header[30] = 0;
- BMP_header[ 3] = 0;BMP_header[31] = 0;
- BMP_header[ 4] = 18;BMP_header[32] = 0;
- BMP_header[ 5] = 0;BMP_header[33] = 0;
- BMP_header[ 6] = 0;BMP_header[34] = 0;
- BMP_header[ 7] = 0;BMP_header[35] = 0;
- BMP_header[ 8] = 0;BMP_header[36] = 0;
- BMP_header[ 9] = 0;BMP_header[37] = 0;
- BMP_header[10] = 54;BMP_header[38] = 0;
- BMP_header[11] = 0;BMP_header[39] = 0;
- BMP_header[12] = 0;BMP_header[40] = 0;
- BMP_header[13] = 0;BMP_header[41] = 0;
- BMP_header[14] = 40;BMP_header[42] = 0;
- BMP_header[15] = 0;BMP_header[43] = 0;
- BMP_header[16] = 0;BMP_header[44] = 0;
- BMP_header[17] = 0;BMP_header[45] = 0;
- BMP_header[18] = 0;BMP_header[46] = 0;
- BMP_header[19] = 3;BMP_header[47] = 0;
- BMP_header[20] = 0;BMP_header[48] = 0;
- BMP_header[21] = 0;BMP_header[49] = 0;
- BMP_header[22] = 0;BMP_header[50] = 0;
- BMP_header[23] = 2;BMP_header[51] = 0;
- BMP_header[24] = 0;BMP_header[52] = 0;
- BMP_header[25] = 0;BMP_header[53] = 0;
- BMP_header[26] = 1; BMP_header[27] = 0;
- end
- //---------------------------------------------------------//
- //--------------Write .bmp file ----------------------//
- //----------------------------------------------------------//
- initial begin
- fd = $fopen(INFILE, "wb+");
- end
- always@(Write_Done) begin // once the processing was done, bmp image will be created
- if(Write_Done == 1'b1) begin
- for(i=0; i<BMP_HEADER_NUM; i=i+1) begin
- $fwrite(fd, "%c", BMP_header[i][7:0]); // write the header
- end
-
- for(i=0; i<WIDTH*HEIGHT*3; i=i+6) begin
- // write R0B0G0 and R1B1G1 (6 bytes) in a loop
- $fwrite(fd, "%c", out_BMP[i ][7:0]);
- $fwrite(fd, "%c", out_BMP[i+1][7:0]);
- $fwrite(fd, "%c", out_BMP[i+2][7:0]);
- $fwrite(fd, "%c", out_BMP[i+3][7:0]);
- $fwrite(fd, "%c", out_BMP[i+4][7:0]);
- $fwrite(fd, "%c", out_BMP[i+5][7:0]);
- end
- end
- end

位图图像的标头数据非常重要,在这里发布。如果没有标题数据,则无法正确显示写入的图像。在 Verilog HDL 中,$fwrite 命令用于将数据写入文件。
接下来,让我们编写一个测试平台 Verilog 代码来验证图像处理操作。
- `timescale 1ns/1ps /**************************************************/
- /******* Testbench for simulation ****************/
- /*********************************************/
- // fpga4student.com FPGA projects, Verilog projects, VHDL projects
- // Verilog project: Image processing in Verilog
- `include "parameter.v" // include definition file module tb_simulation;
- //------------------ // Internal Signals
- //-------------------------------------------------
- reg HCLK, HRESETn;
- wire vsync;
- wire hsync;
- wire [ 7 : 0] data_R0;
- wire [ 7 : 0] data_G0;
- wire [ 7 : 0] data_B0;
- wire [ 7 : 0] data_R1;
- wire [ 7 : 0] data_G1;
- wire [ 7 : 0] data_B1;
- wire enc_done;
- image_read #(.INFILE(`INPUTFILENAME))
- u_image_read
- ( .HCLK (HCLK ),
- .HRESETn (HRESETn ),
- .VSYNC (vsync ),
- .HSYNC (hsync ),
- .DATA_R0 (data_R0 ),
- .DATA_G0 (data_G0 ),
- .DATA_B0 (data_B0 ),
- .DATA_R1 (data_R1 ),
- .DATA_G1 (data_G1 ),
- .DATA_B1 (data_B1 ),
- .ctrl_done (enc_done)
- );
- image_write #(.INFILE(`OUTPUTFILENAME))
- u_image_write (
- .HCLK(HCLK),
- .HRESETn(HRESETn),
- .hsync(hsync),
- .DATA_WRITE_R0(data_R0),
- .DATA_WRITE_G0(data_G0),
- .DATA_WRITE_B0(data_B0),
- .DATA_WRITE_R1(data_R1),
- .DATA_WRITE_G1(data_G1),
- .DATA_WRITE_B1(data_B1),
- .Write_Done()
- );
- //------------- // Test Vectors
- //-------------------------------------
- initial
- begin
- HCLK = 0;
- forever #10 HCLK = ~HCLK;
- end
- initial
- begin
- HRESETn = 0;
- #25 HRESETn = 1;
- end endmodule

最后,我们拥有一切来运行模拟来验证图像处理代码。让我们使用下图作为输入位图文件:
运行仿真 6ms,关闭仿真并打开输出图像以检查结果。以下是参数.v中选定操作处理的输出图像:
反转后输出位图图像
阈值操作后输出位图图像
减去亮度后输出位图图像
由于读取代码是为了模拟目的而对图像传感器/相机进行建模,因此建议不要合成代码。如果你真的想综合处理代码并直接在FPGA上运行,你需要将代码中的这些图像数组(total_memory、temp_BMP、org_R、org_B、org_G)替换为块存储器(RAM)和设计地址生成器来读取图像块内存中的数据。
问题的答案:
此图像处理项目的完整 Verilog 代码可在此处下载。运行模拟大约 6ms 并关闭模拟,然后您将能够看到输出图像。
https://github.com/suisuisi/FPGAandImage/blob/main/Image/012_Others/Verilog_Image_Processing.zip
读取部分作为图像传感器/相机的 Verilog 模型运行(输出 RGB 数据、HSYNC、VSYNC、HCLK)。Verilog 图像读取代码对于实时 FPGA 图像/视频项目中的功能验证非常有用。
3.在这个项目中,我添加了图像处理部分,做一个图像增强的例子。如果您只想使用图像传感器模型来验证您的图像处理设计,您可以轻松移除处理部分以仅获取原始图像数据。
4.图像保存到三个独立的RGB mem中:由于Matlab代码是将图像16进制文件从最后一行写到第一行,所以RGB保存代码(org_R, org_B, org_G)在读取temp_BMP内存时也是这样做的,保存RGB数据正确。如果您想以不同的方式进行,您可以相应地更改它。
如果您想更改图像大小,您可能会发现以下对 BMP 标题的解释很有用:
- 图像大小 = 768*512*3= 1179648 字节
- BMP 标题 = 54 字节
- BMP 文件大小 = 图像大小 + BMP 标题 = 1179702 字节
- 将其转换为十六进制数:1179702 in Decimal = 120036 in Hexade
- 然后 BMP 文件的 4 字节大小:00H, 12 in Hexa = 18 Decimal, 00H, 36 in Hexa = 54 Decimal
- 这就是我们如何得到以下值:
- BMP_header[2] = 54;
- BMP_header[3] = 0;
- BMP_header[4] = 18;
- BMP_header[5] = 0;
- 图像宽度 = 768 => 十六进制:0x0300。图像宽度的 4 个字节是
- 0、3、0、0。这就是您获得以下值的方式:BMP_header[18] = 0;
- BMP_header[19] = 3;
- BMP_header[20] = 0;
- BMP_header[21] = 0;
- 图像高度 = 512 => 十六进制:0x0200。图像宽度的 4 个字节是 0, 2, 0, 0。这就是我们如何得到以下值:
- BMP_header[22] = 0;
- BMP_header[23] = 2;
- BMP_header[24] = 0;
- BMP_header[25] = 0;

您不应综合此代码,因为它不是为在 FPGA 上运行而设计的,而是用于功能验证目的. 如果你真的想合成这段代码(读取和处理)并将图像加载到 FPGA中直接在 FPGA 上处理,请将所有 temp. 变量 (org_R, org_B, org_G, tmp_BMP = total_memory) 并生成地址以读取图像数据(删除 always @(start) 和所有“for 循环” - 这些用于模拟目的)。有两种方式:1. 写一段RAM代码,用$readmemh将图像数据初始化到内存中;2. 使用 Xilinx Core Generator 或 Altera MegaFunction 生成块存储器并将图像数据加载到存储器的初始值(Xilinx Core Gen. 为 .coe 文件,Altera MegaFunction 为 .mif 文件),然后从存储器中读取图像数据并处理它(FSM 设计)。
在这个项目中,为了加快处理速度,同时读取两个偶数和旧像素,但您可以根据您的设计更改正在读取的像素数。
编写Verilog代码对于测试目的也非常有帮助,因为您可以看到BMP 格式的输出。
9.如果要做实时图像处理,可以查看camera接口代码这个:https://www.fpga4student.com/2018/08/basys-3-fpga-ov7670-camera.html
参考:https://www.fpga4student.com/2016/11/image-processing-on-fpga-verilog.html
NOW现在行动!
学习Xilinx FPGA最好的资料其实就是官方手册,下表总结了部分手册的主要介绍内容,关注我,持续更新中......
文件名 | 主标题 | 内容简单介绍 | 是否有中文版 | |
UG476 | 7 Series FPGAs GTX/GTH Transceivers | GTX和GTH介绍,PCIe、serdes等学习必备 | 否 | |
UG471 | 7 Series FPGAs SelectIO Resources | 描述 7 系列 FPGA 中可用的 SelectIO资源。 | 否 | |
UG1114 | PetaLinux Tools Documentaton | PetaLinux 工具文档 参考指南 | 是,V2019.2 | |
UG949 | UltraFAST 设计方法指南(适用于 Vivado Design Suite) | 赛灵思® UltraFast™ 设计方法是用于为当今器件优化设计进程的一套最佳实践。这些设计的规模与复杂性需要执行特定的步骤与设计任务,从而确保设计每一个阶段的成功开展。依照这些步骤,并遵循最佳实践,将帮助您以最快的速度和最高的效率实现期望的设计目标 | 是,V2018.1 | |
IP手册 | pg057 | FIFO Generator | FIFO生成器IP使用手册 | 否 |
pg104 | Complex Multiplier | 复数乘法器IP使用手册 | 否 | |
pg122 | RAM-Based Shift Register | 移位寄存器IP使用手册 | 否 |
推荐阅读
【Vivado那些事】Vivado中常用的快捷键(二)其他常用快捷键
图书推荐|ARM Cortex-M0 全可编程SoC原理及实现
1202年了,还在使用虚拟机吗?Win10安装Ubuntu子系统及图形化界面详细教程
Github 上有哪些优秀的 VHDL/Verilog/FPGA 项目
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。