文章目录
- 前言
- 一、串口传图顶层系统设计框图
- 二、各模块说明
- 三、系统工程及 IP 创建
- 四、uart_ddr3_tft模块
- 五、uart_ddr3_tft模块仿真文件
- 六、uart_ddr3_tft模块仿真文件
前言
结合串口接收模块和 tft 显示屏控制模块,设计一个基于 DDR3 的串口传图帧缓存系统。
提示:以下是本篇文章正文内容,下面案例可供参考
一、串口传图顶层系统设计框图
二、各模块说明
(1)uart_byte_rx 模块:负责串口图像数据的接收,该模块的设计前面章节已经有讲(可参考串口接收)。
(2)bit8_trans_bit16 模块:将串口接收的每两个 8bit 数据转换成一个 16bit 数据(图像数据是 16bit 的 RGB565 的数据,电脑是通过串口将一个像素点数据分两次发送到 FPGA,FPGA 需将串口接收数据重组成 16bit 的图像数据),实现过程相对比较简单(可参考8_trans_16)。
(3)disp_driver 模块:tft 屏显示驱动控制,对缓存在 DDR3 中的图像数据进行显示(可参考VGA成像原理)。
(4)wr_ddr3_fifo 模块:使用的 FIFO IP ,主要用于写入 DDR3 数据的缓存、解决数
据跨时钟域以及数据位宽的转换(IP生成在下方有介绍)。
(5)rd_ddr3_fifo 模块:使用的 FIFO IP ,主要用于读出 DDR3 数据的缓存、解决数据
跨时钟域以及数据位宽的转换(IP生成在下方有介绍)。
(6)fifo2mig_axi 模块:主要是用于接口的转换,将 MIG IP 的 AXI 接口换成与 FIFO
对接的接口(可参考fifo2mig_axi)。
(7)mig_7series_0 模块: DDR3 控制器,使用的 Memory Interface Generator(MIG 7
Series)IP(可参考添加链接描述)。
(8)pll 模块:上述各个模块所需时钟的产生,使用 PLL IP。除去使用 IP 和前面章节讲过的模块外,还需要设计的模块包括 bit8_trans_bit16 模块和fifo2mig_axi 模块(IP生成在下方有介绍)。
(9)顶层模块uart_ddr3_tft,用于实现上述模块的转换与连接(参考第四节uart_ddr3_tft模块)。
三、系统工程及 IP 创建
新建一个以名为uart_ddr3_tft的工程,工程创建好之后,根据系统整体结构图将所需的 IP 的进行一一创建,DDR 控制器 IP就不多说,按照前面 MIG IP 创建流程,创建一个mig_7series_0 的 DDR 控制器。接下来对两个 FIFO IP 进行创建。首先对 wr_ddr3_fifo 模块进行分析,这个 FIFO 处于串口接收模块与 fifo2mig_axi 模块之间,主要是由于两个模块之间时钟和数据传输速率不一致导致需要进行数据缓存。端口数据是 16bit 图像数据,写入时钟采用与串口接收模块相同的工作时钟 50MHz。读端口数据是用于写入到 DDR 存储器,与 DDR 控制器保持一致,数据位宽使用 128bit,读时钟使用 200MHz 的 ui_clk 时钟。根据分析,需创建一个独立时钟的
读写数据位宽不一样的 FIFO,具体 FIFO 的相关配置如下图。注意,这里 FIFO 的 Read Mode需要设置成 First Word Fall Through,写入数据深度暂时设置为 512,根据后面设计情况可进行修改。
rd_ddr3_fifo 模块与 wr_ddr3_fifo 模块类似,同样处于串口接收模块与 fifo2mig_axi 模块
之间。不同的是,这个 FIFO 的写入数据是来自从 DDR 存储器读出的数据,而读出的数据
是用于图像显示。所以写端口数据位宽为 128bit,写入时钟使用 MIG IP 输出的 200MHz 的
ui_clk 时钟。读端口数据位宽为 16bit,读时钟使用与 TFT 驱动时钟一致的时钟。根据分析,
需创建一个独立时钟的读写数据位宽不一样的 FIFO,具体 FIFO 的相关配置如下图。注意,
这里 FIFO 的 Read Mode 需要设置成 First Word Fall Through,写入数据深度暂时设置为 64,根据后面设计情况可进行修改。
pll 模块是用于产生整个系统中所需各种时钟,整个系统中主要使用到 3 个时钟,分别为 DDR 控制器所需 200MHz 时钟、串口模块工作的 50MHz 时钟、5 寸 TFT 屏驱动模块的33MHz。ACX720 板卡 FPGA 的输入时钟是 50MHz 的输入时钟。根据分析可知,PLL 模块的输入时钟是来自外部的 50MHz 晶振时钟,输出时钟为 200MHz、50MHz、33MHz。具体IP 配置界面如下图,其余界面保持默认即可。
整个系统所需的 IP 已经创建完成,创建的 IP 可以通过在 Source 窗口的 IP Source 中看
到。可鼠标双击进行修改配置等操作。
四、uart_ddr3_tft模块
该模块主要作用是串联其他模块,完成传图过程。其中个模块对应的介绍均在第二节后附有连接,以供参考。
/
// Module Name : uart_ddr3_tft
// Description : 串口传图DDR3缓存TFT屏显示
// Version : Vivado2018.3
// Name : 小王在努力...
/
module uart_ddr3_tft(
//System clock reset
input clk50m , //系统时钟输入,50MHz
input reset_n , //复位信号输入
//LED
output [3:0] led ,
//Uart interface
input uart_rx , //串口输入信号
//TFT Interface
output [15:0] TFT_rgb , //TFT数据输出
output TFT_hs , //TFT行同步信号
output TFT_vs , //TFT场同步信号
output TFT_clk , //TFT像素时钟
output TFT_de , //TFT数据使能
output TFT_pwm , //TFT背光控制
//DDR3 Interface
// Inouts
inout [15:0] ddr3_dq ,
inout [1:0] ddr3_dqs_n ,
inout [1:0] ddr3_dqs_p ,
// Outputs
output [13:0] ddr3_addr ,
output [2:0] ddr3_ba ,
output ddr3_ras_n ,
output ddr3_cas_n ,
output ddr3_we_n ,
output ddr3_reset_n ,
output [0:0] ddr3_ck_p ,
output [0:0] ddr3_ck_n ,
output [0:0] ddr3_cke ,
output [0:0] ddr3_cs_n ,
output [1:0] ddr3_dm ,
output [0:0] ddr3_odt
);
//*********************************
//Internal connect
//*********************************
//clock
wire pll_locked;
wire loc_clk50m;
wire loc_clk200m;
wire loc_clk33m;
wire loc_clk9m;
//uart Interface
wire [7:0] uart_byte;
wire uart_byte_vaild;
//wr_fifo Interface
wire [15:0] wrfifo_din;
wire wrfifo_wren;
wire wrfifo_rden;
wire [127:0] wrfifo_dout;
wire [5 : 0] wrfifo_rd_cnt;
wire wrfifo_empty;
wire wrfifo_wr_rst_busy;
wire wrfifo_rd_rst_busy;
//rd_fifo Interface
wire rdfifo_wren;
wire [127:0] rdfifo_din;
wire rdfifo_rden;
wire [15 :0] rdfifo_dout;
wire [5 : 0] rdfifo_wr_cnt;
wire rdfifo_full;
wire rdfifo_wr_rst_busy;
wire rdfifo_rd_rst_busy;
//mig Interface
wire mig_reset_n;
wire aresetn;
wire mmcm_locked;
wire init_calib_complete;
wire ui_clk;
wire ui_clk_sync_rst;
wire[3:0] s_axi_awid;
wire[27:0] s_axi_awaddr;
wire[7:0] s_axi_awlen;
wire[2:0] s_axi_awsize;
wire[1:0] s_axi_awburst;
wire[0:0] s_axi_awlock;
wire[3:0] s_axi_awcache;
wire[2:0] s_axi_awprot;
wire[3:0] s_axi_awqos;
wire s_axi_awvalid;
wire s_axi_awready;
wire[127:0] s_axi_wdata;
wire[15:0] s_axi_wstrb;
wire s_axi_wlast;
wire s_axi_wvalid;
wire s_axi_wready;
wire [3:0] s_axi_bid;
wire [1:0] s_axi_bresp;
wire s_axi_bvalid;
wire s_axi_bready;
wire[3:0] s_axi_arid;
wire[27:0] s_axi_araddr;
wire[7:0] s_axi_arlen;
wire[2:0] s_axi_arsize;
wire[1:0] s_axi_arburst;
wire[0:0] s_axi_arlock;
wire[3:0] s_axi_arcache;
wire[2:0] s_axi_arprot;
wire[3:0] s_axi_arqos;
wire s_axi_arvalid;
wire s_axi_arready;
wire [3:0] s_axi_rid;
wire [127:0] s_axi_rdata;
wire [1:0] s_axi_rresp;
wire s_axi_rlast;
wire s_axi_rvalid;
wire s_axi_rready;
//tft
wire clk_disp;
wire frame_begin;
wire rdfifo_clr;
reg rdfifo_clr_sync_ui_clk;
reg rd_addr_clr;
wire wrfifo_clr;
reg wrfifo_clr_sync_ui_clk;
reg wr_addr_clr;
reg frame_rx_done_flip;
//兼容TFT5.0寸和TFT4.3寸显示屏,可根据实际进行配置选择
/*
parameter DISP_WIDTH = 480;
parameter DISP_HEIGHT = 272;
assign clk_disp = loc_clk9m;
*/
parameter DISP_WIDTH = 800;
parameter DISP_HEIGHT = 480;
assign clk_disp = loc_clk33m;
assign mig_reset_n = pll_locked;
assign aresetn = pll_locked;
assign led = {frame_rx_done_flip,init_calib_complete,mmcm_locked,pll_locked};
pll pll
(
// Clock out ports
.clk_out1 (loc_clk50m ), // output clk_out1
.clk_out2 (loc_clk200m ), // output clk_out2
.clk_out3 (loc_clk33m ), // output clk_out3
.clk_out4 (loc_clk9m ), // output clk_out4
// Status and control signals
.resetn (reset_n ), // input reset
.locked (pll_locked ), // output locked
// Clock in ports
.clk_in1 (clk50m ) // input clk_in1
);
uart_byte_rx#(
.CLK_FRQ(1000000000)
)
uart_byte_rx(
.clk (loc_clk50m ),
.reset_p (ui_clk_sync_rst ),
.baud_set (3'd5 ), //1562500bps
.uart_rx (uart_rx ),
.data_byte(uart_byte ),
.rx_done (uart_byte_vaild ) //一个字节数据有效的标志
);
//---------------------------------------------
//仅仿真用,正常功能时,将197~226行代码屏蔽
//仿真时,取消屏蔽197~226行代码,将179~191代码屏蔽
//---------------------------------------------
// reg [15:0]col_data_cnt;
// reg [15:0]row_data_cnt;
// always@(posedge loc_clk50m or posedge ui_clk_sync_rst)
// begin
// if(ui_clk_sync_rst)
// col_data_cnt <= 16'd0;
// else if(!init_calib_complete)
// col_data_cnt <= 16'd0;
// else if(col_data_cnt == DISP_WIDTH*2)
// col_data_cnt <= 16'd0;
// else
// col_data_cnt <= col_data_cnt + 1'b1;
// end
// always@(posedge loc_clk50m or posedge ui_clk_sync_rst)
// begin
// if(ui_clk_sync_rst)
// row_data_cnt <= 16'd0;
// else if(col_data_cnt == DISP_WIDTH*2)
// if(row_data_cnt >= DISP_HEIGHT-1)
// row_data_cnt <= 16'hffff;
// else
// row_data_cnt <= row_data_cnt + 1'b1;
// else
// row_data_cnt <= row_data_cnt;
// end
// assign uart_byte = row_data_cnt[7:0];
// assign uart_byte_vaild = (col_data_cnt == DISP_WIDTH*2);
//-------------------------------------------
wire [15:0]image_data;
wire image_data_valid;
reg [15:0] image_data_hcnt;
reg [15:0] image_data_vcnt;
reg image_data_hs;
reg image_data_vs;
bit8_trans_bit16 bit8_trans_bit16
(
.clk (loc_clk50m ),
.reset_p (ui_clk_sync_rst ),
.bit8_in (uart_byte ),
.bit8_in_valid (uart_byte_vaild ),
.bit16_out (image_data ),
.bit16_out_valid (image_data_valid)
);
//-------------------------------------------------------------------------------------------
//generate image data hs or vs观察数据是否产生了800*480
always@(posedge loc_clk50m or posedge ui_clk_sync_rst)
if(ui_clk_sync_rst)
image_data_hcnt <= 'd0;
else if(image_data_valid) begin
if(image_data_hcnt == (DISP_WIDTH - 1'b1))
image_data_hcnt <= 'd0;
else
image_data_hcnt <= image_data_hcnt + 1'b1;
end
always@(posedge loc_clk50m or posedge ui_clk_sync_rst)
if(ui_clk_sync_rst)
image_data_vcnt <= 'd0;
else if(image_data_valid) begin
if(image_data_hcnt == (DISP_WIDTH - 1'b1)) begin
if(image_data_vcnt == (DISP_HEIGHT - 1'b1))
image_data_vcnt <= 'd0;
else
image_data_vcnt <= image_data_vcnt + 1'b1;
end
end
//hs
always@(posedge loc_clk50m or posedge ui_clk_sync_rst)
if(ui_clk_sync_rst)
image_data_hs <= 1'b0;
else if(image_data_valid && image_data_hcnt == (DISP_WIDTH - 1'b1))
image_data_hs <= 1'b0;
else
image_data_hs <= 1'b1;
//vs
always@(posedge loc_clk50m or posedge ui_clk_sync_rst)
if(ui_clk_sync_rst)
image_data_vs <= 1'b0;
else if(image_data_valid && image_data_hcnt == (DISP_WIDTH - 1'b1) &&
image_data_vcnt == (DISP_HEIGHT - 1'b1))
image_data_vs <= 1'b0;
else
image_data_vs <= 1'b1;
always@(posedge loc_clk50m or posedge ui_clk_sync_rst)
if(ui_clk_sync_rst)
frame_rx_done_flip <= 1'b0;
else if(image_data_valid && image_data_hcnt == (DISP_WIDTH - 1'b1) &&
image_data_vcnt == (DISP_HEIGHT - 1'b1))
frame_rx_done_flip <= ~frame_rx_done_flip;
//-------------------------------------------------------------------------------------------
assign wrfifo_din = image_data;
assign wrfifo_wren = image_data_valid;
disp_driver disp_driver
(
.ClkDisp (clk_disp ),
.Rst_p (ui_clk_sync_rst),
.Data (rdfifo_dout ),
.DataReq (rdfifo_rden ),
.Disp_HS (TFT_hs ),
.Disp_VS (TFT_vs ),
.Disp_Red (TFT_rgb[15:11] ),
.Disp_Green (TFT_rgb[10:5] ),
.Disp_Blue (TFT_rgb[4:0] ),
.Frame_Begin (frame_begin ),
.Disp_DE (TFT_de ),
.Disp_PCLK (TFT_clk )
);
assign TFT_pwm = 1'b1;
assign wrfifo_clr = ui_clk_sync_rst;
assign rdfifo_clr = frame_begin || ui_clk_sync_rst;
wr_ddr3_fifo wr_ddr3_fifo
(
.rst (wrfifo_clr ), // input wire rst
.wr_clk (loc_clk50m ), // input wire wr_clk
.rd_clk (ui_clk ), // input wire rd_clk
.din (wrfifo_din ), // input wire [15 : 0] din
.wr_en (wrfifo_wren ), // input wire wr_en
.rd_en (wrfifo_rden ), // input wire rd_en
.dout (wrfifo_dout ), // output wire [127 : 0] dout
.full ( ), // output wire full
.empty (wrfifo_empty ), // output wire empty
.rd_data_count (wrfifo_rd_cnt ), // output wire [5 : 0] rd_data_count
.wr_data_count ( ), // output wire [8 : 0] wr_data_count
.wr_rst_busy (wrfifo_wr_rst_busy ), // output wire wr_rst_busy
.rd_rst_busy (wrfifo_rd_rst_busy ) // output wire rd_rst_busy
);
rd_ddr3_fifo rd_ddr3_fifo
(
.rst (rdfifo_clr ), // input wire rst
.wr_clk (ui_clk ), // input wire wr_clk
.rd_clk (loc_clk33m ), // input wire rd_clk
.din (rdfifo_din ), // input wire [127 : 0] din
.wr_en (rdfifo_wren ), // input wire wr_en
.rd_en (rdfifo_rden ), // input wire rd_en
.dout (rdfifo_dout ), // output wire [15 : 0] dout
.full (rdfifo_full ), // output wire full
.empty ( ), // output wire empty
.rd_data_count ( ), // output wire [8 : 0] rd_data_count
.wr_data_count (rdfifo_wr_cnt ), // output wire [5 : 0] wr_data_count
.wr_rst_busy (rdfifo_wr_rst_busy ), // output wire wr_rst_busy
.rd_rst_busy (rdfifo_rd_rst_busy ) // output wire rd_rst_busy
);
always@(posedge ui_clk)
begin
wrfifo_clr_sync_ui_clk <= wrfifo_clr;
wr_addr_clr <= wrfifo_clr_sync_ui_clk;
end
always@(posedge ui_clk)
begin
rdfifo_clr_sync_ui_clk <= rdfifo_clr;
rd_addr_clr <= rdfifo_clr_sync_ui_clk;
end
fifo2mig_axi
#(
.WR_DDR_ADDR_BEGIN (0 ),
.WR_DDR_ADDR_END (DISP_WIDTH*DISP_HEIGHT*2 ),
.RD_DDR_ADDR_BEGIN (0 ),
.RD_DDR_ADDR_END (DISP_WIDTH*DISP_HEIGHT*2 ),
.AXI_ID (4'b0000 ),
.AXI_LEN (8'd31 ) //axi burst length = 32
)fifo2mig_axi
(
//FIFO Interface ports
.wr_addr_clr (wr_addr_clr ), //1:clear sync ui_clk
.wr_fifo_rdreq (wrfifo_rden ),
.wr_fifo_rddata (wrfifo_dout ),
.wr_fifo_empty (wrfifo_empty ),
.wr_fifo_rd_cnt (wrfifo_rd_cnt ),
.wr_fifo_rst_busy (wrfifo_wr_rst_busy | wrfifo_rd_rst_busy),
.rd_addr_clr (rd_addr_clr ), //1:clear sync ui_clk
.rd_fifo_wrreq (rdfifo_wren ),
.rd_fifo_wrdata (rdfifo_din ),
.rd_fifo_alfull (rdfifo_full ),
.rd_fifo_wr_cnt (rdfifo_wr_cnt ),
.rd_fifo_rst_busy (rdfifo_wr_rst_busy | rdfifo_rd_rst_busy),
// Application interface ports
.ui_clk (ui_clk ),
.ui_clk_sync_rst (ui_clk_sync_rst ),
.mmcm_locked (mmcm_locked ),
.init_calib_complete (init_calib_complete ),
// Slave Interface Write Address Ports
.m_axi_awid (s_axi_awid ),
.m_axi_awaddr (s_axi_awaddr ),
.m_axi_awlen (s_axi_awlen ),
.m_axi_awsize (s_axi_awsize ),
.m_axi_awburst (s_axi_awburst ),
.m_axi_awlock (s_axi_awlock ),
.m_axi_awcache (s_axi_awcache ),
.m_axi_awprot (s_axi_awprot ),
.m_axi_awqos (s_axi_awqos ),
.m_axi_awvalid (s_axi_awvalid ),
.m_axi_awready (s_axi_awready ),
// Slave Interface Write Data Ports
.m_axi_wdata (s_axi_wdata ),
.m_axi_wstrb (s_axi_wstrb ),
.m_axi_wlast (s_axi_wlast ),
.m_axi_wvalid (s_axi_wvalid ),
.m_axi_wready (s_axi_wready ),
// Slave Interface Write Response Ports
.m_axi_bid (s_axi_bid ),
.m_axi_bresp (s_axi_bresp ),
.m_axi_bvalid (s_axi_bvalid ),
.m_axi_bready (s_axi_bready ),
// Slave Interface Read Address Ports
.m_axi_arid (s_axi_arid ),
.m_axi_araddr (s_axi_araddr ),
.m_axi_arlen (s_axi_arlen ),
.m_axi_arsize (s_axi_arsize ),
.m_axi_arburst (s_axi_arburst ),
.m_axi_arlock (s_axi_arlock ),
.m_axi_arcache (s_axi_arcache ),
.m_axi_arprot (s_axi_arprot ),
.m_axi_arqos (s_axi_arqos ),
.m_axi_arvalid (s_axi_arvalid ),
.m_axi_arready (s_axi_arready ),
// Slave Interface Read Data Ports
.m_axi_rid (s_axi_rid ),
.m_axi_rdata (s_axi_rdata ),
.m_axi_rresp (s_axi_rresp ),
.m_axi_rlast (s_axi_rlast ),
.m_axi_rvalid (s_axi_rvalid ),
.m_axi_rready (s_axi_rready )
);
mig_7series_0 u_mig_7series_0 (
// Memory interface ports
.ddr3_addr (ddr3_addr ), // output [13:0] ddr3_addr
.ddr3_ba (ddr3_ba ), // output [2:0] ddr3_ba
.ddr3_cas_n (ddr3_cas_n ), // output ddr3_cas_n
.ddr3_ck_n (ddr3_ck_n ), // output [0:0] ddr3_ck_n
.ddr3_ck_p (ddr3_ck_p ), // output [0:0] ddr3_ck_p
.ddr3_cke (ddr3_cke ), // output [0:0] ddr3_cke
.ddr3_ras_n (ddr3_ras_n ), // output ddr3_ras_n
.ddr3_reset_n (ddr3_reset_n ), // output ddr3_reset_n
.ddr3_we_n (ddr3_we_n ), // output ddr3_we_n
.ddr3_dq (ddr3_dq ), // inout [15:0] ddr3_dq
.ddr3_dqs_n (ddr3_dqs_n ), // inout [1:0] ddr3_dqs_n
.ddr3_dqs_p (ddr3_dqs_p ), // inout [1:0] ddr3_dqs_p
.init_calib_complete (init_calib_complete ), // output init_calib_complete
.ddr3_cs_n (ddr3_cs_n ), // output [0:0] ddr3_cs_n
.ddr3_dm (ddr3_dm ), // output [1:0] ddr3_dm
.ddr3_odt (ddr3_odt ), // output [0:0] ddr3_odt
// Application interface ports
.ui_clk (ui_clk ), // output ui_clk
.ui_clk_sync_rst (ui_clk_sync_rst ), // output ui_clk_sync_rst
.mmcm_locked (mmcm_locked ), // output mmcm_locked
.aresetn (aresetn ), // input aresetn
.app_sr_req (1'b0 ), // input app_sr_req
.app_ref_req (1'b0 ), // input app_ref_req
.app_zq_req (1'b0 ), // input app_zq_req
.app_sr_active ( ), // output app_sr_active
.app_ref_ack ( ), // output app_ref_ack
.app_zq_ack ( ), // output app_zq_ack
// Slave Interface Write Address Ports
.s_axi_awid (s_axi_awid ), // input [3:0] s_axi_awid
.s_axi_awaddr (s_axi_awaddr ), // input [27:0] s_axi_awaddr
.s_axi_awlen (s_axi_awlen ), // input [7:0] s_axi_awlen
.s_axi_awsize (s_axi_awsize ), // input [2:0] s_axi_awsize
.s_axi_awburst (s_axi_awburst ), // input [1:0] s_axi_awburst
.s_axi_awlock (s_axi_awlock ), // input [0:0] s_axi_awlock
.s_axi_awcache (s_axi_awcache ), // input [3:0] s_axi_awcache
.s_axi_awprot (s_axi_awprot ), // input [2:0] s_axi_awprot
.s_axi_awqos (s_axi_awqos ), // input [3:0] s_axi_awqos
.s_axi_awvalid (s_axi_awvalid ), // input s_axi_awvalid
.s_axi_awready (s_axi_awready ), // output s_axi_awready
// Slave Interface Write Data Ports
.s_axi_wdata (s_axi_wdata ), // input [127:0] s_axi_wdata
.s_axi_wstrb (s_axi_wstrb ), // input [15:0] s_axi_wstrb
.s_axi_wlast (s_axi_wlast ), // input s_axi_wlast
.s_axi_wvalid (s_axi_wvalid ), // input s_axi_wvalid
.s_axi_wready (s_axi_wready ), // output s_axi_wready
// Slave Interface Write Response Ports
.s_axi_bid (s_axi_bid ), // output [3:0] s_axi_bid
.s_axi_bresp (s_axi_bresp ), // output [1:0] s_axi_bresp
.s_axi_bvalid (s_axi_bvalid ), // output s_axi_bvalid
.s_axi_bready (s_axi_bready ), // input s_axi_bready
// Slave Interface Read Address Ports
.s_axi_arid (s_axi_arid ), // input [3:0] s_axi_arid
.s_axi_araddr (s_axi_araddr ), // input [27:0] s_axi_araddr
.s_axi_arlen (s_axi_arlen ), // input [7:0] s_axi_arlen
.s_axi_arsize (s_axi_arsize ), // input [2:0] s_axi_arsize
.s_axi_arburst (s_axi_arburst ), // input [1:0] s_axi_arburst
.s_axi_arlock (s_axi_arlock ), // input [0:0] s_axi_arlock
.s_axi_arcache (s_axi_arcache ), // input [3:0] s_axi_arcache
.s_axi_arprot (s_axi_arprot ), // input [2:0] s_axi_arprot
.s_axi_arqos (s_axi_arqos ), // input [3:0] s_axi_arqos
.s_axi_arvalid (s_axi_arvalid ), // input s_axi_arvalid
.s_axi_arready (s_axi_arready ), // output s_axi_arready
// Slave Interface Read Data Ports
.s_axi_rid (s_axi_rid ), // output [3:0] s_axi_rid
.s_axi_rdata (s_axi_rdata ), // output [127:0] s_axi_rdata
.s_axi_rresp (s_axi_rresp ), // output [1:0] s_axi_rresp
.s_axi_rlast (s_axi_rlast ), // output s_axi_rlast
.s_axi_rvalid (s_axi_rvalid ), // output s_axi_rvalid
.s_axi_rready (s_axi_rready ), // input s_axi_rready
// System Clock Ports
.sys_clk_i (loc_clk200m ),
.sys_rst (mig_reset_n ) // input sys_rst
);
endmodule
五、uart_ddr3_tft模块仿真文件
`timescale 1ns / 1ns
`define CLK_PERIOD 20
module uart_ddr3_tft_tb();
reg clk50m;
reg reset_n;
wire [15:0] TFT_rgb; //TFT数据输出
wire TFT_hs; //TFT行同步信号
wire TFT_vs; //TFT场同步信号
wire TFT_clk; //TFT像素时钟
wire TFT_de; //TFT数据使能
wire TFT_pwm; //TFT背光控制
wire [13:0] ddr3_addr;
wire [2:0] ddr3_ba;
wire ddr3_cas_n;
wire [0:0] ddr3_ck_n;
wire [0:0] ddr3_ck_p;
wire [0:0] ddr3_cke;
wire ddr3_ras_n;
wire ddr3_reset_n;
wire ddr3_we_n;
wire [15:0] ddr3_dq;
wire [1:0] ddr3_dqs_n;
wire [1:0] ddr3_dqs_p;
wire [0:0] ddr3_cs_n;
wire [1:0] ddr3_dm;
wire [0:0] ddr3_odt;
initial clk50m = 1;
always #(`CLK_PERIOD/2) clk50m = ~clk50m;
initial begin
reset_n = 1'b0;
#201;
reset_n = 1'b1;
@(posedge uart_ddr3_tft.init_calib_complete)
@(posedge TFT_vs);
@(posedge TFT_vs);
@(posedge TFT_vs);
$stop;
end
uart_ddr3_tft
uart_ddr3_tft
(
//System clock reset
.clk50m (clk50m ), //系统时钟输入,50M
.reset_n (reset_n ), //复位信号输入,低有效
//led
.led ( ), //指示灯
//Uart interface
.uart_rx ( ), //串口输入信号
//TFT Interface
.TFT_rgb (TFT_rgb ), //TFT数据输出
.TFT_hs (TFT_hs ), //TFT行同步信号
.TFT_vs (TFT_vs ), //TFT场同步信号
.TFT_clk (TFT_clk ), //TFT像素时钟
.TFT_de (TFT_de ), //TFT数据使能
.TFT_pwm (TFT_pwm ), //TFT背光控制
// Memory interface ports
.ddr3_addr (ddr3_addr ), // output [13:0] ddr3_addr
.ddr3_ba (ddr3_ba ), // output [2:0] ddr3_ba
.ddr3_cas_n (ddr3_cas_n ), // output ddr3_cas_n
.ddr3_ck_n (ddr3_ck_n ), // output [0:0] ddr3_ck_n
.ddr3_ck_p (ddr3_ck_p ), // output [0:0] ddr3_ck_p
.ddr3_cke (ddr3_cke ), // output [0:0] ddr3_cke
.ddr3_ras_n (ddr3_ras_n ), // output ddr3_ras_n
.ddr3_reset_n (ddr3_reset_n ), // output ddr3_reset_n
.ddr3_we_n (ddr3_we_n ), // output ddr3_we_n
.ddr3_dq (ddr3_dq ), // inout [15:0] ddr3_dq
.ddr3_dqs_n (ddr3_dqs_n ), // inout [1:0] ddr3_dqs_n
.ddr3_dqs_p (ddr3_dqs_p ), // inout [1:0] ddr3_dqs_p
.ddr3_cs_n (ddr3_cs_n ), // output [0:0] ddr3_cs_n
.ddr3_dm (ddr3_dm ), // output [1:0] ddr3_dm
.ddr3_odt (ddr3_odt ) // output [0:0] ddr3_odt
);
ddr3_model ddr3_model
(
.rst_n (ddr3_reset_n ),
.ck (ddr3_ck_p ),
.ck_n (ddr3_ck_n ),
.cke (ddr3_cke ),
.cs_n (ddr3_cs_n ),
.ras_n (ddr3_ras_n ),
.cas_n (ddr3_cas_n ),
.we_n (ddr3_we_n ),
.dm_tdqs(ddr3_dm ),
.ba (ddr3_ba ),
.addr (ddr3_addr ),
.dq (ddr3_dq ),
.dqs (ddr3_dqs_p ),
.dqs_n (ddr3_dqs_n ),
.tdqs_n ( ),
.odt (ddr3_odt )
);
endmodule
六、uart_ddr3_tft模块仿真文件
在顶层设计分析综合没有错误并且顶层仿真确认设计功能没有问题后,进行上板验证。对工程的管脚和时钟进行约束后,生成 Bit 文件。下载完成后,开发板上 LED0~LED2 会亮,TFT5.0 寸屏上显示花屏状态。如下图所示。
出现这种花屏是因为这个时候,DDR3 中并未写入数据,显示的数据是不可知的一些数据。LED0 和 LED1 分别表示的是 DDR 控制器内时钟锁相环的 locked 信号和 DDR 初始化校准完成信号的状态,亮表示这个两个信号均变为高电平,说明 DDR 已经正常完成初始化和校准操作。接下来通过串口传图工具向 FPGA 传输图片数据。
这里提供的上位机要求图片为位深度为 24 或 16 的 bmp 格式图片,图片的宽度和高度需要为 800480(插 5 寸屏情况下)或 480272(插 4.3 寸屏情况下)。关于图片的信息可通过右键图片查看其属性,在属性的详细信息窗口可以看到图片大小,位深度等信息。
传图过程中,可以看到 TFT 屏上开始显示发送的图片。图片传送完成后,TFT 屏显示效果如下。
【附件:】链接:https://pan.baidu.com/s/1YPc3aytOKLQmEqpLnjk4rw?pwd=wzxj
提取码:wzxj