我们在做FPGA图像处理中,有些时候写算法的时候,需要查看图像算法处理之后的效果如何,来验证自己算法的正确性,可能身边没有板子,我们可以通过Vivado仿真结果,来验证算法的正确性。
本文在Vivado中搭建一个基本的图像算法处理仿真平台。将一个车牌bmp图像文件读取进来,然后按照摄像头的时序输出来,通过RGB888转YCbCr提取Cb分量,然后在经过二值化算法,提取车牌信息。
开发环境:Vivado
工程架构:
仿真时间14ms,Vivado图像仿真结果如下:
为了验证自己的算法是否正确,我们需要通过matlab也做图像算法处理,然后对比matlab和Vivado两者的输出图像差别。
matlab代码如下,matlab代码按照Vivado图像算法写的,也会输出图像处理结果。
clc;
clear all;
close all;
FID = fopen('G:\picture_deal\image_prj\erzhihua\chepai.bmp','r');%图像读入
FID_output = fopen('G:\picture_deal\image_prj\erzhihua\matlab_output.bmp','w');%图像算法处理后输出结果
bmp_all_data=fread(FID,'uint8');
bmp_all_data_output=bmp_all_data;
bmp_frame_header_data = bmp_all_data(1:54);
%从帧头读取图像的宽度和高度
width_temp=dec2hex(bmp_frame_header_data(19:22),2);
height_temp=dec2hex(bmp_frame_header_data(23:26),2);
for i=1:4
width_str(9-2*i:9-2*i+1)=width_temp(i,:);
height_str(9-2*i:9-2*i+1)=height_temp(i,:);
end
width=hex2dec(width_str);
height=hex2dec(height_str);
%截取RGB数据
bmp_rgb_image_data = bmp_all_data(55:end);
bmp_rgb_image_data1 = reshape(bmp_rgb_image_data,3,width*height);
R_data = reshape(bmp_rgb_image_data1(3,:),width,height)';
G_data = reshape(bmp_rgb_image_data1(2,:),width,height)';
B_data = reshape(bmp_rgb_image_data1(1,:),width,height)';
%Y = 0.299R + 0.587G + 0.114B
%Cb = -0.172R - 0.339G + 0.511B + 128;
%Cr = 0.511R - 0.428G - 0.083B + 128;
% 我们现在处理全部按照FPGA中处理,扩大 256 倍,转换如下
%Y = (77R + 150G + 29B)/256
%Cb = (-44R - 87G + 130B)/256 + 128;
%Cr = (128R - 107G - 21B)/256 + 128;
for r = 1:height
for c = 1:width
Y_data(r, c) = uint8((77*R_data(r, c) + 150*G_data(r, c) + 29*B_data(r, c))/256);
Cb_data(r, c) = uint8((-43*R_data(r, c) - 85*G_data(r, c) + 128*B_data(r, c))/256 + 128);
Cr_data(r, c) = uint8((128*R_data(r, c) - 107*G_data(r, c) - 21*B_data(r, c))/256 + 128);
end
end
figure(1);
I=flipdim(Cb_data,1);%原图像的水平镜像
imshow(I);
title('Cb分量图像');
%二值化算法
erzhihua_data = zeros(height,width);
for r = 1:height
for c = 1:width
if(Cb_data(r, c) < 150) %白的还是白的 %215
erzhihua_data(r,c) = 255; %白
else
erzhihua_data(r,c) = 0;%黑
end
end
end
figure(2);
I=flipdim(erzhihua_data,1);%二值化图像
imshow(I);
title('二值化图像');
R_data1 = reshape(erzhihua_data',1,height*width);
G_data1 = reshape(erzhihua_data',1,height*width);
B_data1 = reshape(erzhihua_data',1,height*width);
bmp_rgb_image_data_output = zeros(3,height*width);
bmp_rgb_image_data_output(1,:) = B_data1;
bmp_rgb_image_data_output(2,:) = G_data1;
bmp_rgb_image_data_output(3,:) = R_data1;
bmp_all_data_output(55:end) = reshape(bmp_rgb_image_data_output,1,width*height*3);
fwrite(FID_output,bmp_all_data_output);%图像算法处理后输出结果
fclose(FID);
fclose(FID_output);
matlab图像处理结果如下:
我们需要对比这两个图像的区别,看看像素点图像的结果相差是否在一定范围,下面这段代码就是比较两个图像的像素误差
clc;
clear all;
close all;
%matlab算法处理的图像
FID_matlab = fopen('G:\picture_deal\image_prj\erzhihua\matlab_output.bmp','r');
%FPGA处理的图像
FID_fpga = fopen('G:\picture_deal\image_prj\erzhihua\fpga_output.bmp','r');
bmp_all_data_matlab =fread(FID_matlab,'uint8');
bmp_all_data_fpga = fread(FID_fpga,'uint8');
bmp_frame_header_data = bmp_all_data_matlab(1:54);
%从帧头读取图像的宽度和高度
width_temp=dec2hex(bmp_frame_header_data(19:22),2);
height_temp=dec2hex(bmp_frame_header_data(23:26),2);
for i=1:4
width_str(9-2*i:9-2*i+1)=width_temp(i,:);
height_str(9-2*i:9-2*i+1)=height_temp(i,:);
end
width=hex2dec(width_str);
height=hex2dec(height_str);
%截取RGB数据
bmp_rgb_data_matlab = bmp_all_data_matlab(55:end);
bmp_rgb_data_fpga = bmp_all_data_fpga(55:end);
bmp_rgb_data_temp_matlab = reshape(bmp_rgb_data_matlab,3,width*height);
bmp_rgb_data_temp_fpga = reshape(bmp_rgb_data_fpga,3,width*height);
R_data_matlab = reshape(bmp_rgb_data_temp_matlab(3,:),width,height)';
G_data_matlab = reshape(bmp_rgb_data_temp_matlab(2,:),width,height)';
B_data_matlab = reshape(bmp_rgb_data_temp_matlab(1,:),width,height)';
R_data_fpga = reshape(bmp_rgb_data_temp_fpga(3,:),width,height)';
G_data_fpga = reshape(bmp_rgb_data_temp_fpga(2,:),width,height)';
B_data_fpga = reshape(bmp_rgb_data_temp_fpga(1,:),width,height)';
R_error = R_data_matlab - R_data_fpga;
fclose(FID_matlab);
fclose(FID_fpga);
通过查看R_error这个变量,我们可以看到误差为0,验证了Vivado仿真图像算法的正确性。
bmp_sim_VIP_tb代码:
`timescale 1ns / 1ns
module bmp_sim_VIP_tb();
integer iBmpFileId ; //输入BMP图片
integer oBmpFileId_1; //输出BMP图片
integer oTxtFiled ; //输入文本
integer iIndex = 0; //输入BMP数据索引
integer pixel_index = 0; //输入像素数据索引
integer iCode;
integer iBmpWidth; //输入BMP宽度
integer iBmpHight; //输入BMP高度
integer iBmpSize; //输入BMP字节数
integer iDataStartIndex; //输入BMP像素数据偏移量
reg [7:0] rBmpData [0:2000000] ; //用于寄存输入BMP图片中的字节数据(包括54字节的文件头)
reg [7:0] Vip_BmpData_1 [0:2000000] ; //用于寄存图像处理输出BMP图片
reg [7:0] rBmpWord ; //输出BMP图片时用于寄存数据(以word为单位,即4Byte)
reg [7:0] pixel_data ; //输出视频流时的像素数据
reg clk;
reg rst_n;
reg [7:0] vip_pixel_data_1[0:921600]; //680*480*3
initial begin
//打开输入BMP图片
iBmpFileId = $fopen("G:\\picture_deal\\image_prj\\erzhihua\\chepai.bmp","rb");
//将输入图片加载到数组中
iCode = $fread(rBmpData,iBmpFileId);
//根据BMP图片文件头的格式,分别计算出图片的宽度/高度/像素数据偏移量/图片字节数
iBmpWidth = {rBmpData[21],rBmpData[20],rBmpData[19],rBmpData[18]};
iBmpHight = {rBmpData[25],rBmpData[24],rBmpData[23],rBmpData[22]};
iBmpSize = {rBmpData[5],rBmpData[4],rBmpData[3],rBmpData[2]};
iDataStartIndex = {rBmpData[13],rBmpData[12],rBmpData[11],rBmpData[10]};
//关闭输入图片
$fclose(iBmpFileId);
//打开输出BMP图片
oBmpFileId_1 = $fopen("G:\\picture_deal\\image_prj\\erzhihua\\fpga_output.bmp","wb+");
//延迟13ms,等待第一帧图像处理结束
#13000000
//加载图像处理后,BMP图片的文件头和像素数据
//输出第一张
for (iIndex = 0; iIndex < iBmpSize; iIndex = iIndex + 1) begin
if(iIndex < 54) begin
Vip_BmpData_1[iIndex] = rBmpData[iIndex];
//$display("data %h",rBmpData[iIndex]);
end
else begin
Vip_BmpData_1[iIndex] = vip_pixel_data_1[iIndex-54];
end
end
//将数组中的数据写到输出的BMP图片中
for (iIndex = 0; iIndex < iBmpSize; iIndex = iIndex + 1) begin
rBmpWord = Vip_BmpData_1[iIndex];
$fwrite(oBmpFileId_1,"%c",rBmpWord);
end
//关闭输出BMP图片
$fclose(oBmpFileId_1);
end
//初始化时钟和复位信号
initial begin
clk = 1;
rst_n = 0;
#110
rst_n = 1;
end
always #10 clk = ~clk;
//在时钟驱动下,从数组中读取像素数据,用于在仿真中查看BMP数据
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
pixel_data <= 8'd0;
pixel_index <= 0;
end
else begin
pixel_data <= rBmpData[pixel_index];
pixel_index <= pixel_index +1;
end
end
//产生摄像头时序
wire cmos_vsync ;
reg cmos_href;
wire cmos_clken;
reg [23:0] cmos_data;
reg cmos_clken_r;
reg [31:0] cmos_index;
parameter [10:0] IMG_HDISP = 11'd640;
parameter [10:0] IMG_VDISP = 11'd480;
localparam H_SYNC = 11'd5;
localparam H_BACK = 11'd5;
localparam H_DISP = IMG_HDISP;
localparam H_FRONT = 11'd5;
localparam H_TOTAL = H_SYNC + H_BACK + H_DISP + H_FRONT;
localparam V_SYNC = 11'd1;
localparam V_BACK = 11'd0;
localparam V_DISP = IMG_VDISP;
localparam V_FRONT = 11'd1;
localparam V_TOTAL = V_SYNC + V_BACK + V_DISP + V_FRONT;
//模拟OV7725/OV5640 驱动模块输出的时钟使能
always@(posedge clk or negedge rst_n) begin
if(!rst_n)
cmos_clken_r <= 0;
else
cmos_clken_r <= ~cmos_clken_r;
end
//水平寄存器
reg [10:0] hcnt;
always@(posedge clk or negedge rst_n) begin
if(!rst_n)
hcnt <= 11'd0;
else if(cmos_clken_r)
hcnt <= (hcnt < H_TOTAL - 1'b1)? hcnt + 1'b1 : 11'd0;
end
//竖直寄存器
reg [10:0] vcnt;
always@(posedge clk or negedge rst_n) begin
if(!rst_n)
vcnt <= 11'd0;
else if(cmos_clken_r) begin
if(hcnt == H_TOTAL - 1'b1)
vcnt <= (vcnt < V_TOTAL - 1'b1)? vcnt + 1'b1 : 11'd0;
else
vcnt <= vcnt;
end
end
//场同步
reg cmos_vsync_r;
always@(posedge clk or negedge rst_n) begin
if(!rst_n)
cmos_vsync_r <= 1'b0;
else begin
if(vcnt <= V_SYNC - 1'b1)
cmos_vsync_r <= 1'b0;
else
cmos_vsync_r <= 1'b1;
end
end
assign cmos_vsync = cmos_vsync_r;
//行有效
wire frame_valid_ahead = (vcnt >= V_SYNC + V_BACK && vcnt < V_SYNC + V_BACK + V_DISP
&& hcnt >= H_SYNC + H_BACK && hcnt < H_SYNC + H_BACK + H_DISP)
? 1'b1 : 1'b0;
reg cmos_href_r;
always@(posedge clk or negedge rst_n) begin
if(!rst_n)
cmos_href_r <= 1'b0;
else begin
if(frame_valid_ahead)
cmos_href_r <= 1'b1;
else
cmos_href_r <= 1'b0;
end
end
always@(posedge clk or negedge rst_n) begin
if(!rst_n)
cmos_href <= 1'b0;
else begin
cmos_href <= cmos_href_r;
end
end
assign cmos_clken = cmos_href & cmos_clken_r;
//从数组中以视频格式输出像素数据
wire [10:0] x_pos;
wire [10:0] y_pos;
assign x_pos = frame_valid_ahead ? (hcnt - (H_SYNC + H_BACK)): 0;
assign y_pos = frame_valid_ahead ? (vcnt - (V_SYNC + V_BACK)): 0;
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
cmos_index <= 0;
cmos_data <= 24'd0;
end
else begin
cmos_index <= y_pos * 1920 + x_pos * 3 + 54;
cmos_data <= {rBmpData[cmos_index],rBmpData[cmos_index+1],rBmpData[cmos_index+2]};//按照BGR888存放
end
end
//--------------------------图像处理算法实现----------------------------//
wire per_frame_vsync = cmos_vsync;
wire per_frame_href = cmos_href;
wire per_frame_clken = cmos_clken;
wire [7:0] per_img_red = cmos_data[7:0];
wire [7:0] per_img_green = cmos_data[15:8];
wire [7:0] per_img_blue = cmos_data[23:16];
wire post0_frame_vsync ;
wire post0_frame_href ;
wire post0_frame_clken ;
wire [7:0] post0_img_Y ;
wire [7:0] post0_img_Cb ;
wire [7:0] post0_img_Cr ;
//最后经过图像处理算法处理完的结果
wire post_frame_vsync ;
wire post_frame_href ;
wire post_frame_clken ;
wire post_img_Bit ;
wire [7:0] post_img_Y ;
picture_process u_picture_process(
.clk (clk),
.rst_n (rst_n),
//Image data prepred to be processed
.per_frame_vsync (per_frame_vsync),
.per_frame_href (per_frame_href ),
.per_frame_clken (per_frame_clken),
.per_img_red (per_img_red ),
.per_img_green (per_img_green ),
.per_img_blue (per_img_blue ),
//Image data has been processed
.post_frame_vsync (post_frame_vsync),
.post_frame_href (post_frame_href ),
.post_frame_clken (post_frame_clken),
.post_img_Bit (post_img_Bit ),
.post_img_Y (post_img_Y )
);
//输出图片
wire PCI1_vip_out_frame_vsync ;
wire PCI1_vip_out_frame_href ;
wire PCI1_vip_out_frame_clken ;
wire [7:0] PCI1_vip_out_img_R ;
wire [7:0] PCI1_vip_out_img_G ;
wire [7:0] PCI1_vip_out_img_B ;
assign PCI1_vip_out_frame_vsync = post_frame_vsync;
assign PCI1_vip_out_frame_href = post_frame_href;
assign PCI1_vip_out_frame_clken = post_frame_clken;
assign PCI1_vip_out_img_R = {8{post_img_Bit}};
assign PCI1_vip_out_img_G = {8{post_img_Bit}};
assign PCI1_vip_out_img_B = {8{post_img_Bit}};
//assign PCI1_vip_out_img_R = post_img_Y;
//assign PCI1_vip_out_img_G = post_img_Y;
//assign PCI1_vip_out_img_B = post_img_Y;
reg [31:0] PCI1_vip_cnt ;
reg PCI1_vip_vsync_r ; //寄存VIP输出的场同步
reg PCI1_vip_out_en ; //寄存VIP处理图像的使能信号,仅维持一帧的时间
always@(posedge clk or negedge rst_n) begin
if(!rst_n)
PCI1_vip_vsync_r <= 1'b0;
else begin
PCI1_vip_vsync_r <= PCI1_vip_out_frame_vsync;
end
end
always@(posedge clk or negedge rst_n) begin
if(!rst_n)
PCI1_vip_out_en <= 1'b1;
else if(PCI1_vip_vsync_r & (!PCI1_vip_out_frame_vsync)) begin
PCI1_vip_out_en <= 1'b0;
end
end
always@(posedge clk or negedge rst_n) begin
if(!rst_n)
PCI1_vip_cnt <= 32'd0;
else if(PCI1_vip_out_en) begin
if(PCI1_vip_out_frame_href & PCI1_vip_out_frame_clken) begin
//$display("output picture22222");
PCI1_vip_cnt <= PCI1_vip_cnt + 3;
vip_pixel_data_1[PCI1_vip_cnt+0] <= PCI1_vip_out_img_R;
vip_pixel_data_1[PCI1_vip_cnt+1] <= PCI1_vip_out_img_G;
vip_pixel_data_1[PCI1_vip_cnt+2] <= PCI1_vip_out_img_B;
end
end
end
endmodule
picture_process 代码:
module picture_process(
input clk ,
input rst_n ,
//Image data prepred to be processed
input per_frame_vsync ,
input per_frame_href ,
input per_frame_clken ,
input [7:0] per_img_red ,
input [7:0] per_img_green ,
input [7:0] per_img_blue ,
//Image data has been processed
output post_frame_vsync ,
output post_frame_href ,
output post_frame_clken ,
output post_img_Bit ,
output [7:0] post_img_Y
);
wire post0_frame_vsync ;
wire post0_frame_href ;
wire post0_frame_clken ;
wire [7:0] post0_img_Y ;
wire [7:0] post0_img_Cb ;
wire [7:0] post0_img_Cr ;
assign post_img_Y = post0_img_Cb;
//彩色转灰度
picture_RGB888_YCbCr444 u_PICTURE_RGB888_YCbCr444(
//global signal
.clk (clk),
.rst_n (rst_n),
//Image data prepred to be processed
.per_frame_vsync (per_frame_vsync),
.per_frame_href (per_frame_href ),
.per_frame_clken (per_frame_clken),
.per_img_red (per_img_red ),
.per_img_green (per_img_green ),
.per_img_blue (per_img_blue ),
//Image data has been processed
.post_frame_vsync (post0_frame_vsync),
.post_frame_href (post0_frame_href ),
.post_frame_clken (post0_frame_clken),
.post_img_Y (post0_img_Y ),
.post_img_Cb (post0_img_Cb ),
.post_img_Cr (post0_img_Cr )
);
//二值化
picture_binarization #(
.THRESHOLD (8'd150)) //设置二值化阈值
u_picture_binarization(
//global signal
.clk (clk),
.rst_n (rst_n),
//Image data prepred to be processed
.per_frame_vsync (post0_frame_vsync),
.per_frame_href (post0_frame_href ),
.per_frame_clken (post0_frame_clken),
.per_img_Y (post0_img_Cb ),
//Image data has been processed
.post_frame_vsync (post_frame_vsync),
.post_frame_href (post_frame_href ),
.post_frame_clken (post_frame_clken),
.post_img_Bit (post_img_Bit )
);
endmodule
picture_RGB888_YCbCr444 代码
module picture_RGB888_YCbCr444(
//global signal
input clk ,
input rst_n ,
//Image data prepred to be processed
input per_frame_vsync ,
input per_frame_href ,
input per_frame_clken ,
input [7:0] per_img_red ,
input [7:0] per_img_green ,
input [7:0] per_img_blue ,
//Image data has been processed
output post_frame_vsync ,
output post_frame_href ,
output post_frame_clken ,
output [7:0] post_img_Y ,
output [7:0] post_img_Cb ,
output [7:0] post_img_Cr
);
//--------------------------------------------
/*********************************************
//Refer to <OV7725 Camera Module Software Applicaton Note> page 5
Y = (77 *R + 150*G + 29 *B)>>8
Cb = (-43*R - 85 *G + 128*B)>>8 + 128
Cr = (128*R - 107*G - 21 *B)>>8 + 128
--->
Y = (77 *R + 150*G + 29 *B)>>8
Cb = (-43*R - 85 *G + 128*B + 32768)>>8
Cr = (128*R - 107*G - 21 *B + 32768)>>8
**********************************************/
//Step 1
reg [15:0] img_red_r0, img_red_r1, img_red_r2;
reg [15:0] img_green_r0, img_green_r1, img_green_r2;
reg [15:0] img_blue_r0, img_blue_r1, img_blue_r2;
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
img_red_r0 <= 0;
img_red_r1 <= 0;
img_red_r2 <= 0;
img_green_r0 <= 0;
img_green_r1 <= 0;
img_green_r2 <= 0;
img_blue_r0 <= 0;
img_blue_r1 <= 0;
img_blue_r2 <= 0;
end
else begin
img_red_r0 <= per_img_red * 8'd77;
img_red_r1 <= per_img_red * 8'd43;
img_red_r2 <= per_img_red * 8'd128;
img_green_r0 <= per_img_green * 8'd150;
img_green_r1 <= per_img_green * 8'd85;
img_green_r2 <= per_img_green * 8'd107;
img_blue_r0 <= per_img_blue * 8'd29;
img_blue_r1 <= per_img_blue * 8'd128;
img_blue_r2 <= per_img_blue * 8'd21;
end
end
//--------------------------------------------------
//Step 2
reg [15:0] img_Y_r0;
reg [15:0] img_Cb_r0;
reg [15:0] img_Cr_r0;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
img_Y_r0 <= 0;
img_Cb_r0 <= 0;
img_Cr_r0 <= 0;
end
else
begin
img_Y_r0 <= img_red_r0 + img_green_r0 + img_blue_r0;
img_Cb_r0 <= img_blue_r1 - img_red_r1 - img_green_r1 + 16'd32768;
img_Cr_r0 <= img_red_r2 - img_green_r2 - img_blue_r2 + 16'd32768;
end
end
//--------------------------------------------------
//Step 3
reg [7:0] img_Y_r1;
reg [7:0] img_Cb_r1;
reg [7:0] img_Cr_r1;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
img_Y_r1 <= 0;
img_Cb_r1 <= 0;
img_Cr_r1 <= 0;
end
else
begin
img_Y_r1 <= img_Y_r0[15:8];
img_Cb_r1 <= img_Cb_r0[15:8];
img_Cr_r1 <= img_Cr_r0[15:8];
end
end
//------------------------------------------
//lag 3 clocks signal sync
reg [2:0] per_frame_vsync_r;
reg [2:0] per_frame_href_r;
reg [2:0] per_frame_clken_r;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
per_frame_vsync_r <= 0;
per_frame_href_r <= 0;
per_frame_clken_r <= 0;
end
else
begin
per_frame_vsync_r <= {per_frame_vsync_r[1:0], per_frame_vsync};
per_frame_href_r <= {per_frame_href_r[1:0], per_frame_href};
per_frame_clken_r <= {per_frame_clken_r[1:0], per_frame_clken};
end
end
assign post_frame_vsync = per_frame_vsync_r[2];
assign post_frame_href = per_frame_href_r[2];
assign post_frame_clken = per_frame_clken_r[2];
assign post_img_Y = post_frame_href ? img_Y_r1 : 8'd0;
assign post_img_Cb = post_frame_href ? img_Cb_r1: 8'd0;
assign post_img_Cr = post_frame_href ? img_Cr_r1: 8'd0;
endmodule
picture_binarization代码
module picture_binarization #(
parameter THRESHOLD = 8'd80) //设置二值化阈值
(
//global signal
input clk ,
input rst_n ,
//Image data prepred to be processed
input per_frame_vsync ,
input per_frame_href ,
input per_frame_clken ,
input [7:0] per_img_Y ,
//Image data has been processed
output post_frame_vsync ,
output post_frame_href ,
output post_frame_clken ,
output post_img_Bit
);
//reg define
reg post_frame_vsync_r;
reg post_frame_href_r;
reg post_frame_clken_r;
reg post_img_Bit_r;
assign post_frame_vsync = post_frame_vsync_r ;
assign post_frame_href = post_frame_href_r ;
assign post_frame_clken = post_frame_clken_r ;
assign post_img_Bit = post_img_Bit_r ;
//二值化
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
post_img_Bit_r <= 1'b0;
else if(per_img_Y < THRESHOLD) //阈值
post_img_Bit_r <= 1'b1; //白
else
post_img_Bit_r <= 1'b0; //黑
end
//延时1拍以同步时钟信号
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
post_frame_vsync_r <= 1'd0;
post_frame_href_r <= 1'd0;
post_frame_clken_r <= 1'd0;
end
else begin
post_frame_vsync_r <= per_frame_vsync;
post_frame_href_r <= per_frame_href;
post_frame_clken_r <= per_frame_clken;
end
end
endmodule
源文件免费下载:基于Vivado图像算法处理的仿真搭建-其它文档类资源-CSDN下载
感谢crazy_bingo前辈的分享。