简介
在DE2开发板上使用串口接收PC发送的640*480分辨率灰度图,存入SRAM,通过VGA进行显示。
开发板:DE2
型号:EP2C35F672C6
开发工具:Quartus II 13.0 + Modelsim 10.5 SE
全局时钟: 50M
VGA时钟:25M
SRAM大小:256k*16bit,总共512kb
目前还不会用SDRAM,先从简单的SRAM入手。
由于640*480分辨率的24位彩色图片需要900kb,SRAM装不下,所以使用8位灰度图(300kb)。
该SRAM为256k*16bit,为了存下300kb的灰度图,我将其包装为512k*8bit
RTL视图
一共五个模块:PLL、串口接收、写入地址计数、SRAM驱动、VGA驱动
PLL模块为VGA驱动模块提供25M时钟。
串口接收模块接收来自PC发送的图片数据。
写入地址计数模块根据接收到的数据,产生写入地址,并在接收完整张图片后,输出receive_done信号,允许VGA从SRAM读取数据。
SRAM驱动模块对SRAM芯片进行读写。
VGA驱动模块产生VGA时序显示图片。
串口接收模块
波特率:115200
数据位:8
校验:无
停止位:1
module uart_rx(
// clk, rst_n
input clk,
input rst_n,
// uart rx
input rx,
// valid data output
output reg valid,
output reg [7:0] data
);
parameter CLK_FRE = 50_000_000;
parameter BAUD_RATE = 115200; // 默认115200波特率
parameter cnt_baud_max = CLK_FRE / BAUD_RATE - 1; // 115200波特率下是434时钟周期一波特
// 打两拍防止亚稳态,rx_3用于检测rx下降沿
reg rx_1;
reg rx_2;
reg rx_3;
// 工作使能
reg work_ena;
// 波特计数器 比特计数器
reg [8:0] cnt_baud;
reg [4:0] cnt_bit;
// 计数器使能、清零
wire cnt_baud_ena;
wire cnt_baud_end;
wire cnt_bit_ena;
wire cnt_bit_end;
// data移位寄存器
reg [7:0] data_shift;
// valid打一拍再输出,和data同步输出
reg valid_reg;
// 打两拍防止亚稳态
always @(posedge clk, negedge rst_n) begin
if(!rst_n) begin
rx_1 <= 0;
rx_2 <= 0;
rx_3 <= 0;
end else begin
rx_1 <= rx;
rx_2 <= rx_1;
rx_3 <= rx_2;
end
end
// rx下降沿检测,出现下降沿开始工作,接收完数据结束工作
always @(posedge clk, negedge rst_n) begin
if(!rst_n) begin
work_ena <= 0;
end else begin
if(~rx_2 & rx_3)
work_ena <= 1;
else if(cnt_bit_ena && cnt_bit_end)
work_ena <= 0;
end
end
// 波特计数器
always @(posedge clk, negedge rst_n) begin
if(!rst_n)
cnt_baud <= 0;
else if(cnt_baud_ena) begin
if(cnt_baud_end)
cnt_baud <= 0;
else
cnt_baud <= cnt_baud + 1;
end else
cnt_baud <= 0;
end
assign cnt_baud_ena = work_ena;
assign cnt_baud_end = (cnt_baud == cnt_baud_max);
// 比特计数器
always @(posedge clk, negedge rst_n) begin
if(!rst_n)
cnt_bit <= 0;
else if(cnt_bit_ena) begin
if(cnt_bit_end)
cnt_bit <= 0;
else
cnt_bit <= cnt_bit + 1;
end
end
assign cnt_bit_ena = (cnt_baud == cnt_baud_max / 2);
assign cnt_bit_end = (cnt_bit == 8);
// data移位寄存器
always @(posedge clk, negedge rst_n) begin
if(!rst_n)
data_shift <= 0;
else if(cnt_bit_ena)
data_shift <= {
rx_2, data_shift[7:1]};
end
// 内部valid_reg有效信号
always @