目的:
1.使用uart串口接收模块接收待显示的串行数据(像素RGB值)。
2.把待显示的数据写入ram中。
3.从ram中读取像素值到TFT显示屏中显示,并对应输出该像素的坐标值。
注意:
1.遵循uart协议的一个数据位宽为8,一个RGB565像素值位宽为16,所以接收两个再存入RAM中的一个存储单元。
2.由显示屏控制器发出读取数据的请求信号,再从ram中读出数据,传输到显示屏显示,总共慢了两拍,因此请求信号应该提前两拍发出。
3.在读取ram模块中可以控制在显示屏中显示的区域。用参数划定区域,然后区域内读取ram值并输出显示,区域外不读数据,输出0(黑屏)。
4.由于每个fpga芯片上的ram存储资源是有限的,只能存储定量的像素值,所以如果显示屏的分辨率太高,只能显示一部分区域。
5.ram资源的查找方法:①看fpga芯片有几个块ram资源
②到手册上查看该芯片上每个ram的存储容量。
③两个值相乘即是最大容量。
6.把两位低位宽数据存储成一位高位宽数据,可以利用计数器的奇偶,或者取它的高位。如:

框图:

实现:把之前的模块进行连线,并增加写入模块和读出模块。(为了相互适配,旧模块在本次设计中代码有所调整)
`timescale 1ns /1ns
module uart_ram_TFT_send_tb( );
reg clk ;
reg reset ;
reg uart_tx ;
wire [15:0]RGB565_data ;
wire [15:0]vish_axis ;//显示的行坐标
wire [15:0]visv_axis ;//显示的列坐标
reg [7:0] rand;
reg [16:0]input_cnt ;
uart_ram_TFT uart_ram_TFT_sim_send(//顶层连线
clk,//50MHz
reset,
uart_tx ,
RGB565_data,//输出的内容数据
vish_axis ,//显示的行坐标
visv_axis //显示的列坐标
);
initial clk = 1 ;
always #10 clk = ! clk ;
initial begin
reset = 0 ;
uart_tx = 1;
input_cnt = 0 ;
rand = 0 ;
input_cnt = 0 ;
#201 ;
reset = 1 ;
#800000;
repeat(65536)begin
#20 ;
rand = {$random} % 255;
#20 ;
uart_input(rand);
input_cnt = input_cnt + 1 ;
end
#1000 ;
$stop ;
end
task uart_input ;//设定一个任务uart_inpt,有一个输入端uart_tx_data_stm 。在这个task里可以对task外的变量进行赋值
input [7:0]uart_tx_data_stm ;//不返回值,所以不能用x=uart_input。而是直接uart_input。
begin //结构简单的begin-end
uart_tx = 1 ;
#20 ;
uart_tx = 0 ;
#8640 ;
uart_tx = uart_tx_data_stm[0] ;
#8640 ;
uart_tx = uart_tx_data_stm[1] ;
#8640 ;
uart_tx = uart_tx_data_stm[2] ;
#8640 ;
uart_tx = uart_tx_data_stm[3] ;
#8640 ;
uart_tx = uart_tx_data_stm[4] ;
#8640 ;
uart_tx = uart_tx_data_stm[5] ;
#8640 ;
uart_tx = uart_tx_data_stm[6] ;
#8640 ;
uart_tx = uart_tx_data_stm[7] ;
#8640 ;
uart_tx = 1 ;
#8640 ;
end
endtask
endmodule
module uart_ram_TFT(//顶层连线模块
clk,//50MHz
reset,
uart_tx ,
RGB565_data,//输出的内容数据
vish_axis ,//显示的行坐标
visv_axis //显示的列坐标
);
input clk ;
input reset ;
input uart_tx ;
output [15:0]RGB565_data ;
output [15:0]vish_axis ;//显示的行坐标
output [15:0]visv_axis ;//显示的列坐标
//内部变量
wire [7:0]parallel_data ;//串口接收模块接收的并行数据8位
wire rx_done ;//串口接收模块接收8位数据结束信号
//uart接收模块
uart_receive_1 uart_receive(//串口接收模块
.clk(clk) ,
.reset(reset) ,
.baud_rate(5) ,
.uart_tx(uart_tx),
.data(parallel_data) ,
.rx_done(rx_done)
);
//内部变量
wire [15:0]addr_write ;//串口接收模块接收的并行数据8位
wire [15:0]data_write ;//串口接收模块接收8位数据结束信号
wire write_enable ;//写入使能信号
//uart接收的数据存入ram模块
uart_to_ram uart_to_ram(//将uart串口接收模块输出的数据写入ram中
.clk(clk) ,
.reset(reset) ,
.data(parallel_data),
.rx_done(rx_done),
.addr(addr_write) ,
.dout(data_write) ,
.wenable(write_enable )
);
//内部变量
wire clk_b ;//串口接收模块接收的并行数据8位
wire [15:0]addr_read ;
wire read_ram_request ;
wire [15:0]read_data ;
//ram存储模块
RAM_DISPLAY RAM (
.clka(clk), // input wire clka
.ena(1), // input wire ena
.wea(write_enable), // input wire [0 : 0] wea
.addra(addr_write), // input wire [15 : 0] addra
.dina(data_write), // input wire [15 : 0] dina
.clkb(clk_b), // input wire clkb
.enb(read_ram_request), // input wire enb
.addrb(addr_read), // input wire [15 : 0] addrb
.doutb(read_data) // output wire [15 : 0] doutb
);
//内部变量
wire disp_request ;
wire [15:0]disp_data ;
//从ram读数据模块
ram_to_display ram_to_display(//读ram数据到显示屏模块
.clka(clk),//输入时钟
.reset(reset),//复位
.data(read_data),//ram读出的数据16位
.data_request(disp_request),//显示屏控制的的数据请求信号
.h_axis(vish_axis) ,//行坐标
.v_axis(visv_axis) ,//列坐标
.clkb(clk_b),//显示屏控制器的输入时钟
.addr_read(addr_read),//读ram的地址
.read_ram_request(read_ram_request),//读ram请求信号
.display_data(disp_data)//显示屏控制器的数据输入信号
);
//屏幕显示器控制模块
VGA TFT_control(
.clk(clk_b),
.reset(reset),
.content_data_request(disp_request),//数据请求信号
.content_data(disp_data),//要显示的内容数据
.RGB_data(RGB565_data),//输出的内容数据
.vis_h_axis(vish_axis) ,//显示的行坐标
.vis_v_axis(visv_axis) ,//显示的列坐标
.vis_sig()//内容显示同步信号(高电平时显示)
);
en

该博客详细描述了一个FPGA系统如何通过UART串口接收RGB565像素数据,然后将其存储到内部RAM中,再根据TFT显示屏的控制器请求,从RAM读取数据并在显示屏上按指定区域显示。设计中包含了串口接收模块、数据写入RAM模块、从RAM读取数据模块以及TFT显示屏控制模块,同时考虑了显示屏的分辨率限制和数据传输延迟。
最低0.47元/天 解锁文章
1023

被折叠的 条评论
为什么被折叠?



