基于ROM的VGA&Uart字符显示显示,实验基于basys2开发板
一:基本功能
通过PC端,利用软件向开发板发送数据(基于UART通信),开发板根据接受到的数据,向显示器显示正确的数据(VGA显示),类似于打字机功能,数据存储与设置的ROM中。#
二:说明
①:此实验设置的分辨率为640*480;其中字符显示区域为8个字英文字符的宽度,因为英文字符的宽度是中文字符的一半,故只能显示四个汉字,或者八个西文字符。
②:关于ROM数据的获取,首先在开发板根据接收到的信息进行判断,然后根据判断结果,返回相应的数据在ROM中的地址,然后从ROM中获取数据存到寄存器中,在进行显示,就实现了打字机效果。当然,删除也是一样的,删除原理就是显示的逆向,只需要将接收到的数据在寄存器中的值变为0就可以了。
③:ROM设置的宽度为128位,深度43.内容在末尾处。注:led[7:0]为从PC端接收到的数据。
话不多说,上代码:
顶层模块:
module top(
input clk,
input key_in,
input sys_rst_n,
input rs232_rx,
output vga_hs,//行同步信号
output vga_vs,//场同步信号
output [7:0] vga_rgb,//红绿蓝三原色输出
output [7:0] led
);
wire vga_clk;
wire po_flag;
wire [7:0] pixel_data;
wire [9:0] pixel_xpos; //像素点横坐标
wire [9:0] pixel_ypos;
wire key_en;
clk clk_vga (
.clk(clk),
.sys_rst_n(sys_rst_n),
.vga_clk(vga_clk)
);
rx rx (
.clk(clk),
.sys_rst_n(sys_rst_n),
.rs232_rx(rs232_rx),
.led(led),
.po_flag(po_flag)
);
driver driver (
.vga_clk(vga_clk),
.sys_rst_n(sys_rst_n),
.pixel_data(pixel_data),
.vga_hs(vga_hs),
.vga_vs(vga_vs),
.vga_rgb(vga_rgb),
.pixel_xpos(pixel_xpos),
.pixel_ypos(pixel_ypos)
);
display display (
.vga_clk(vga_clk),
.sys_rst_n(sys_rst_n),
.pixel_xpos(pixel_xpos),
.pixel_ypos(pixel_ypos),
.pixel_data(pixel_data),
.led(led),
.po_flag(po_flag),
.clk(clk),
.key_en(key_en)
);
key key (
.clk(clk),
.sys_rst_n(sys_rst_n),
.key_en(key_en),
.key_in(key_in)
);
endmodule
VGA时钟模块利用分频实现20MHZ
module clk(
input clk,
input sys_rst_n,
output reg vga_clk
);
always@(posedge clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
vga_clk <= 1;
else
vga_clk <= ~vga_clk;
end
endmodule
uart接收模块
module rx(
input clk,
input sys_rst_n,
input rs232_rx,//链接电脑的发送端
output reg po_flag,//接受完成标志
output reg [7:0] led//接收到的8位
);
localparam BAUD_END = 5207;
localparam BAUD_M = BAUD_END/2-1;
localparam BIT_END = 8;
reg [3:0] bit_cnt;
reg [7:0] rx_data;
reg rx_r1;
reg rx_r2;
reg rx_r3;
reg rx_flag;
reg [12:0] band_cnt;
reg bit_flag;
wire rx_neg;
assign rx_neg = ~rx_r2 & rx_r3;
always@(posedge clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
led <= 0;
else if (po_flag)
led <= rx_data;
else
led <= led;
end
always@(posedge clk )
begin
rx_r1 <= rs232_rx;
rx_r2 <= rx_r1;
rx_r3 <= rx_r2;
end
always@(posedge clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
rx_flag <= 0;
else if(rx_neg == 1)
rx_flag <= 1;
else if(bit_cnt == 0 && band_cnt ==BAUD_END)
rx_flag <= 1'b0;
end
always@(posedge clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
band_cnt <= 0;
else if(band_cnt == BAUD_END)
band_cnt <=0;
else if (rx_flag == 1)
band_cnt <= band_cnt +1'b1;
else
band_cnt <= 0;
end
always@(posedge clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
bit_flag <= 0;
else if(band_cnt ==BAUD_M)
bit_flag <= 1;
else
bit_flag <= 0;
end
always@(posedge clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
bit_cnt <= 0;
else if (bit_cnt == BIT_END && bit_flag == 1)
bit_cnt <= 0;
else if(bit_flag == 1)
bit_cnt <= bit_cnt +1'b1;
end
always@(posedge clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
rx_data <= 0;
else if (bit_flag == 1 && bit_cnt >= 1)
begin
rx_data <= {rx_r2,rx_data[7:1]};
end
end
always@(posedge clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
po_flag <= 0;
else if(bit_cnt == BIT_END && bit_flag == 1)
po_flag <= 1;
else
po_flag <= 0;
end
endmodule
VGA显示驱动模块
module driver(
input vga_clk,//vga驱动时钟
input sys_rst_n,//fuwei
input [7:0] pixel_data,//像素点数据
output vga_hs,//行同步信号
output vga_vs,//场同步信号
output [7:0] vga_rgb,//红绿蓝三原色输出
output [9:0] pixel_xpos,//像素点横坐标
output [9:0] pixel_ypos//像素点纵坐标
);
parameter H_SYNC = 10'd96; //行同步
parameter H_BACK = 10'd48; //行显示后沿
parameter H_DISP = 10'd640; //行有效数据
parameter H_FRONT = 10'd16; //行显示前沿
parameter H_TOTAL = 10'd800; //行扫描周期
parameter V_SYNC = 10'd2; //场同步
parameter V_BACK = 10'd33; //场显示后沿
parameter V_DISP = 10'd480; //场有效数据
parameter V_FRONT = 10'd10; //场显示前沿
parameter V_TOTAL = 10'd525; //场扫描周期
reg [9:0] cnt_h;
reg [9:0] cut_v;
wire vga_en;
wire data_req;
//vga行场同步信号
assign vga_hs = (cnt_h <= H_SYNC )?1'b0:1'b1;
assign vga_vs = (cut_v <= V_SYNC )?1'b0:1'b1;
//使能RGB565数据输出
assign vga_en = (((cnt_h >= H_SYNC + H_BACK)&&(cnt_h < H_SYNC+ H_BACK + H_DISP))
&&((cut_v >= V_SYNC + V_BACK)&&(cut_v < V_SYNC + V_BACK+ V_DISP)))?1'b1:1'b0;
//RGB565数据输出
assign vga_rgb = vga_en?pixel_data:8'b0;
//请求像素点颜色数据输入
assign data_req = (((cnt_h >= H_SYNC + H_BACK)&&(cnt_h < H_SYNC + H_BACK + H_DISP ))
&&((cut_v >= V_SYNC + V_BACK)&&(cut_v < V_SYNC + V_BACK + V_DISP)))?1'b1:1'b0;
//像素点坐标
assign pixel_xpos = data_req?(cnt_h - (H_SYNC + H_BACK - 1'b1)):10'd0;
assign pixel_ypos = data_req?(cut_v - (V_SYNC + V_BACK - 1'b1)):10'd0;
//行计数器对像素时钟计数
always@(posedge vga_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
cnt_h <= 10'd0;
else
begin
if(cnt_h < H_TOTAL -1'b1)
cnt_h <= cnt_h + 1'b1;
else
cnt_h <= 10'd0;
end
end
//场计数器对行计数
always@(posedge vga_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
cut_v <= 0;
else if(cnt_h == H_TOTAL -1'b1)
begin
if(cut_v < V_TOTAL - 1'b1)
cut_v <= cut_v + 1'b1;
else
cut_v <= 0;
end
end
endmodule
VGA显示数据模块 &包含删除功能
module display(
input vga_clk, //VGA驱动时钟
input sys_rst_n, //复位信号
input [9:0] pixel_xpos, //像素点横坐标
input [9:0] pixel_ypos, //像素点纵坐标
output reg [7:0] pixel_data,//像素点数据
input [7:0] led,
input po_flag,
input clk,
input key_en
);
reg [6:0] begin_addra;
reg [9:0] begin_x;
reg [9:0] begin_y;
// reg [127:0] data;
reg [63:0] aa;
reg [63:0] bb;
reg [63:0] cc;
reg [63:0] dd;
reg [63:0] ee;
reg [63:0] ff;
reg [63:0] gg;
reg [63:0] hh;
reg [63:0] ii;
reg [63:0] jj;
reg [63:0] kk;
reg [63:0] ll;
reg [63:0] mm;
reg [63:0] nn;
reg [63:0] oo;
reg [63:0] pp;
reg [3:0] cnt;
parameter H_DISP = 10'd640; //分辨率一行
parameter V_DISP = 10'd480; //分辨率一列
localparam WHITE = 8'b111_111_11; //RGB332 白色
localparam BLACK = 8'b000_000_00; //RGB332 黑色
localparam RED = 8'b111_000_00; //RGB332 红色
localparam GREEN = 8'b000_111_00; //RGB332 绿色
localparam BLUE = 8'b000_000_11; //RGB332 蓝色
reg [5:0] addra;
wire [127:0] douta;
IP_ROM_7 your_instance_name (
.clka(clk), // input clka
.addra(addra), // input [5 : 0] addra
.douta(douta) // output [127 : 0] douta
);
always@(posedge clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
addra <= 0;
else
begin
case(led)
"A": addra <= 6'd0;
"B": addra <= 6'd1;
"C": addra <= 6'd2;
"D": addra <= 6'd3;
"E": addra <= 6'd4;
"F": addra <= 6'd5;
"G": addra <= 6'd6;
"H": addra <= 6'd7;
"I": addra <= 6'd8;
"J": addra <= 6'd9;
"K": addra <= 6'd10;
"L": addra <= 6'd11;
"M": addra <= 6'd12;
"N": addra <= 6'd13;
"O": addra <= 6'd14;
"P": addra <= 6'd15;
"Q": addra <= 6'd16;
"R": addra <= 6'd17;
"S": addra <= 6'd18;
"T": addra <= 6'd19;
"U": addra <= 6'd20;
"V": addra <= 6'd21;
"W": addra <= 6'd22;
"X": addra <= 6'd23;
"Y": addra <= 6'd24;
"Z": addra <= 6'd25;
"0": addra <= 6'd26;
"1": addra <= 6'd27;
"2": addra <= 6'd28;
"3": addra <= 6'd29;
"4": addra <= 6'd30;
"5": addra <= 6'd31;
"6": addra <= 6'd32;
"7": addra <= 6'd33;
"8": addra <= 6'd34;
"9": addra <= 6'd35;
" ": addra <= 6'd36;
8'hD0: addra <= 6'd37;
8'hC1: addra <= 6'd38;
8'hCF: addra <= 6'd39;
8'hE0: addra <= 6'd40;
8'hCE: addra <= 6'd41;
8'hC4: addra <= 6'd42;
default: begin_addra <= 0;
endcase
end
end
reg en;
reg [2:0]cnt_en;
always@(posedge clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
begin
en<=0;
end
else if(po_flag)
en <= 1;
else if(cnt_en == 3'd3)
en <= 0;
end
always@(posedge clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
cnt_en <= 0;
else if(en)
cnt_en <= cnt_en + 1'b1;
else
cnt_en <= 0;
end
always@(posedge clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
begin
aa<= 0;
bb<= 0;
cc<= 0;
dd<= 0;
ee<= 0;
ff <= 0;
gg<= 0;
hh<= 0;
ii <= 0;
jj <= 0;
kk<= 0;
ll <= 0;
mm<= 0;
nn<= 0;
oo<= 0;
pp<= 0;
end
else if( cnt_en == 3'd3 && !key_en)
begin
aa[63:0] <= {aa[55:0],douta[127:120]};
bb[63:0] <= {bb[55:0],douta[119:112]};
cc[63:0] <= {cc[55:0],douta[111:104]};
dd[63:0] <= {dd[55:0],douta[103:96]};
ee[63:0] <= {ee[55:0],douta[95:88]};
ff[63:0] <= {ff[55:0],douta[87:80]};
gg[63:0] <= {gg[55:0],douta[79:72]};
hh[63:0] <= {hh[55:0],douta[71:64]};
ii[63:0] <= {ii[55:0],douta[63:56]};
jj[63:0] <= {jj[55:0],douta[55:48]};
kk[63:0] <= {kk[55:0],douta[47:40]};
ll[63:0] <= {ll[55:0],douta[39:32]};
mm[63:0] <= {mm[55:0],douta[31:24]};
nn[63:0] <= {nn[55:0],douta[23:16]};
oo[63:0] <= {oo[55:0],douta[15:8]};
pp[63:0] <= {pp[55:0],douta[7:0]};
end
else if(key_en)
begin
aa[63:0] <= {8'h0,aa[63:8]};
bb[63:0] <= {8'h0,bb[63:8]};
cc[63:0] <= {8'h0,cc[63:8]};
dd[63:0] <= {8'h0,dd[63:8]};
ee[63:0] <= {8'h0,ee[63:8]};
ff[63:0 ] <= {8'h0,ff[63:8]};
gg[63:0] <= {8'h0,gg[63:8]};
hh[63:0] <= {8'h0,hh[63:8]};
ii[63:0] <={8'h0,ii[63:8]};
jj[63:0] <= {8'h0,jj[63:8]} ;
kk[63:0] <= {8'h0,kk[63:8]};
ll[63:0] <= {8'h0,ll[63:8]} ;
mm[63:0] <= {8'h0,mm[63:8]};
nn[63:0] <= {8'h0,nn[63:8]} ;
oo[63:0] <= {8'h0,oo[63:8]} ;
pp[63:0] <= {8'h0,pp[63:8]};
end
end
always@(posedge vga_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
begin
begin_x <= 20;
begin_y <= 20;
end
else
begin
begin_x <= 200;
begin_y <= 200;
end
end
always@(posedge vga_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
begin
cnt <= 1;
pixel_data <= 0;
end
else
begin
if(pixel_xpos>= begin_x&&pixel_xpos <64+begin_x &&pixel_ypos>= begin_y && pixel_ypos < begin_y +16)
begin
case(pixel_ypos-begin_y)
0:
begin
if(aa[63-pixel_xpos+begin_x] != 0)
pixel_data <= BLUE;
else
pixel_data <= RED;
end
1:
begin
if(bb[63-pixel_xpos+begin_x] != 0)
pixel_data <= BLUE;
else
pixel_data <= RED;
end
2:
begin
if(cc[63-pixel_xpos+begin_x] != 0)
pixel_data <= BLUE;
else
pixel_data <= RED;
end
3:
begin
if(dd[63-pixel_xpos+begin_x] != 0)
pixel_data <= BLUE;
else
pixel_data <= RED;
end
4:
begin
if(ee[63-pixel_xpos+begin_x] != 0)
pixel_data <= BLUE;
else
pixel_data <= RED;
end
5:
begin
if(ff[63-pixel_xpos+begin_x] != 0)
pixel_data <= BLUE;
else
pixel_data <= RED;
end
6:
begin
if(gg[63-pixel_xpos+begin_x] != 0)
pixel_data <= BLUE;
else
pixel_data <= RED;
end
7:
begin
if(hh[63-pixel_xpos+begin_x] != 0)
pixel_data <= BLUE;
else
pixel_data <= RED;
end
8:
begin
if(ii[63-pixel_xpos+begin_x] != 0)
pixel_data <= BLUE;
else
pixel_data <= RED;
end
9:
begin
if(jj[63-pixel_xpos+begin_x] != 0)
pixel_data <= BLUE;
else
pixel_data <= RED;
end
10:
begin
if(kk[63-pixel_xpos+begin_x] != 0)
pixel_data <= BLUE;
else
pixel_data <= RED;
end
11:
begin
if(ll[63-pixel_xpos+begin_x] != 0)
pixel_data <= BLUE;
else
pixel_data <= RED;
end
12:
begin
if(mm[63-pixel_xpos+begin_x] != 0)
pixel_data <= BLUE;
else
pixel_data <= RED;
end
13:
begin
if(nn[63-pixel_xpos+begin_x] != 0)
pixel_data <= BLUE;
else
pixel_data <= RED;
end
14:
begin
if(oo[63-pixel_xpos+begin_x] != 0)
pixel_data <= BLUE;
else
pixel_data <= RED;
end
15:
begin
if(cnt == 8)
cnt <= 1;
else
cnt <= cnt +1'b1;
if(pp[63-pixel_xpos+begin_x] != 0)
pixel_data <= BLUE;
else
pixel_data <= RED;
end
default: pixel_data <= pixel_data;
endcase
end
else
pixel_data <= RED;
end
end
endmodule
按键消抖模块
module key(
input clk,
input sys_rst_n,
output key_en,
input key_in
);
//这两段代码前面分别进行计数和在计数满产生一个高脉冲信号cnt_full
//20ms计数器
reg cnt_full;
reg [19:0] cnt;
always@(posedge clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
cnt <= 20'd0;
else if(cnt == 20'd1000000-1)
cnt <= 20'd0;
else
cnt <= cnt + 1'b1;
end
//计数满信号
always@(posedge clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
cnt_full <= 1'b0;
else if(cnt == 20'd1000000-1)
cnt_full <= 1'b1;
else
cnt_full <= 1'b0;
end
//这两段代码就是来用实现取前后按键信号的
reg key_in_r;
reg key_in_r_next;
always@(posedge clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
key_in_r_next <= 0;
else if(cnt_full)
key_in_r_next <= key_in;
else
key_in_r_next <= key_in_r_next;
end
always@(posedge clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
key_in_r <= 0;
else
key_in_r <= key_in_r_next;
end
assign key_en = ~key_in_r & (key_in_r_next);
endmodule
引脚分配
NET "clk" LOC = B8;
NET "sys_rst_n" LOC = N3;
NET "rs232_rx" LOC = B7;
NET"vga_rgb[0]"LOC = C14;
NET"vga_rgb[1]"LOC = D13;
NET"vga_rgb[2]"LOC = F13;
NET"vga_rgb[3]"LOC = F14;
NET"vga_rgb[4]"LOC = G13;
NET"vga_rgb[5]"LOC = G14;
NET"vga_rgb[6]"LOC = H13;
NET"vga_rgb[7]"LOC = J13;
NET"vga_hs"LOC = J14;
NET"vga_vs"LOC = K13;
NET "led[7]" LOC = G1;
NET "led[6]" LOC = P4;
NET "led[5]" LOC = N4;
NET "led[4]" LOC = N5;
NET "led[3]" LOC = P6;
NET "led[2]" LOC = P7;
NET "led[1]" LOC = M11;
NET "led[0]" LOC = M5;
NET "key_in" LOC = A7;
ROM.COE
MEMORY_INITIALIZATION_RADIX=16;
MEMORY_INITIALIZATION_VECTOR=
0000001010182828243C444242E70000,
000000F8444444784442424244F80000,
0000003E424280808080804244380000,
000000F8444242424242424244F80000,
000000FC424848784848404242FC0000,
000000FC424848784848404040E00000,
0000003C44448080808E844444380000,
000000E7424242427E42424242E70000,
0000007C1010101010101010107C0000,
0000003E0808080808080808080888F0,
000000EE444850705048484444EE0000,
000000E0404040404040404042FE0000,
000000EE6C6C6C6C6C54545454D60000,
000000C7626252524A4A4A4646E20000,
00000038448282828282828244380000,
000000FC424242427C40404040E00000,
0000003844828282828282B24C380600,
000000FC4242427C4848444442E30000,
0000003E4242402018040242427C0000,
000000FE921010101010101010380000,
000000E74242424242424242423C0000,
000000E7424244242428281810100000,
000000D654545454546C282828280000,
000000E7422424181818242442E70000,
000000EE444428281010101010380000,
0000007E840408081020204242FC0000,
0000001E333737333B3B331E00000000,
0000000C1C7C0C0C0C0C0C0C00000000,
0000003C6666060C1830607E00000000,
0000003C6666061C0666663C00000000,
0000003030363636667F060600000000,
0000007E6060607C06060C7800000000,
0000001C18307C666666663C00000000,
0000007E060C0C181830303000000000,
0000003C6666763C6E66663C00000000,
0000003C666666663E0C183800000000,
00000000000000000000000000000000,
02013F000804FF0101017F0101010101,
0000F8002040FE000000FC0000000000,
0000002023FA22736AA3A22223220000,
00000000F80808F808F80808F8080000,
0000000201FF10100804031CE0000000,
0000000000FC2020408000E01C000000;