基于basys2的VGA显示中ROM以及RAM的使用
上篇文章讲述了关于vga字符显示以及打字机效果的实现,我们是利用寄存器制作的显示模块,但是如果我们扩大显示
的字节数,就会发现,软件在布局布线的时候会报错,意思就是板子的资源不够用了,思来想去,也不是没道理,毕竟板
子的资源是有限的。既然这样,我们就可以换一种思路。前面我们用到了ROM储存字模,显示存储使用起存其实现的。
那么我们可以利用RAM的可读可写功能,制作一个显存,由于开发板上RAM是一块特定的资源,我们利用这块资源,
及大大节省了板子的寄存器资源。就不会在报错了。
我这里采用的是单口的RAM,只能同时执行单一的读操作或者写操作。我们要根据开发板接收到的数据,从ROM中
读取字模并按照一定的逻辑存储到RAM中,这一点是比较难的,但是相对的,在RAM输出的时候只需要利用计数器,
就可以实现输出了。由于一个字符的宽的是8位,但是在事件过程中会发现,每个字符的第一列都会显示在下一个字
符的第一列,也就是说,第一列字符有延时。造成这个的主要原因是RAM在写入的时候有一个周期的延迟,所以导
致每次写入的时候最后一位数据会写入到下一个字符。由于这个问题暂时还没有更好的解决办法,所以我采用了一
个方法,就是扩大了每个字符的位宽,就是每一个字符的显示由以前的8个像素点,变成了现在的呃9个。前面说到
了因为每个字符的第一列会延迟到下一个字符。所以我们干脆直接将第一列像素全部置零,而后面的八位才是真正
的字符。这样就解决了延迟问题。当然和不是根本的解决办法。我们只是利用了”障眼法“。
下面是代码:【注意这只是VGA的display模块,其他模块请参考上篇文章】
module display_2(
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;
parameter H_DISP = 10'd640; //分辨率一行
parameter V_DISP = 10'd480; //分辨率一列
localparam RED = 8'b111_000_00; //RGB332 红色
localparam BLUE = 8'b000_000_11; //RGB332 蓝色
reg [5:0] addra;
wire [127:0] douta;
wire douta_ram;
reg [11:0] addra_ram;
reg [11:0] addra_ram_1;
reg wea;
reg dina;
IP_ROM_7 IP_ROM_7 (
.clka(clk), // input clka
.addra(addra), // input [5 : 0] addra
.douta(douta) // output [127 : 0] douta
);
//显存RAM
ram_2304 ram_2304(
.clka(clk), // input clka
.wea(wea), // input [0 : 0] wea
.addra(addra_ram), // input [11 : 0] addra
.dina(dina), // input [0 : 0] dina
.douta(douta_ram) // output [0 : 0] douta
);
reg [2:0]cnt_en;
reg [7:0] cnt;
reg [3:0] cnt_t;
reg [11:0] cnt_data;
always@(posedge clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
wea <= 0;
else if(cnt == 8 && cnt_t == 15)
wea <= 0;
else if(cnt_en == 3)
wea <= 1;
else
wea <= wea;
end
reg [4:0] cnt_8;
always@(posedge clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
cnt_8 <= 0;
else if(cnt_8 == 15 )
cnt_8 <= 0;
else if(cnt == 8 && cnt_t == 15)
cnt_8 <= cnt_8 + 1'b1;
end
reg [8:0] dina_1;//RAM写入
always@(posedge clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
begin
cnt_t <= 0;
cnt <= 0;
end
else if(wea)
begin
case(cnt_t)
0:begin
dina_1 <= {1'b0,douta[127 :120]};//增加空像素,解决延时问题
dina <= dina_1[8-cnt];
addra_ram_1 <= cnt_t*144+cnt+9*cnt_8;
if(cnt == 8)
begin
cnt <= 0;
cnt_t <= cnt_t + 1'b1;
end
else
begin
cnt <= cnt +1'b1;
end
end
1:begin
dina_1 <= {1'b0,douta[119 :112]};
dina <= dina_1[8-cnt];
addra_ram_1 <= cnt_t*144+cnt+9*cnt_8;
if(cnt == 8)
begin
cnt <= 0;
cnt_t <= cnt_t + 1'b1;
end
else
begin
cnt <= cnt +1'b1;
end
end
2:begin
dina_1 <= {1'b0,douta[111 :104]};
dina <= dina_1[8-cnt];
addra_ram_1 <= cnt_t*144+cnt+9*cnt_8;
if(cnt == 8)
begin
cnt <= 0;
cnt_t <= cnt_t + 1'b1;
end
else
begin
cnt <= cnt +1'b1;
end
end
3:begin
dina_1 <= {1'b0,douta[103 :96]};
dina <= dina_1[8-cnt];
addra_ram_1 <= cnt_t*144+cnt+9*cnt_8;
if(cnt == 8)
begin
cnt <= 0;
cnt_t <= cnt_t + 1'b1;
end
else
begin
cnt <= cnt +1'b1;
end
end
4:begin
dina_1 <= {1'b0,douta[95 :88]};
dina <= dina_1[8-cnt];
addra_ram_1 <= cnt_t*144+cnt+9*cnt_8;
if(cnt == 8)
begin
cnt <= 0;
cnt_t <= cnt_t + 1'b1;
end
else
begin
cnt <= cnt +1'b1;
end
end
5:begin
dina_1 <= {1'b0,douta[87 :80]};
dina <= dina_1[8-cnt];
addra_ram_1 <= cnt_t*144+cnt+9*cnt_8;
if(cnt == 8)
begin
cnt <= 0;
cnt_t <= cnt_t + 1'b1;
end
else
begin
cnt <= cnt +1'b1;
end
end
6:begin
dina_1 <= {1'b0,douta[79 :72]};
dina <= dina_1[8-cnt];
addra_ram_1 <= cnt_t*144+cnt+9*cnt_8;
if(cnt == 8)
begin
cnt <= 0;
cnt_t <= cnt_t + 1'b1;
end
else
begin
cnt <= cnt +1'b1;
end
end
7:begin
dina_1 <= {1'b0,douta[71 :64]};
dina <= dina_1[8-cnt];
addra_ram_1 <= cnt_t*144+cnt+9*cnt_8;
if(cnt == 8)
begin
cnt <= 0;
cnt_t <= cnt_t + 1'b1;
end
else
begin
cnt <= cnt +1'b1;
end
end
8:begin
dina_1 <= {1'b0,douta[63 :56]};
dina <= dina_1[8-cnt];
addra_ram_1 <= cnt_t*144+cnt+9*cnt_8;
if(cnt == 8)
begin
cnt <= 0;
cnt_t <= cnt_t + 1'b1;
end
else
begin
cnt <= cnt +1'b1;
end
end
9:begin
dina_1 <= {1'b0,douta[55 :48]};
dina <= dina_1[8-cnt];
addra_ram_1 <= cnt_t*144+cnt+9*cnt_8;
if(cnt == 8)
begin
cnt <= 0;
cnt_t <= cnt_t + 1'b1;
end
else
begin
cnt <= cnt +1'b1;
end
end
10:begin
dina_1 <= {1'b0,douta[47 :40]};
dina <= dina_1[8-cnt];
addra_ram_1 <= cnt_t*144+cnt+9*cnt_8;
if(cnt == 8)
begin
cnt <= 0;
cnt_t <= cnt_t + 1'b1;
end
else
begin
cnt <= cnt +1'b1;
end
end
11:begin
dina_1 <= {1'b0,douta[39 :32]};
dina <= dina_1[8-cnt];
addra_ram_1 <= cnt_t*144+cnt+9*cnt_8;
if(cnt == 8)
begin
cnt <= 0;
dina <= 0;
cnt_t <= cnt_t + 1'b1;
end
else
begin
dina <= douta[39 - cnt];
cnt <= cnt +1'b1;
end
end
12:begin
dina_1 <= {1'b0,douta[31 :24]};
dina <= dina_1[8-cnt];
addra_ram_1 <= cnt_t*144+cnt+9*cnt_8;
if(cnt == 8)
begin
cnt <= 0;
cnt_t <= cnt_t + 1'b1;
end
else
begin
cnt <= cnt +1'b1;
end
end
13:begin
dina_1 <= {1'b0,douta[23 :16]};
dina <= dina_1[8-cnt];
addra_ram_1 <= cnt_t*144+cnt+9*cnt_8;
if(cnt == 8)
begin
cnt <= 0;
cnt_t <= cnt_t + 1'b1;
end
else
begin
cnt <= cnt +1'b1;
end
end
14:begin
dina_1 <= {1'b0,douta[15 :8]};
dina <= dina_1[8-cnt];
addra_ram_1 <= cnt_t*144+cnt+9*cnt_8;
if(cnt == 8)
begin
cnt <= 0;
cnt_t <= cnt_t + 1'b1;
end
else
begin
cnt <= cnt +1'b1;
end
end
15:begin
dina_1 <= {1'b0,douta[7 :0]};
dina <= dina_1[8-cnt];
addra_ram_1 <= cnt_t*144+cnt+9*cnt_8;
if(cnt == 8)
begin
cnt <= 0;
cnt_t <= 0;
end
else
begin
cnt <= cnt +1'b1;
end
end
endcase
end
end
always@(posedge clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
addra_ram <= 0;
else if(wea)
addra_ram <= addra_ram_1;
else if(!wea && pixel_xpos>= begin_x&&pixel_xpos <144+begin_x &&pixel_ypos>= begin_y && pixel_ypos < begin_y +16)
addra_ram <= cnt_data;
end
always@(posedge vga_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
pixel_data <= 0;
else if(!wea && pixel_xpos>= begin_x&&pixel_xpos <144+begin_x &&pixel_ypos>= begin_y && pixel_ypos < begin_y +16)
begin
if(douta_ram != 0)
pixel_data <= BLUE;
else
pixel_data <= RED;
end
else
pixel_data <= RED;
end
always@(posedge vga_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
cnt_data <= 0;
else if(!wea && pixel_xpos>= begin_x&&pixel_xpos <144+begin_x &&pixel_ypos>= begin_y && pixel_ypos < begin_y +16)
begin
if(cnt_data == 2303)
cnt_data <= 0;
else
cnt_data <= cnt_data + 1'b1;
end
end
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;
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
begin_x <= 20;
begin_y <= 20;
end
else
begin
begin_x <= 200;
begin_y <= 200;
end
end
endmodule