目录
1.VGA时序
1.1top.v(顶层文件)
1.2调用的IP核(Clocking Wizard) PLL, 25.175MHZ。
1.3vga_driver.v(vga驱动)
1.4frame_controller.v(帧控制)
1.5top_tb.v(测试文件)
1.6仿真图:
2.利用VGA显示图像,并进行灰度变换
2.1将图像数据导为.coe文件
2.2调用IP核RAM,将.coe文件导入
2.3修改模块
2.4仿真图
2.5数据总流向
3.边缘检测---sobel算子
3.1图像处理模块
3.2顶层模块
3.3仿真图
module top(
input sys_clk,//100MHZ
input sys_rst_n,
output [3:0] VGA_R,
output [3:0] VGA_G,
output [3:0] VGA_B,
output VGA_HSYNC,
output VGA_VSYNC
);
//========= PPL IP produce vga_clk =====
wire vga_clk;
wire locked;
wire rst_n;
wire [15:0] rgb_data;
wire [11:0] vga_data;
wire [9:0] pos_x;
wire [9:0] pos_y;
assign rst_n = sys_rst_n && locked;
assign VGA_R = vga_data[11:8];
assign VGA_G = vga_data[7:4];
assign VGA_B = vga_data[3:0];
clk_wiz_0 u_clk(
// Clock out ports
.clk_out1(vga_clk),
// Status and control signals
.resetn(sys_rst_n),
.locked(locked),
// Clock in ports
.clk_in1(sys_clk)
);
//========== vga_driver =============
vga_driver u0_vga_driver(
.vga_clk(vga_clk),
.rst_n(rst_n),
.rgb_data(rgb_data),//RGB565
.vga_data(vga_data),//RGB444
.vga_hsync(VGA_HSYNC),
.vga_vsync(VGA_VSYNC),
.pos_x(pos_x),
.pos_y(pos_y)
);
//========== frame_controller =======
frame_controller u1_frame_controller(
.vga_clk(vga_clk),
.rst_n(rst_n),
.pos_x(pos_x),
.pos_y(pos_y),
.img_data(rgb_data)//RGB565
);
endmodule
`timescale 1ps/1ps
(* CORE_GENERATION_INFO = "clk_wiz_0,clk_wiz_v6_0_2_0_0,{component_name=clk_wiz_0,use_phase_alignment=true,use_min_o_jitter=false,use_max_i_jitter=false,use_dyn_phase_shift=false,use_inclk_switchover=false,use_dyn_reconfig=false,enable_axi=0,feedback_source=FDBK_AUTO,PRIMITIVE=PLL,num_out_clk=1,clkin1_period=10.000,clkin2_period=10.000,use_power_down=false,use_reset=true,use_locked=true,use_inclk_stopped=false,feedback_type=SINGLE,CLOCK_MGR_TYPE=NA,manual_override=false}" *)
module clk_wiz_0
(
// Clock out ports
output clk_out1,
// Status and control signals
input resetn,
output locked,
// Clock in ports
input clk_in1
);
clk_wiz_0_clk_wiz inst
(
// Clock out ports
.clk_out1(clk_out1),
// Status and control signals
.resetn(resetn),
.locked(locked),
// Clock in ports
.clk_in1(clk_in1)
);
endmodule
module vga_driver(
input wire vga_clk,
input wire rst_n,
input wire [15:0] rgb_data,//RGB565
output wire [11:0] vga_data,//RGB444
output wire vga_hsync,
output wire vga_vsync,
output wire [9:0] pos_x,
output wire [9:0] pos_y
);
//resolution 640*480
parameter H_SYNC = 10'd96,
H_BACK =10'd40,
H_LEFT = 10'd8,
H_VAILD = 10'd640,
H_RIGHT = 10'd8,
H_FRONT = 10'd8,
H_TOTAL = 10'd800;
parameter V_SYNC = 10'd2,
V_BACK =10'd25,
V_TOP = 10'd8,
V_VAILD = 10'd480,
V_BOTTOM = 10'd8,
V_FRONT = 10'd2,
V_TOTAL = 10'd525;
//==============core code============
//===================================
reg [9:0] h_cnt;
reg [9:0] v_cnt;
wire vga_data_vaild;
//==============line scan============
always @(posedge vga_clk or negedge rst_n)
begin
if(!rst_n)
h_cnt <= 1'b0;
else if(h_cnt == H_TOTAL-1)//not <= cause the == use less resource
h_cnt <= 10'd0;
else
h_cnt <= h_cnt + 1'b1;
end
//==============column scan============
always @(posedge vga_clk or negedge rst_n)
begin
if(!rst_n)
v_cnt <= 1'b0;
else if((v_cnt == V_TOTAL-1)&&(h_cnt == H_TOTAL-1))//the column tillthe all imge last
v_cnt <= 10'd0;
else if(h_cnt == H_TOTAL-1)
v_cnt <= v_cnt + 1'b1;
end
//===============vga_hsync assignment==
assign vga_hsync = (h_cnt <= H_SYNC)?1'b1:1'b0;
//===============vga_vsync assignment==
assign vga_vsync = (v_cnt <= V_SYNC)?1'b1:1'b0;
//===============vga_data_vaild assignment==
assign vga_data_vaild = (
(h_cnt >= H_SYNC+H_BACK+H_LEFT-1'b1)&&
(h_cnt <= H_SYNC+H_BACK+H_LEFT+H_VAILD-1'b1)&&
(v_cnt >= V_SYNC+V_BACK+V_TOP)&&
(v_cnt <= V_SYNC+V_BACK+V_TOP+V_VAILD)
)?1'b1:1'b0;//do a square
//===============vga_data assignment==
assign vga_data = (vga_data_vaild == 1'b1)?{rgb_data[15:12],rgb_data[10:7],rgb_data[4:1]}:12'd0;
//===============pos_x assignment==
assign pos_x = (vga_data_vaild)?(h_cnt-H_SYNC-H_BACK-H_LEFT+1'b1):10'h3ff;
//===============pos_y assignment==
assign pos_y = (vga_data_vaild)?(v_cnt-V_SYNC-V_BACK-V_TOP):10'h3ff;
endmodule
module frame_controller(
input wire vga_clk,
input wire rst_n,
input wire [9:0] pos_x,
input wire [9:0] pos_y,
output wire [15:0] img_data
);
assign img_data = (pos_x>8'd100 && pos_x<8'd200)?16'hffe2:16'hf800;
endmodule
`timescale 1ns / 1ps
module top_tb();
reg clk;
reg rst_n;
initial begin
clk <= 1'b0;
rst_n <= 1'b0;
#20;
rst_n <= 1'b1;
end
always #5 clk = ~clk;
top u_top(
.sys_clk(clk),//100MHZ
.sys_rst_n(rst_n)
);
endmodule
matlab里面导出,.coe文件格式开头为
memory_initialization_radix=16;
memory_initialization_vector=
结尾修改为分号,注意中英文区别,不然导不进ROM中。
img = imread('ganyu.bmp');
%分离通道
r = img(:,:,1);
g = img(:,:,2);
b = img(:,:,3);
%修改位宽
r = uint32(r);
g = uint32(g);
b = uint32(b);
%降维度 2->1,要先转置,再reshape
r = reshape(r',307200,1);
g = reshape(g',307200,1);
b = reshape(b',307200,1);
%rgb888->rgb444
rgb444 = zeros(307200,1);
for i=1:307200
rgb444(i) = bitshift(bitshift(r(i),-4),8) + bitshift(bitshift(g(i),-4),4) + bitshift(bitshift(b(i),-4),0);
end
%.coe文件前面要加的
file = fopen('img.coe','w+');
fprintf(file,'memory_initialization_radix=16;\nmemory_initialization_vector=\n');
%每行输出三个数,不够在前面补0
for i = 1:307200
fprintf(file,'%03x,\n',rgb444(i));
end
fclose(file);
注意数据的宽度和深度,要符合FPGA板载资源,深度可以适当多点。
top.v
module top(
input sys_clk,//100MHZ
input sys_rst_n,
output [3:0] VGA_R,
output [3:0] VGA_G,
output [3:0] VGA_B,
output VGA_HSYNC,
output VGA_VSYNC
);
//========= PPL IP produce vga_clk =====
wire vga_clk;
wire locked;
wire rst_n;
wire [11:0] rgb_data;
wire [11:0] vga_data;
wire [9:0] pos_x;
wire [9:0] pos_y;
wire vga_valid;
wire vga_data_valid_pre3;
wire [11:0] gray_data;
assign rst_n = sys_rst_n && locked;
assign VGA_R = vga_data[11:8];
assign VGA_G = vga_data[7:4];
assign VGA_B = vga_data[3:0];
clk_wiz_0 u_clk(
// Clock out ports
.clk_out1(vga_clk),
// Status and control signals
.resetn(sys_rst_n),
.locked(locked),
// Clock in ports
.clk_in1(sys_clk)
);
//========== vga_driver =============
vga_driver u0_vga_driver(
.vga_clk(vga_clk),
.rst_n(rst_n),
.rgb_data(gray_data),//RGB444
.vga_data(vga_data),//RGB444
.vga_hsync(VGA_HSYNC),
.vga_vsync(VGA_VSYNC),
.pos_x(pos_x),
.pos_y(pos_y),
.vga_valid(vga_valid),
.vga_data_valid_pre3(vga_data_valid_pre3)
);
//========== frame_controller =======
frame_controller u1_frame_controller(
.vga_clk(vga_clk),
.rst_n(rst_n),
.pos_x(pos_x),
.pos_y(pos_y),
.rgb_data(rgb_data),//RGB444
.vga_data_valid_pre3(vga_data_valid_pre3)
);
//============image processing=======
rgb2gray u_rgb2gray(
.imgPixel_in(rgb_data),
.imgPixel_out(gray_data)
);
endmodule
vga_driver.v
module vga_driver(
input wire vga_clk,
input wire rst_n,
input wire [11:0] rgb_data,//RGB444
output wire [11:0] vga_data,//RGB444
output wire vga_hsync,
output wire vga_vsync,
output wire [9:0] pos_x,
output wire [9:0] pos_y,
output wire vga_valid,
output wire vga_data_valid_pre3
);
//resolution 640*480
parameter H_SYNC = 10'd96,
H_BACK =10'd40,
H_LEFT = 10'd8,
H_VAILD = 10'd640,
H_RIGHT = 10'd8,
H_FRONT = 10'd8,
H_TOTAL = 10'd800;
parameter V_SYNC = 10'd2,
V_BACK =10'd25,
V_TOP = 10'd8,
V_VAILD = 10'd480,
V_BOTTOM = 10'd8,
V_FRONT = 10'd2,
V_TOTAL = 10'd525;
//==============core code============
//===================================
reg [9:0] h_cnt;
reg [9:0] v_cnt;
wire vga_data_valid;
//==============line scan============
always @(posedge vga_clk or negedge rst_n)
begin
if(!rst_n)
h_cnt <= 1'b0;
else if(h_cnt == H_TOTAL-1)//not <= cause the == use less resource
h_cnt <= 10'd0;
else
h_cnt <= h_cnt + 1'b1;
end
//==============column scan============
always @(posedge vga_clk or negedge rst_n)
begin
if(!rst_n)
v_cnt <= 1'b0;
else if((v_cnt == V_TOTAL-1)&&(h_cnt == H_TOTAL-1))//the column tillthe all imge last
v_cnt <= 10'd0;
else if(h_cnt == H_TOTAL-1)
v_cnt <= v_cnt + 1'b1;
end
//===============vga_hsync assignment==
assign vga_hsync = (h_cnt <= H_SYNC)?1'b1:1'b0;
//===============vga_vsync assignment==
assign vga_vsync = (v_cnt <= V_SYNC)?1'b1:1'b0;
//===============vga_data_vaild assignment==
assign vga_data_valid = (
(h_cnt >= H_SYNC+H_BACK+H_LEFT)&&
(h_cnt <= H_SYNC+H_BACK+H_LEFT+H_VAILD)&&
(v_cnt >= V_SYNC+V_BACK+V_TOP)&&
(v_cnt <= V_SYNC+V_BACK+V_TOP+V_VAILD)
)?1'b1:1'b0;//do a square
assign vga_data_valid_pre3 = (
(h_cnt >= H_SYNC+H_BACK+H_LEFT-2'd3)&&
(h_cnt <= H_SYNC+H_BACK+H_LEFT+H_VAILD-2'd3)&&
(v_cnt >= V_SYNC+V_BACK+V_TOP)&&
(v_cnt <= V_SYNC+V_BACK+V_TOP+V_VAILD)
)?1'b1:1'b0;//do a square
//=============
assign vga_valid = vga_data_valid;
//===============vga_data assignment==
assign vga_data = (vga_data_valid == 1'b1)?rgb_data:12'd0;
//===============pos_x assignment==
assign pos_x = (vga_data_valid)?(h_cnt-H_SYNC-H_BACK-H_LEFT):10'h3ff;
//===============pos_y assignment==
assign pos_y = (vga_data_valid)?(v_cnt-V_SYNC-V_BACK-V_TOP):10'h3ff;
endmodule
frame_controller.v
module frame_controller(
input wire vga_clk,
input wire rst_n,
inout wire vga_data_valid_pre3,
input wire [9:0] pos_x,
input wire [9:0] pos_y,
output wire [11:0] rgb_data
);
parameter FRAME_SIZE = 19'd307200;
reg [18:0] read_addr;
always @(posedge vga_clk or negedge rst_n)
begin
if(!rst_n)
read_addr <= 19'h7ffff;
else if(vga_data_valid_pre3 == 1'b1)
read_addr <= read_addr + 1'b1;
else if(read_addr == (FRAME_SIZE - 1'b1))
read_addr <= 19'd0;
else
read_addr <= read_addr;
end
blk1 u_1
(
.clka(vga_clk),
.ena(1'b1),
.addra(read_addr),
.douta(rgb_data)
);
endmodule
rgb2gray.v
module rgb2gray(
input [11:0] imgPixel_in,
output [11:0] imgPixel_out
);
wire [3:0] R;
wire [3:0] G;
wire [3:0] B;
wire [4:0] gray;
assign R = imgPixel_in[11:8];
assign G = imgPixel_in[7:4];
assign B = imgPixel_in[3:0];
assign gray = (R + G<<1 + B)>>2;
assign imgPixel_out = {gray[4:1],gray[4:1],gray[4:1]};
endmodule
测试文件不变。
cov_sobel.v
module cov_sobel(
input vga_clk,
input rst_n,
input wire [9:0] pos_x,
input wire [9:0] pos_y,
input wire [23:0] rgb_data,//rgb444--rgb888--rgb444
output reg [11:0] sobel_out
);
parameter THRESHOLD = 4'b0101;
wire [7:0] r;
wire [7:0] g;
wire [7:0] b;
wire [7:0] gray;
wire [23:0] gray_data;
assign r = rgb_data[23:16];
assign g = rgb_data[15:8];
assign b = rgb_data[7:0];
assign gray = r*5/16 + r*9/16 + b*2/16;
assign gray_data = {gray,gray,gray};
reg line_clk;
reg state;//idle
reg [7:0] line_buf0[639:0];
reg [7:0] line_buf1[639:0];
reg [7:0] p0;
reg [7:0] p1;
reg [7:0] p2;
reg [9:0] conv_out;
reg [3:0] tmp;
initial state = 0;
//=============line_clk========
always @(posedge vga_clk)begin
if(pos_x>0 && pos_y<479)begin
if(pos_x == 0)
line_clk <= 1'b1;
else
line_clk <= 1'b0;
end
end
//==========state=========
always @(posedge vga_clk)begin
case(state)
1'b0:begin
line_buf0[pos_x] <= gray;
line_buf1[pos_x] <= line_buf1[pos_x];
p2 <= gray;
p1 <= p2;
p0 <= p1;
if(pos_x>=2 && pos_y>=3)begin
if((p0 + p1*2 + p2)>(line_buf0[pos_x-2] + line_buf0[pos_x-1]*2 + line_buf0[pos_x]))
conv_out <= (p0 + p1*2 + p2) - (line_buf0[pos_x-2] + line_buf0[pos_x-1]*2 + line_buf0[pos_x]);
else
conv_out <= (line_buf0[pos_x-2] + line_buf0[pos_x-1]*2 + line_buf0[pos_x]) - (p0 + p1*2 + p2);
end
end
1'b1:begin
line_buf1[pos_x] <= gray;
line_buf0[pos_x] <= line_buf0[pos_x];
p2 <= gray;
p1 <= p2;
p0 <= p1;
if(pos_x>=2 && pos_y>=3)begin
if((p0 + p1*2 + p2)>(line_buf1[pos_x-2] + line_buf1[pos_x-1]*2 + line_buf1[pos_x]))
conv_out <= (p0 + p1*2 + p2) - (line_buf1[pos_x-2] + line_buf1[pos_x-1]*2 + line_buf1[pos_x]);
else
conv_out <= (line_buf1[pos_x-2] + line_buf1[pos_x-1]*2 + line_buf1[pos_x]) - (p0 + p1*2 + p2);
end
end
default:begin
conv_out <= conv_out;
line_buf0[pos_x] <= line_buf0[pos_x];
line_buf1[pos_x] <= line_buf1[pos_x];
end
endcase
end
//========comparison threshold======
always @(*)begin
tmp = (conv_out[5:2]>THRESHOLD)?4'hf:4'h0;
sobel_out = ({tmp,tmp,tmp});
end
endmodule
module top(
input sys_clk,//100MHZ
input sys_rst_n,
output [3:0] VGA_R,
output [3:0] VGA_G,
output [3:0] VGA_B,
output VGA_HSYNC,
output VGA_VSYNC
);
//========= PPL IP produce vga_clk =====
wire vga_clk;
wire locked;
wire rst_n;
wire [11:0] rgb_data;
wire [11:0] vga_data;
wire [9:0] pos_x;
wire [9:0] pos_y;
wire vga_valid;
wire vga_data_valid_pre3;
wire [11:0] sobel_data;
assign rst_n = sys_rst_n && locked;
assign VGA_R = vga_data[11:8];
assign VGA_G = vga_data[7:4];
assign VGA_B = vga_data[3:0];
clk_wiz_0 u_clk(
// Clock out ports
.clk_out1(vga_clk),
// Status and control signals
.resetn(sys_rst_n),
.locked(locked),
// Clock in ports
.clk_in1(sys_clk)
);
//========== vga_driver =============
vga_driver u0_vga_driver(
.vga_clk(vga_clk),
.rst_n(rst_n),
.rgb_data(sobel_data),//RGB444
.vga_data(vga_data),//RGB444
.vga_hsync(VGA_HSYNC),
.vga_vsync(VGA_VSYNC),
.pos_x(pos_x),
.pos_y(pos_y),
.vga_valid(vga_valid),
.vga_data_valid_pre3(vga_data_valid_pre3)
);
//========== frame_controller =======
frame_controller u1_frame_controller(
.vga_clk(vga_clk),
.rst_n(rst_n),
.pos_x(pos_x),
.pos_y(pos_y),
.rgb_data(rgb_data),//RGB444
.vga_data_valid_pre3(vga_data_valid_pre3)
);
//============image processing=======
cov_sobel u_sobel(
.vga_clk(vga_clk),
.rst_n(rst_n),
.pos_x(pos_x),
.pos_y(pos_y),
.rgb_data({{rgb_data[11:8],4'hf},{rgb_data[7:4],4'hf},{rgb_data[3:0],4'hf}}),
.sobel_out(sobel_data)
);
endmodule