结合串口接收模块和 tft 显示屏控制模块,设计一个基于 DDR3—Native接口的串口传图帧缓存系统。
提示:以下是本篇文章正文内容,下面案例可供参考
(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生成参考 IP生成 )。
(5)rd_ddr3_fifo 模块:使用的 FIFO IP ,主要用于读出 DDR3 数据的缓存、解决数据
跨时钟域以及数据位宽的转换(IP生成参考 IP生成 )。
(6)fifo_ddr3_native_fifo 模块:主要是用于接口的转换,将 MIG IP 的Native接口换成与 FIFO
对接的接口(可参考第五节 )。
(7)mig_7series_native 模块: DDR3 控制器,使用的 Memory Interface Generator(MIG 7
Series)IP(可参考 DDR3 控制器 MIG IP 详解完整版 )。
(8)pll 模块:上述各个模块所需时钟的产生,使用 PLL IP。除去使用 IP 和前面章节讲过的模块外,还需要设计的模块包括 bit8_trans_bit16 模块和fifo_ddr3_native_fifo 模块(IP生成在下方有介绍)。
(9)顶层模块uart_ddr3_native_tft,用于实现上述模块的转换与连接(参考第三节)。
该模块主要作用是串联其他模块,完成传图过程。其中个模块对应的介绍均在第二节后附有连接,以供参考。
`timescale 1ns / 1ns
//
// Create Date: 2023/06/20 08:58:45
// Module Name: uart_fifo_ddr3_fifo_tft
// Name: 小王在努力...
// Revision 0.01 - File Created
// Additional Comments:
//
module uart_ddr3_native_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
);
//pll interface
wire loc_clk200M;
wire loc_clk33M ;
wire loc_clk50M ;
wire pll_locked ;
//bit8_trans_bit16 interface
wire [15:0]image_data;
wire image_data_valid;
// fifo_mig_axi_fifo Interface
wire [15:0]rdfifo_dout ;
wire ui_clk ;
wire ui_clk_sync_rst ;
wire init_calib_complete;
wire rdfifo_rden ;
wire rdfifo_wren;
//disp_driver interface
wire frame_begin;
wire rdfifo_WR_EN;
//--------------------------------------------------------
//测试数据
parameter test_count = 24'd32400,
test_count_div_8 = 24'd4050,
uart_byte_cnt_x2 = test_count*2;
assign led = {init_calib_complete,pll_locked,rdfifo_WR_EN,TFT_vs};
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 Interface
//------------------------------------------------------------------------
wire [7:0]uart_byte ;
wire uart_byte_vaild;
uart_byte_rx#(
.CLK_FRQ(1000000000)
)
uart_byte_rx(
.clk (loc_clk50M ),
.reset_p (ui_clk_sync_rst ),
.baud_set (3'd4 ), //115200bps
.uart_rx (uart_rx ),
.data_byte(uart_byte ),
.rx_done (uart_byte_vaild ) //一个字节数据有效的标志
);
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------
//-------------------------------
// 测试使用
// 测试时将124-142注释
//-------------------------------
// reg [23:0]uart_byte_cnt;
// reg [7:0]uart_byte ;
// reg uart_byte_vaild;
// always @ (posedge loc_clk50M or negedge ui_clk_sync_rst)
// if(ui_clk_sync_rst)
// uart_byte_cnt <= 0;
// else if (fifo_ddr3_native_fifo.wr_fifo_rst_busy == 1'b0)
// begin
// if (uart_byte_cnt == uart_byte_cnt_x2 )
// uart_byte_cnt <= uart_byte_cnt;
// else
// uart_byte_cnt <= uart_byte_cnt + 1;
// end
// else
// uart_byte_cnt <= 0;
// always @ (posedge loc_clk50M or negedge ui_clk_sync_rst)
// if(ui_clk_sync_rst)
// uart_byte <= 0;
// else if(fifo_ddr3_native_fifo.wr_fifo_rst_busy == 1'b0)
// begin
// if (uart_byte_cnt == uart_byte_cnt_x2)
// uart_byte <= 0;
// else
// uart_byte <= uart_byte_cnt[7:0];
// end
// else
// uart_byte <= 0;
// always @ (posedge loc_clk50M or negedge ui_clk_sync_rst)
// if(ui_clk_sync_rst)
// uart_byte_vaild <= 0;
// else if(fifo_ddr3_native_fifo.wr_fifo_rst_busy == 1'b0)
// if (uart_byte_cnt == uart_byte_cnt_x2 )
// uart_byte_vaild <= 0;
// else
// uart_byte_vaild <= 1;
// else
// uart_byte_vaild <= 0;
//-------------------------------------------------------------------------------------------------------
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)
);
fifo_ddr3_native_fifo#(
. rd_req_cnt_thresh (24'd10 ) ,
. wr_rd_cnt (test_count ) ,
. wr_ddr_cnt (test_count_div_8 )
)fifo_ddr3_native_fifo
(
//wr_ddr3_fifo ports
.wrfifo_rst (ui_clk_sync_rst ) ,
.loc_clk50M (loc_clk50M ) ,
.wrfifo_din (image_data ) ,
.wrfifo_wren (image_data_valid ) ,
//rd_ddr3_fifo ports
.rdfifo_rst (ui_clk_sync_rst ) ,
.loc_clk33M (loc_clk33M ) ,
.rdfifo_rden (rdfifo_rden ) ,
.rdfifo_dout (rdfifo_dout ) ,
.rdfifo_wren (rdfifo_wren ) ,
.rdfifo_WR_EN (rdfifo_WR_EN ) ,
//DDR3 Interface
//input
. loc_clk200M (loc_clk200M ) ,
. xx_sys_rst (pll_locked ) , //用于连接 pll_locked
//output
. ui_clk (ui_clk ) ,
. ui_clk_sync_rst (ui_clk_sync_rst) ,
. init_calib_complete(init_calib_complete) ,
//DDR3 Interface
// Inouts
. ddr3_dq (ddr3_dq ) ,
. ddr3_dqs_n (ddr3_dqs_n ) ,
. ddr3_dqs_p (ddr3_dqs_p ) ,
// Outputs
. ddr3_addr (ddr3_addr ) ,
. ddr3_ba (ddr3_ba ) ,
. ddr3_ras_n (ddr3_ras_n ) ,
. ddr3_cas_n (ddr3_cas_n ) ,
. ddr3_we_n (ddr3_we_n ) ,
. ddr3_reset_n (ddr3_reset_n) ,
. ddr3_ck_p (ddr3_ck_p ) ,
. ddr3_ck_n (ddr3_ck_n ) ,
. ddr3_cke (ddr3_cke ) ,
. ddr3_cs_n (ddr3_cs_n ) ,
. ddr3_dm (ddr3_dm ) ,
. ddr3_odt (ddr3_odt )
);
wire [15:0] disp_data;
wire DataReq;
wire [11:0]hcount;
wire [11:0]vcount;
disp_driver disp_driver
(
.ClkDisp (loc_clk33M ),
.Rst_p (ui_clk_sync_rst),
.EN (rdfifo_WR_EN ),
.Data (disp_data ),
//.Data (rdfifo_dout ),
.DataReq (DataReq ),
.hcount (hcount),
.vcount (vcount),
.Disp_HS (TFT_hs ),
.Disp_VS (TFT_vs ),
.Disp_RGB (TFT_rgb ),
.Disp_DE (TFT_de ),
.Disp_PCLK (TFT_clk ),
.TFT_PWM (TFT_PWM )
);
wire data_en;
assign data_en = DataReq && (hcount <= 12'd180) && (vcount <= 12'd180);
assign disp_data = data_en? rdfifo_dout :16'h00;//将多余图像显示红色
assign rdfifo_rden = data_en? 1'b1:1'b0;
endmodule
`timescale 1ns / 1ns
//
// Create Date: 2023/06/20 08:58:45
// Module Name: uart_fifo_ddr3_fifo_tft_tb
// Name: 小王在努力...
// Revision 0.01 - File Created
//
`define CLK_PERIOD 20
module uart_ddr3_native_tft_tb();
reg clk50m;
reg reset_n;
reg uart_rx;
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;
//uart_rx = 1'b1;
#201;
reset_n = 1'b1;
@(negedge uart_ddr3_native_tft.ui_clk_sync_rst);
@(posedge uart_ddr3_native_tft.init_calib_complete)
@(posedge TFT_vs);
@(posedge TFT_vs);
@(posedge TFT_vs);
$stop;
end
uart_ddr3_native_tft
uart_ddr3_native_tft
(
//System clock reset
.clk50m (clk50m ), //系统时钟输入,50M
.reset_n (reset_n ), //复位信号输入,低有效
//led
.led ( ), //指示灯
//Uart interface
.uart_rx (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
`timescale 1ns / 1ps
//
// Module Name: fifo_ddr3_native_fifo
// Name: 小王在努力...
//
module fifo_ddr3_native_fifo
#(
parameter rd_req_cnt_thresh = 24'd6 ,
wr_rd_cnt = 24'd64 ,
wr_ddr_cnt = 24'd8
//此部分数据可根据实际需要改变 (wr_rd_cnt)64*16位 = 128位*8(wr_ddr_cnt )
)
(
//wr_ddr3_fifo ports
input wrfifo_rst ,
input loc_clk50M ,
input [15:0]wrfifo_din ,
input wrfifo_wren ,
//rd_ddr3_fifo ports
input rdfifo_rst ,
input loc_clk33M ,
input rdfifo_rden ,
output [15:0]rdfifo_dout ,
output rdfifo_wren ,
//tft的EN信号
output reg rdfifo_WR_EN ,
//DDR3 Interface
//input
input loc_clk200M ,
input xx_sys_rst , //用于连接 pll_locked
//output
output ui_clk ,
output ui_clk_sync_rst ,
output init_calib_complete ,
//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
);
//------------------------------------------
//状态机参数
localparam S_IDLE = 4'b0001 ,
S_WRITE = 4'b0010 ,
S_WAIT = 4'b0100 ,
S_READ = 4'b1000 ;
//------------------------------------------
//**********************************
//信号定义说明
//**********************************
//wrfifo ports
wire[127:0]wrfifo_dout ;
wire wrfifo_rden ;
wire wrfifo_wr_rst_busy ;
wire wrfifo_rd_rst_busy ;
//rdfifo ports
wire[127:0]rdfifo_din ;
wire rdfifo_wr_rst_busy ;
wire rdfifo_rd_rst_busy ;
wire [11:0]rdfifo_wr_cnt ;
//cmd ports
reg [27:0]app_addr ;
wire [2:0]app_cmd ;
wire app_en ;
wire app_rdy ;
//write data ports
wire[127:0]app_wdf_data ;
wire app_wdf_end ;
wire app_wdf_wren ;
wire app_wdf_rdy ;
//read data ports
wire[127:0]app_rd_data ;
wire app_rd_data_end ;
wire app_rd_data_valid ;
//ddr3 相关信号
wire app_sr_active;
wire app_ref_ack;
wire app_zq_ack ;
//状态机控制相关信号
reg [23:0]wrfifo_din_cnt;
reg wrfifo_WR_EN;
//tft控制信号
reg [23:0]rdfifo_din_cnt;
//wr_ddr3_req ports
wire wr_fifo_rst_busy ;
wire wr_ddr3_req ;
//rd_ddr3_req ports
wire rd_fifo_rst_busy ;
wire rd_ddr3_req ;
//state transform
reg [3:0] curr_state ;
//wrfifo / rdfifo
assign wrfifo_rden = app_wdf_wren && app_wdf_rdy;
assign rdfifo_din = app_rd_data;
assign rdfifo_wren = app_rd_data_valid;
//--------------------------------------------------------------------------------
//------------------------------------
//根据wrfifo写入的是16位数据读出为128,
//由16->128此过程需要转换时间因此当ddr
//过早请求数据(128位),而此时wrfifo
//的16位还未转化为128,将造成数据的丢失。
//设计将wrfifo的16——>128全部完成后,ddr
//在请求数据,这样可以避免数据丢失
//------------------------------------
//判断wrfifo是否将数据全部写入
always @(posedge loc_clk50M or negedge wrfifo_rst)
begin
if(wrfifo_rst)
wrfifo_din_cnt <= 0;
else if( wrfifo_wren)
begin
if(wrfifo_din_cnt == wr_rd_cnt-1 )
wrfifo_din_cnt <= 0;
else
wrfifo_din_cnt <= wrfifo_din_cnt + 1;
end
else
wrfifo_din_cnt <= wrfifo_din_cnt;
end
always @(posedge loc_clk50M or negedge wrfifo_rst)
begin
if(wrfifo_rst)
wrfifo_WR_EN <= 0;
else if( wrfifo_din_cnt == wr_rd_cnt-1)
wrfifo_WR_EN <= 1;
else
wrfifo_WR_EN <= wrfifo_WR_EN ;
end
//--------------------------------------------------------------------------------
//判断读写的条件
assign wr_fifo_rst_busy = (wrfifo_wr_rst_busy | wrfifo_rd_rst_busy),
wr_ddr3_req = ((wr_fifo_rst_busy == 1'b0) && wrfifo_WR_EN) ? 1'b1:1'b0,
rd_fifo_rst_busy = (rdfifo_wr_rst_busy | rdfifo_rd_rst_busy),
rd_ddr3_req = ((rd_fifo_rst_busy == 1'b0) && (rdfifo_wr_cnt <= rd_req_cnt_thresh)) ;
//**********************************
//state transform
//**********************************
assign IDLE_transform_WRITE = ((curr_state == S_IDLE ) && init_calib_complete && (wr_ddr3_req == 1'b1) ) ,
WRITE_transform_WAIT = ((curr_state == S_WRITE ) && app_rdy && app_wdf_rdy && (app_addr == wr_rd_cnt-8)),
WRITE_transform_COUNT = ((curr_state == S_WRITE) && app_rdy && app_wdf_rdy),
WAIT_transform_RDED = ((curr_state == S_WAIT ) && (rd_ddr3_req == 1'b1)) ,
READ_transform_WAIT = ((curr_state == S_READ ) && app_rdy && (app_addr == wr_rd_cnt-8) ),
READ_transform_COUNT = ((curr_state == S_READ ) && app_rdy ) ;
//-----------------------------------------------------------------------------------------------
//**********************************
//状态转移实现
//**********************************
//在写状态MIG IP 命令接收和数据接收都准备好,或者在读状态命令接收准备好,此时拉高使能信号,
assign app_en = WRITE_transform_COUNT || READ_transform_COUNT ;
//在写状态,命令接收和数据接收都准备好,此时拉高写使能
assign app_wdf_wren = WRITE_transform_COUNT;
//由于 DDR3 芯片时钟和用户时钟的分频选择 4:1,突发长度为 8,故两个信号相同
assign app_wdf_end = app_wdf_wren;
//处于读的时候命令值为 1,其他时候命令值为 0
assign app_cmd = (curr_state == S_READ) ? 3'd1 :3'd0;
assign app_wdf_data = wrfifo_dout;
//**********************************
//state machine
//**********************************
always @ (posedge ui_clk or negedge ui_clk_sync_rst)
if(ui_clk_sync_rst)
begin
curr_state <= S_IDLE;
app_addr <= 0;
end
else if(init_calib_complete)
begin
case(curr_state)
S_IDLE:begin
if(IDLE_transform_WRITE)
begin
curr_state <= S_WRITE;
app_addr <= 0;
end
else
curr_state <= curr_state;
end
S_WRITE:begin
if(WRITE_transform_WAIT)
curr_state <= S_WAIT;
else if(WRITE_transform_COUNT)
begin
app_addr <= app_addr + 8;
end
else begin
curr_state <= curr_state;
app_addr <= app_addr;
end
end
S_WAIT:begin
if(WAIT_transform_RDED)
begin
curr_state <= S_READ;
app_addr <= 0;
end
else
curr_state <= curr_state;
end
S_READ:begin
if(READ_transform_WAIT)
curr_state <= S_WAIT;
else if(READ_transform_COUNT)
begin
app_addr <= app_addr + 8;
end
else begin
curr_state <= curr_state;
app_addr <= app_addr;
end
end
default:begin
curr_state <= S_IDLE;
app_addr <= 0;
end
endcase
end
//-----------------------------------------------------------------------------------------------
//计算rdfifo_wren拉低 在rdfifo写数据完成后在对TFT相关内容操作
//防止tft请求数据,而rdfifo还未写入数据,造成数据丢失。
always @(posedge ui_clk or negedge rdfifo_rst)
begin
if(rdfifo_rst)
rdfifo_din_cnt <= 0;
else if( rdfifo_wren)
begin
if(rdfifo_din_cnt == wr_ddr_cnt-1 )
rdfifo_din_cnt <= 0;
else
rdfifo_din_cnt <= rdfifo_din_cnt + 1;
end
else
rdfifo_din_cnt <= rdfifo_din_cnt;
end
always @(posedge ui_clk or negedge rdfifo_rst)
begin
if(rdfifo_rst)
rdfifo_WR_EN <= 0;
else if( rdfifo_din_cnt == wr_ddr_cnt-1)
rdfifo_WR_EN <= 1;
else
rdfifo_WR_EN <=rdfifo_WR_EN ;
end
//-----------------------------------------------------------------------------------------------------------
//**********************************
//例化 wr_ddr3_fifo、rd_ddr3_fifo、mig_7series_0
//**********************************
wr_ddr3_fifo wr_ddr3_fifo (
.rst (wrfifo_rst), // 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 ( ), // output wire empty
.rd_data_count( ), // output wire [9 : 0] rd_data_count
.wr_data_count( ), // output wire [12 : 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_rst ), // 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 ( ), // output wire full
.empty ( ), // output wire empty
.rd_data_count( ), // output wire [12 : 0] rd_data_count
.wr_data_count(rdfifo_wr_cnt), // output wire [9 : 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
);
mig_7series_native u_mig_7series_native (
// 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
.app_addr (app_addr ), // input [27:0] app_addr
.app_cmd (app_cmd ), // input [2:0] app_cmd
.app_en (app_en ), // input app_en
.app_wdf_data (app_wdf_data ), // input [127:0] app_wdf_data
.app_wdf_end (app_wdf_end ), // input app_wdf_end
.app_wdf_wren (app_wdf_wren ), // input app_wdf_wren
.app_rd_data (app_rd_data ), // output [127:0] app_rd_data
.app_rd_data_end (app_rd_data_end ), // output app_rd_data_end
.app_rd_data_valid (app_rd_data_valid), // output app_rd_data_valid
.app_rdy (app_rdy ), // output app_rdy
.app_wdf_rdy (app_wdf_rdy ), // output app_wdf_rdy
.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 (app_sr_active ), // output app_sr_active
.app_ref_ack (app_ref_ack ), // output app_ref_ack
.app_zq_ack (app_zq_ack ), // output app_zq_ack
.ui_clk (ui_clk ), // output ui_clk
.ui_clk_sync_rst (ui_clk_sync_rst ), // output ui_clk_sync_rst
.app_wdf_mask (16'h0000 ), // input [15:0] app_wdf_mask
// System Clock Ports
.sys_clk_i (loc_clk200M ),
.sys_rst (xx_sys_rst ) // input sys_rst
);
endmodule
`timescale 1ns / 1ns
//
// Module Name: fifo_ddr3_native_fifo_tb
// Name: 小王在努力...
//
module fifo_ddr3_native_fifo_tb();
reg wrfifo_rst;
reg loc_clk50M;
reg [15:0]wrfifo_din;
reg wrfifo_wren;
reg rdfifo_rst;
reg loc_clk33M;
reg rdfifo_rden;
wire[15:0]rdfifo_dout;
wire rdfifo_WR_EN;
reg loc_clk200M;
reg xx_sys_rst;
wire ui_clk;
wire ui_clk_sync_rst;
wire init_calib_complete;
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 loc_clk200M = 1'b1;
always #2.5 loc_clk200M = ~loc_clk200M;
initial loc_clk50M = 1'b1;
always #10 loc_clk50M = ~loc_clk50M;
initial loc_clk33M = 1'b1;
always #15 loc_clk33M = ~loc_clk33M;
initial begin
xx_sys_rst = 1'b0;
wrfifo_rst = 1'b1;
wrfifo_wren= 1'b0;
wrfifo_din = 16'd0;
rdfifo_rst = 1'b1;
rdfifo_rden= 1'b0;
#201;
xx_sys_rst = 1'b1;
#200;
wrfifo_rst = 1'b0;
rdfifo_rst = 1'b0;
@(posedge init_calib_complete)
#200;
wr_data(16'd100,16'd64);
#2000;
rd_data(16'd64);
#5000;
$stop;
end
task wr_data;
input [15:0]data_begin;
input [15:0]wr_data_cnt;
begin
wrfifo_wren = 1'b0;
wrfifo_din = data_begin;
@(posedge loc_clk50M);
#1 wrfifo_wren = 1'b1;
repeat(wr_data_cnt)
begin
@(posedge loc_clk50M);
wrfifo_din = wrfifo_din + 1'b1;
end
#1 wrfifo_wren = 1'b0;
end
endtask
task rd_data;
input [15:0]rd_data_cnt;
begin
rdfifo_rden = 1'b0;
@(posedge loc_clk33M);
#1 rdfifo_rden = 1'b1;
repeat(rd_data_cnt)
begin
@(posedge loc_clk33M);
end
#1 rdfifo_rden = 1'b0;
end
endtask
fifo_ddr3_native_fifo
#(
. wr_req_cnt_thresh (24'd6 ) ,
. rd_req_cnt_thresh (24'd6 ) ,
. wr_rd_cnt (24'd64 ) ,
. wr_ddr_cnt (24'd8 )
)fifo_ddr3_native_fifo
(
//wr_ddr3_fifo ports
.wrfifo_rst (wrfifo_rst) ,
.loc_clk50M (loc_clk50M ) ,
.wrfifo_din (wrfifo_din) ,
.wrfifo_wren (wrfifo_wren) ,
//rd_ddr3_fifo ports
.rdfifo_rst (rdfifo_rst) ,
.loc_clk33M (loc_clk33M) ,
.rdfifo_rden (rdfifo_rden) ,
.rdfifo_dout (rdfifo_dout) ,
.rdfifo_WR_EN (rdfifo_WR_EN) ,
//DDR3 Interface
//input
. loc_clk200M (loc_clk200M) ,
. xx_sys_rst (xx_sys_rst) , //用于连接 pll_locked
//output
. ui_clk (ui_clk) ,
. ui_clk_sync_rst (ui_clk_sync_rst) ,
. init_calib_complete (init_calib_complete) ,
//DDR3 Interface
// Inouts
. ddr3_dq (ddr3_dq ) ,
. ddr3_dqs_n (ddr3_dqs_n ) ,
. ddr3_dqs_p (ddr3_dqs_p ) ,
// Outputs
. ddr3_addr (ddr3_addr ) ,
. ddr3_ba (ddr3_ba ) ,
. ddr3_ras_n (ddr3_ras_n ) ,
. ddr3_cas_n (ddr3_cas_n ) ,
. ddr3_we_n (ddr3_we_n ) ,
. ddr3_reset_n (ddr3_reset_n) ,
. ddr3_ck_p (ddr3_ck_p ) ,
. ddr3_ck_n (ddr3_ck_n ) ,
. ddr3_cke (ddr3_cke ) ,
. ddr3_cs_n (ddr3_cs_n ) ,
. ddr3_dm (ddr3_dm ) ,
. ddr3_odt (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
在顶层设计分析综合没有错误并且顶层仿真确认设计功能没有问题后,进行上板验证。对工程的管脚和时钟进行约束后,生成 Bit 文件。
这里提供的图片为位深度为 16 的 图片,图片的宽度和高度需要为180*180。传图过程中,可以看到 TFT 屏上开始显示发送的图片。图片传送完成后,TFT 屏显示效果如下。
【附件:】链接:https://pan.baidu.com/s/1MdA5rjA9xWzU3rk27PNnmw?pwd=qs4i
提取码:qs4i