标签:output 不一致 line str 过程 inf ssi 技术 parameter
一、项目目的
用户端的写、读控制主要功能需要按照FIFO IP核能够接受的逻辑,编写对应的逻辑功能,因此该控制器的输出应该按照FIFO IP核的时序进行。
1、用户写控制器实现
下面先对写控制器进行分析。FIFO IP核预留的写端口主要包括两个FIFO接口,其中一个可以缓存数据,另外一个可以缓存命令。为了保证数据在写入DDR3 SDRAM中时,不出线数据量和突发长度不一致的情况,我们可以先将需要写入的数据存到数据FIFO中,在对命令FIFO发送写命令相关的信息,这样就可以保证FIFO IP核接受搭配命令之后,有正确的突发长度的数据可以传输。
2、用户写控制器框架
由上图可以看到,需要写入的数据wr_data由wr_en标志有效,我们需要在该模块实现由输入的wr_data和wr_en产生FIFO IP核写端口所需要的信息,并最终有FIFO IP核写数据端口的FIFO标志产生用户端写完成信号。
3、 该模块的各个变量说明
4、用户端写控制的时序图
由上图可以看到,我们根据输入进来的数据的数量可以确定突发的长度,当输入的数据结束时,产生命令FIFO的写使能等端口信息。当FIFO IP核在接受到命令FIFO的命令后,会将数据FIFO取出写入到DDR3 SDRAM中,我们可以根据FIFO的空标志确定是否完成该过程,当出现数据FIFO的空标志上升沿,则认为所有突发的空标志均可以写入到DDR3 SDRAM中,此时我们可以产生一个user_wr_end信号告知外部模块本次突发写结束。
地址的计算:DDR3是16位的数据地址,每个地址递增1代表着写入16位的数据,呢么128位数据时8个16位的DDR存储空间。
代码:
`timescale 1ns / 1ps //************************************************************************** // *** 名称 : user_wr_ctrl.v // *** 作者 : tedyma // *** 博客 : https://www.cnblogs.com/tedymafpga/ // *** 日期 : 2019-08-10 // *** 描述 : 用户写逻辑,只需要控制少量的接口来控制更多的命令 //************************************************************************** module user_wr_ctrl //========================< 端口 >========================================== ( input wire sclk , input wire rst , input wire wr_en , input wire [127:0] wr_data , output wire p2_wr_en , output wire [127:0] p2_wr_data , output wire [15:0] p2_wr_mask , output wire p2_cmd_en , output wire [6:0] p2_cmd_bl , output wire [2:0] p2_cmd_instr , output wire [27:0] p2_cmd_addr , output wire user_wr_end , input wire p2_wr_empty ); //-------------------------------------------------------------------------- //-- 参数化 //-------------------------------------------------------------------------- parameter BURST_LEN = 64 ; //突发长度 parameter START_ADDR = 0 ; //开始地址 parameter STOP_ADDR = 785920 ; //1024*768-512(我们这里设置分辨率为1024*768)512=64*128/16 parameter ADDR_ADD = 64*128/16 ; //每次需要增加的地址 //-------------------------------------------------------------------------- //-- 信号定义 //-------------------------------------------------------------------------- reg wr_en_r ; reg [127:0] wr_data_r ; reg p2_cmd_en_r ; reg [27:0] p2_cmd_addr_r ; reg [6:0] data_cnt ; reg p2_wr_empty_r0,p2_wr_empty_r1,p2_wr_empty_r2; reg user_wr_end_r ; //-------------------------------------------------------------------------- //-- 输出的接口信号 //-------------------------------------------------------------------------- assign p2_wr_data = wr_data_r ; assign p2_wr_en = wr_en_r ; assign p2_cmd_en = p2_cmd_en_r ; assign p2_wr_mask = 0 ; assign p2_cmd_bl = BURST_LEN ; assign p2_cmd_instr = 3‘d0 ; assign p2_cmd_addr = p2_cmd_addr_r ; assign user_wr_end = user_wr_end_r ; //-------------------------------------------------------------------------- //-- 数据和写命令 //-------------------------------------------------------------------------- always @(posedge sclk) begin if(rst) begin wr_en_r <= 1‘b0; wr_data_r <= ‘d0; end else begin wr_en_r <= wr_en; wr_data_r <= wr_data; end end //-------------------------------------------------------------------------- //-- wr_cmd_en命令 //-------------------------------------------------------------------------- always @(posedge sclk) begin if(rst) begin p2_cmd_en_r <= 1‘b0; end else if(wr_en == 1‘b0 && wr_en_r == 1‘b1)begin p2_cmd_en_r <= 1‘b1; end else begin p2_cmd_en_r <= 1‘b0; end end //-------------------------------------------------------------------------- //-- 地址 //-------------------------------------------------------------------------- always @(posedge sclk) begin if(rst) begin p2_cmd_addr_r <= START_ADDR; end else if(p2_cmd_addr_r == STOP_ADDR && p2_cmd_en_r == 1‘b1)begin p2_cmd_addr_r <= START_ADDR; end else if(p2_cmd_en_r == 1‘b1)begin p2_cmd_addr_r <= p2_cmd_addr_r + ADDR_ADD; end end //-------------------------------------------------------------------------- //-- 对输入的FIFO空信号打两拍(在top顶层模块,也需要打两拍,作用不一样) //-------------------------------------------------------------------------- always @(posedge sclk)begin p2_wr_empty_r0 <= p2_wr_empty; p2_wr_empty_r1 <= p2_wr_empty_r0; p2_wr_empty_r2 <= p2_wr_empty_r1; end //-------------------------------------------------------------------------- //-- 用户结束信号 //-------------------------------------------------------------------------- always @(posedge sclk) begin if(rst) begin user_wr_end_r <= 1‘b0; end else if(p2_wr_empty_r1 == 1‘b1 && p2_wr_empty_r2 == 1‘b0)begin user_wr_end_r <= 1‘b1; end else begin user_wr_end_r <= 1‘b0; end end endmodule
二、用户端的读实现
1、用户端的读控制器介绍
FIFO IP核控制器读端口预留了两个FIFO接口,其中一个为命令FIFO,另一个为数据FIFO,我们需要将相应的信息发送到命令FIFO中,FIFO IP核检测到命令FIFO中有命令后,会根据命令的信息发送对应突发长度的数据到数据FIFO,我们检测到数据FIFO内存够了所需要的数据量,则可以将对应的数据读出即可。
2、用户端的读控制器框架
用户端的读模块需要一个rd_start作为输入,在rd_start信号有效后,该模块会输出命令FIFO所需的p1_cmd_en、p1_cmd_bl、p1_cmd_instr和p1_cmd_addr信号,之后FIFO IP核控制器会根据该信息发送对应突发长度的数据到数据FIFO,我们可以根据p1_rd_count的值判断数据FIFO的数据量,当数据FIFO内的数据量与所需要的数据量一致时,我们可以产生p1_rd_en信号到数据FIFO,将数据FIFO内的数据读出。
3、端口变量说明
4、用户端读控制的时序图
由图4可以看出,在rd_start有效时,会产生读端口命令FIFO所需要的信号,这些信号会在p1_cmd_en有效的情况下被写入到读端的命令FIFO,之后DDR3 IP核控制器会将所需要的数据存入到读端的数据FIFO,我们根据p1_rd_count的值可以判断数据FIFO内的数据量是否满足本次突发,然后产生p1_rd_en读出已经满足本次突发的数据,当读完最后一个数据后,可以产生user_rd_end信号。
标签:output 不一致 line str 过程 inf ssi 技术 parameter
原文地址:https://www.cnblogs.com/tedymafpga/p/11813303.html