注册网站页面跳转错误,php网站超市,介绍自己做的电影网站,网站维护与更新内容:使用DDR3 IP核#xff0c;向DDR3写入数据#xff0c;然后再读出数据#xff0c;通过串口打印。
设备#xff1a;ZYNQ 7010 xc7z010clg-400-1。软件VIVADO 2018.3
#xff08;1#xff09;工程模块#xff1a;一个写FIFO#xff0c;一个读FIFO。一个ZYNQ IP核向DDR3写入数据然后再读出数据通过串口打印。
设备ZYNQ 7010 xc7z010clg-400-1。软件VIVADO 2018.3
1工程模块一个写FIFO一个读FIFO。一个ZYNQ IP核DDR3在ZYNQ IP核内勾选。一个AXI4通信接口转换模块。
2工程的运行逻辑简介
AXI4的接口是64位也就是两个FIFO读FIFO、写FIFO与ZYNQ 的接口位宽是64位。我们进入和出来DDR3的数据都是64位的。
整个工程分为两个流程 突发写DDR3设置一次突发写的长度是16个64位的数据 顶层文件内持续向写FIFO写入数据写FIFO的读计数会累积增加。每次写入FIFO的数据位宽是16位当我们写入64个16位的数据读计数值rd_cnt就会等于16代表16个64位的数据排列在FIFO里。 当rd_cnt 16 就代表满足一次突发写DDR3的设置长度“16”那就会自动执行一次DDR3的突发写数据就进入到DDR3里了每次向DDR3里写1个64位数重复了16次。 突发读DDR3设置一次突发读的长度是16个64位的数据 我们要把之前写到DDR3里的数据读出来放到读FIFO里。DDR3的读操作受限于读FIFO的写计数值wr_cnt。wr_cnt在读FIFO被写入数据后会自动增加增加1就代表DDR3给FIFO写了1个64位的数据。在读FIFO复位后wr_cnt会清零如果wr_cnt小于等于我们设定的16DDR就自动往读FIFO搬运数值一直到wr_cnt等于16了DDR3就不会往FIFO里搬运数据。当wr_cnt等于16就等于DDR3给了读FIFO16个64位的数据代表一次突发读完成
关于两个过程的一些问题 红色箭头代表写流程绿色箭头代表读流程 其中有很多的问题比如时钟信号线等等。看看我们怎么代码实现对DDR3的数据写入和读取吧。
**代码块一**给写FIFO写入数据这些数据会自动存入到DDR3中
/***********************方式2* 直接使能计数****************************/
reg [15:0] dat2;
wire wrfifo_data_en dat2 1024; //代表输入1024个16位数 rd 256 *64always(posedge loc_clk100m or posedge cnt_en_reg2)beginif(cnt_en_reg2)dat2 16d0;else if(!wrfifo_data_en !cnt_en_reg2)dat2 dat2 1b1;elsedat2 dat2;endassign wrfifo_clr reset;assign wrfifo_wren !wrfifo_data_en !cnt_en_reg2; assign wrfifo_din dat2;assign wrfifo_wren 代表允许写FIFO写入数据的使能信号 assign wrfifo_din 代表给写FIFO写入的数据在使能信号为1的情况下有效
**代码块二**读FIFO的读出数据。DDR3会自动把数据给读FIFO我们要把读FIFO的数据读出
/***********************方式1* 标志位cnt读计数****************************/
wire rdfifo_empty;
wire rdfifo_rd_rst_busy;
wire rd_en;
wire rdfifo_en_reg2;
reg [19:0] rdfifo_en_reg;
reg rd_clr;
assign rdfifo_en_reg2 rdfifo_en_reg[19];
// //延迟20个时钟周期always(posedge loc_clk100m or negedge wrfifo_data_en)beginif(!wrfifo_data_en)rdfifo_en_reg {20{1b1}};elserdfifo_en_reg rdfifo_en_reg 1;endassign rd_en rdfifo_empty | rdfifo_rd_rst_busy;
reg [15:0] rd_dat;
reg rd_send_en;
wire rdfifo_data_en rd_dat 1024; //代表输入1024个16位数 reg [31:0] rd_cnt;always (posedge loc_clk100m or posedge rdfifo_en_reg2)if(rdfifo_en_reg2)beginrd_dat 0;rd_cnt 0;rd_send_en 0;endelse if(!rdfifo_data_en !rd_en)beginif(rd_cnt 32d9_999_999) begin// d199_999rd_dat rd_dat 1b1;rd_send_en 1;rd_cnt 0;endelse beginrd_cnt rd_cnt 1b1;rd_dat rd_dat;rd_send_en 0;endendelse beginrd_cnt 0 ;rd_send_en 0;rd_dat rd_dat;endreg rd_send_en_reg;always (posedge loc_clk100m or posedge rdfifo_en_reg2)if(rdfifo_en_reg2)rd_send_en_reg 0;else if(rd_send_en)rd_send_en_reg 1;else rd_send_en_reg 0;assign rdfifo_rden rd_send_en;assign rdfifo_clr reset | rd_clr;这里的rd_send_en 是读FIFO的读使能信号每隔“d9_999_999”也就是9_999_999 1 10_000_000 * 10ns 100 ms读一次读FIFO的数据因为读使能和读数据有一个周期的延迟因此rd_send_en_reg 出现了他被用来给uart模块块用来发送读FIFO的数据来验证我们整个流程是否正确。
**代码块三**串口打印 uart tx /
uart_byte_tx uart_byte_tx(.clk(loc_clk100m),.reset(reset),.data_byte(rdfifo_dout),.send_en(rd_send_en_reg),.baud_set(3d0),.uart_tx(uart_tx),.tx_done( ),.uart_state()); rdfifo_dout就是读FIFO的数据口了因为rdfifo_dout是16位的我们这样使用会直接输出低八位的数据。
在代码块一我们看到
/***********************方式2* 直接使能计数****************************/
reg [15:0] dat2;
wire wrfifo_data_en dat2 1024; //代表输入1024个16位数 rd 256 *64always(posedge loc_clk100m or posedge cnt_en_reg2)beginif(cnt_en_reg2)dat2 16d0;else if(!wrfifo_data_en !cnt_en_reg2)dat2 dat2 1b1;elsedat2 dat2;endassign wrfifo_clr reset;assign wrfifo_wren !wrfifo_data_en !cnt_en_reg2; assign wrfifo_din dat2;assign wrfifo_din dat2; dat2作为一直给FIFO也就是一直给DDR3的数据是从0~1024开始变化的。所以串口打印的数据只有八位8h00到8hFF一共256个数据。那么根据1024个数据挨个打印出来在低八位上显示的效果就是4次循环打印输出00到FF
到这里整个流程就结束了由于这个DDR3的工程涉及到PS与PL侧的资源导致会有很多出BUG的地方。因此整个工程代码难度比较高我还是建议使用一个基础版的工程文件来学习整个DDR3的运行流程接下来我会上传我自己编写的基础版的代码供大家学习参考