該FPGA項目旨在詳細展示如何使用Verilog處理圖像,從Verilog中讀取輸入位圖圖像(.bmp),處理并將處理結果寫入Verilog中的輸出位圖圖像。提供了用于讀取圖像、圖像處理和寫入圖像的完整 Verilog 代碼 。
在這個FPGA Verilog項目中,一些簡單的處理操作都是在Verilog中實現(xiàn)的,比如反相、亮度控制和閾值操作。圖像處理操作由“parameter.v”文件選擇,然后將處理后的圖像數(shù)據寫入位圖圖像 output.bmp 以供驗證。所述圖像讀取Verilog代碼作為圖像傳感器/攝像機的模型的Verilog,它可以是用于在實時的功能驗證真正有用的操作FPGA圖像處理項目。當您想查看 BMP 格式的輸出圖像時,圖像寫入部分對于測試也非常有用。在這個項目中,我在閱讀部分添加了一些簡單的圖像處理代碼來制作圖像處理的示例,但是您可以輕松地將其刪除以獲得原始圖像數(shù)據。學生提出的所有相關問題都在本文底部得到解答。首先,Verilog 不能直接讀取圖像。要在 Verilog 中讀取 .bmp 圖像,需要將圖像從位圖格式轉換為十六進制格式。下面是將位圖圖像轉換為 .hex 文件的 Matlab 示例代碼。輸入圖像大小為 768x512,圖像 .hex 文件包括位圖圖像的 R、G、B 數(shù)據。
b=imread(‘kodim24.bmp’); % 24-bit BMP image RGB888
k=1;
for i=5121 % 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
’, a);
disp(‘Text file write done’);disp(‘ ’);
fclose(fid);
要讀取圖像十六進制數(shù)據文件,Verilog 使用以下命令:readmemb 如果圖像數(shù)據在二進制文本文件中。讀取圖像.hex 文件后,將RGB 圖像數(shù)據保存到內存中并讀出進行處理。
下面是圖像讀取和處理部分的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”文件也是定義輸入輸出文件的路徑和名稱。對圖像進行處理后,需要將處理后的數(shù)據寫入輸出圖像進行驗證。
以下Verilog代碼是將處理后的圖像數(shù)據寫入位圖圖像進行驗證:
/******************** 寫入.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
位圖圖像的標頭數(shù)據非常重要,在這里發(fā)布。如果沒有標題數(shù)據,則無法正確顯示寫入的圖像。在 Verilog HDL 中,$fwrite 命令用于將數(shù)據寫入文件。
接下來,讓我們編寫一個測試平臺 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,關閉仿真并打開輸出圖像以檢查結果。以下是參數(shù).v中選定操作處理的輸出圖像:
由于讀取代碼是為了模擬目的而對圖像傳感器/相機進行建模,因此建議不要合成代碼。如果你真的想綜合處理代碼并直接在FPGA上運行,你需要將代碼中的這些圖像數(shù)組(total_memory、temp_BMP、org_R、org_B、org_G)替換為塊存儲器(RAM)和設計地址生成器來讀取圖像塊內存中的數(shù)據。
問題的答案:
此圖像處理項目的完整 Verilog 代碼可在此處下載。運行模擬大約 6ms 并關閉模擬,然后您將能夠看到輸出圖像。
https://github.com/suisuisi/FPGAandImage/blob/main/Image/012_Others/Verilog_Image_Processing.zip
讀取部分作為圖像傳感器/相機的 Verilog 模型運行(輸出 RGB 數(shù)據、HSYNC、VSYNC、HCLK)。Verilog 圖像讀取代碼對于實時 FPGA 圖像/視頻項目中的功能驗證非常有用。
3.在這個項目中,我添加了圖像處理部分,做一個圖像增強的例子。如果您只想使用圖像傳感器模型來驗證您的圖像處理設計,您可以輕松移除處理部分以僅獲取原始圖像數(shù)據。
4.圖像保存到三個獨立的RGB mem中:由于Matlab代碼是將圖像16進制文件從最后一行寫到第一行,所以RGB保存代碼(org_R, org_B, org_G)在讀取temp_BMP內存時也是這樣做的,保存RGB數(shù)據正確。如果您想以不同的方式進行,您可以相應地更改它。
如果您想更改圖像大小,您可能會發(fā)現(xiàn)以下對 BMP 標題的解釋很有用:
圖像大小 = 768*512*3= 1179648 字節(jié)
BMP 標題 = 54 字節(jié)
BMP 文件大小 = 圖像大小 + BMP 標題 = 1179702 字節(jié)
將其轉換為十六進制數(shù):1179702 in Decimal = 120036 in Hexade
然后 BMP 文件的 4 字節(jié)大小: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 個字節(jié)是
0、3、0、0。這就是您獲得以下值的方式:BMP_header[18] = 0;
BMP_header[19] = 3;
BMP_header[20] = 0;
BMP_header[21] = 0;
圖像高度 = 512 =》 十六進制:0x0200。圖像寬度的 4 個字節(jié)是 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) 并生成地址以讀取圖像數(shù)據(刪除 always @(start) 和所有“for 循環(huán)” - 這些用于模擬目的)。有兩種方式:1. 寫一段RAM代碼,用$readmemh將圖像數(shù)據初始化到內存中;2. 使用 Xilinx Core Generator 或 Altera MegaFunction 生成塊存儲器并將圖像數(shù)據加載到存儲器的初始值(Xilinx Core Gen. 為 .coe 文件,Altera MegaFunction 為 .mif 文件),然后從存儲器中讀取圖像數(shù)據并處理它(FSM 設計)。
在這個項目中,為了加快處理速度,同時讀取兩個偶數(shù)和舊像素,但您可以根據您的設計更改正在讀取的像素數(shù)。
編寫Verilog代碼對于測試目的也非常有幫助,因為您可以看到BMP 格式的輸出。
9.如果要做實時圖像處理,可以查看camera接口代碼這個:https://www.fpga4student.com/2018/08/basys-3-fpga-ov7670-camera.html
責任編輯:haq
-
FPGA
+關注
關注
1625文章
21620瀏覽量
601238 -
Verilog
+關注
關注
28文章
1343瀏覽量
109925 -
HDL
+關注
關注
8文章
326瀏覽量
47307
原文標題:使用 Verilog HDL 在 FPGA 上進行圖像處理
文章出處:【微信號:Open_FPGA,微信公眾號:OpenFPGA】歡迎添加關注!文章轉載請注明出處。
發(fā)布評論請先 登錄
相關推薦
評論