1.原理图——————这次设计的数据流是产生数据的模块是image-ctrl模块、ddr3控制模块、hdmi-buffer、vga-ctrl模块、以及hdmi转换模块。
该模块的有2个操作始终,其中vga_clk 65M是用来产生数据的,ui_clk为ddr3控制模块的写入数据与地址的时钟,跨时钟域数据传输将32bit的图像数据转换为128bit的数据。rd_en信号的产生是由image-fifo的读出计数器产生的。而参数为何是14是因为当ddr3中存在16个数据时,对应的fifo 读出来的计数是14因而参数为14。
这是ddr3的整个模块的控制信号,信号过多,因此在程序中做了详细介绍。
这是hdmi-buffer的控制模块,是将ddr3存储的数据读出来,然后数据传给vga模块,最终通过hdmi-ctrl将数据转换为差分信号,再以单bit形式显示在显示器上。
2.关键程序
`timescale 1ns / 1ps
module ddr3_bank_ctrl(
input wire ui_clk_sync_rst , //经过ddr3 ip核后产生的高有效复位信号①
input wire ui_clk , //经过ddr3 产生的100M时钟②
input wire calib_complete , //calib_done③
input wire rd_data_valid , //ddr3输出的有效数据使能信号④
output wire ddr3_app_en , //ddr3的命令使能信号⑤
input wire app_rdy , //ddr3输入的读准备信号⑥
output wire[2:0] app_cmd , //读写命令控制⑦
output wire[27:0] out_addr , //输入到ddr3的地址⑧
output wire app_wdf_wren , //写使能信号⑨
input wire app_wdf_rdy , //ddr3输入的写准备信号⑩
output wire[127:0] out_data , //输入到ddr3的数据①
//input wire clk_125M , //输入到读写fifo的数据使能时钟②
input wire wf_wren , //输入到写fifo的地址数据使能信号③
input wire[127:0] data_in , //输入写fifo的数据④
input wire[31:0] data_addr , //输入写ffio的地址⑤
output wire app_wdf_end , //ddr3对应的写结束信号⑥
output wire[15:0] app_wdf_mask , //ddr3的掩码⑦
input wire [31 : 0] rd_addr , //输入到读fifo的地址
input wire [127 : 0] ddr3_out_data , //ddr3输出的数据最终输入到读数据的fifo
output wire [8 : 0] rdfifo_cnt , //fifo缓存的数据计数
output wire [127 : 0] rdfifo_data , //fifo最终输出的数据
input wire rd_fifo_en_data , //fifo最终输出的数据的使能信号
input wire rd_fifo_en
);
reg wdfl_detect ; //是wdfL
reg rdfl_detect ; //读数据监测
reg write_cycle ; //写循环
reg read_cycle ; //读循环
reg [3:0] ddr3_burst_cnt ; //写完成16计数
reg [3:0] rdddr3_burst_cnt; //读完成16计数
wire [8 : 0] wdfl_rd_cnt ;
wire [8 : 0] rdf1_rd_cnt ;
wire [3:0] rc_data ;
wire [3:0] rd_data ;
wire [27:0] WR_addr ;
wire [27:0] RD_addr ;
wire rdflcmd_rd_en ;
reg [2:0] state ;
parameter IDLE = 3'b001 ;
parameter WRITE = 3'b010 ;
parameter READ = 3'b100 ;
assign app_wdf_mask = 16'd0;
assign app_wdf_wren = app_wdf_rdy&write_cycle&app_rdy; //写数据使能
assign app_wdf_end = app_wdf_wren;
assign rdflcmd_rd_en = read_cycle&app_rdy;
assign ddr3_app_en = (write_cycle)?app_wdf_wren:rdflcmd_rd_en; //ddr3的使能信号
assign app_cmd = (state==READ)?3'b001:3'd0;
assign out_addr = (state==WRITE)?WR_addr:RD_addr;
always@(posedge ui_clk)
if(ui_clk_sync_rst)
state<=IDLE;
else case (state)
IDLE: if(calib_complete==1)
state<=WRITE;
WRITE: if((wdfl_rd_cnt<14&&wdfl_detect==1)||
(ddr3_burst_cnt==15&&app_wdf_wren==1))
state<=READ;
READ: if((rdf1_rd_cnt<14&&rdfl_detect==1)||
(rdddr3_burst_cnt==15&&rdflcmd_rd_en==1&&app_rdy==1))
state<=WRITE;
default: state<=IDLE;
endcase
always@(posedge ui_clk)
if(ui_clk_sync_rst)
wdfl_detect<=1'b0;
else if((calib_complete==1&&state==IDLE )||((rdf1_rd_cnt<14&&rdfl_detect==1)||
(rdddr3_burst_cnt==15&&rdflcmd_rd_en==1&&app_rdy==1)))
wdfl_detect<=1'b1;
else wdfl_detect<=1'b0;
always@(posedge ui_clk)
if(ui_clk_sync_rst)
rdfl_detect<='d0;
else if ((wdfl_rd_cnt<14&&wdfl_detect==1)||
(ddr3_burst_cnt==15&&app_wdf_wren==1))
rdfl_detect<=1'b1;
else rdfl_detect<='d0;
always@(posedge ui_clk)
if(ui_clk_sync_rst)
write_cycle<=1'b0;
else if(app_wdf_wren == 1&& ddr3_burst_cnt==15) //
write_cycle<=1'b0;
else if(wdfl_detect==1'b1&&wdfl_rd_cnt>=14)
write_cycle<=1'b1;
always@(posedge ui_clk)
if(ui_clk_sync_rst)
ddr3_burst_cnt<='d0;
else if(ddr3_burst_cnt==15 && write_cycle == 1)
ddr3_burst_cnt<='d0;
else if(app_wdf_wren==1)
ddr3_burst_cnt<=ddr3_burst_cnt+1'b1;
always@(posedge ui_clk)
if(ui_clk_sync_rst)
read_cycle<=1'b0;
else if(rdflcmd_rd_en == 1&& rdddr3_burst_cnt==15) //
read_cycle<=1'b0;
else if(rdfl_detect==1'b1&&rdf1_rd_cnt>=14)
read_cycle<=1'b1;
always@(posedge ui_clk)
if(ui_clk_sync_rst)
rdddr3_burst_cnt<='d0;
else if(rdddr3_burst_cnt==15&&read_cycle==1&&app_rdy==1)
rdddr3_burst_cnt<='d0;
else if(read_cycle==1&&app_rdy==1)
rdddr3_burst_cnt<=rdddr3_burst_cnt+1'b1;
fifo_generator_512 fifo_generator_512_inst (
.wr_clk(ui_clk), // input wire wr_clk
.rd_clk(ui_clk), // input wire rd_clk
.din(data_in), // input wire [127 : 0] din
.wr_en(wf_wren), // input wire wr_en
.rd_en(app_wdf_wren), // input wire rd_en 展示忘记了
.dout(out_data), // output wire [127 : 0] dout
.full(), // output wire full
.empty(), // output wire empty
.rd_data_count(wdfl_rd_cnt) // output wire [8 : 0] rd_data_count
);
fifo_cmd_256_32 fifo_cmd_256_32_inst (
.wr_clk(ui_clk), // input wire wr_clk
.rd_clk(ui_clk), // input wire rd_clk
.din(data_addr), // input wire [31 : 0] din
.wr_en(wf_wren), // input wire wr_en
.rd_en(app_wdf_wren), // input wire rd_en
.dout({rc_data,WR_addr}), // output wire [31 : 0] dout
.full(), // output wire full
.empty() // output wire empty
);
rd_data_128_512 rd_data_128_512_inst (
.wr_clk(ui_clk), // input wire wr_clk
.rd_clk(ui_clk), // input wire rd_clk
.din(ddr3_out_data), // input wire [127 : 0]
.wr_en(rd_data_valid), // input wire wr_en
.rd_en(rd_fifo_en_data), // input wire rd_en
.dout(rdfifo_data), // output wire [127 : 0] dout
.full(), // output wire full
.empty(), // output wire empty
.rd_data_count(rdfifo_cnt) // output wire [8 : 0] rdfifo_cnt
);
rcmd_fifo_32_512 rcmd_fifo_32_512_inst (
.wr_clk(ui_clk ), // input wire wr_clk
.rd_clk(ui_clk ), // input wire rd_clk
.din (rd_addr ), // input wire [31 : 0] rd_addr
.wr_en(rd_fifo_en ), // input wire wr_en
.rd_en(rdflcmd_rd_en), // input wire rd_en
.dout({rd_data,RD_addr}), // output wire [31 : 0] dout
.full(), // output wire full
.empty(), // output wire empty
.rd_data_count(rdf1_rd_cnt) // output wire [8 : 0] rdf1_rd_cnt
);
endmodule
3.仿真结果
最终数据以当行计数拉高的时候,显示四组0-255。
4.中秋节快乐