MIG连载-----写模块(3)

写模块总体框图

在这里插入图片描述
写模块分别用命令fifo和数据fifo里面读取数据;
a7_wr_start :指示写开始信号
a7_wr_bl :用户接口突发传输的数据个数n,则传输的总bit数位128*n。
app_rdy,app_wdf_rdy :来自IP核分别表示IP和准备好接受数据和写数据准备好写入。
data_req :数据fifo读出数据响应信号,同数据fifo读使能信号
a7_wr_data_end :一次突发传输结束信号,详细见时序图

写时序图

在这里插入图片描述
1.wr_bl:用于将数据缓存起来,因为a7_wr_start有效一个时钟周期
2.app_addr :用于缓存初始地址,并且没读入一个数据之后地址+(UI用户数据总线位宽)/(DDR3数据总线位宽)
2.wr_flag :指示可以写数据,遇到a7_wr_start有效止之后一直拉高即可,wr_flag拉低条件同cnt拉低条件
3.app_wdf_rdy :基本一直处于拉高状态,很少有为0的情况
4.app_rdy :出现低电平的可能性还是很高的
5.cnt :写入数据的个数计数,归零条件是:cnt==BL && app_rdy && app_wdf_rdy && wr_flag
6.app_addr :首地址由a7_wr_addr_initi决定,之后每次+8会伴随写入一个128bit的数据
7.此时序图反映的是数据和命令在同一个时钟写入的情况,其它两种情况原理相同

在这里插入图片描述
假设计数器cnt清零的条件是cntBL,wr_flag 拉低的条件是cnt == BL,如果是上面的时序图,这样最后一个数据无法写入,因为app_rdy在cntBL期间为低,也就是最后一个数据始终无法写入,所以cnt清零的条件是cnt==BL && app_rdy && app_wdf_rdy && wr_flag。

读时序的三种模式:from ug586 page of 167
在这里插入图片描述
写有三种模式,第三种模式数据迟于命令出来,最大不能超过两个周期。

//*************************************************************************//
//写模块的总体思路是先从命令fifo里面取指令,然后根据指令对数据fifo进行操作
//后续会有仲裁器判断读写模块哪个先执行
//*************************************************************************//

module a7_wr_ctrl   #(
    parameter      BL_WIDTH   = 7,
    parameter      ADDR_WIDRH = 28,
    parameter      DATA_WIDTH = 128,
    
    )

(
    input   wire                     sclk             , //模块工作时钟,连接到ui_clk即可
    input   wire                     sys_rst          ,
    input   wire                     a7_wr_start      ,
    input   wire               [2:0] a7_wr_cmd        , //直传给MIG的读写指令
    input   wire      [BL_WIDTH-1:0] a7_wr_bl         , //命令fifo读出的突发长度   
    input   wire    [ADDR_WIDRH-1:0] a7_wr_init_addr  , 
    input   wire    [DATA_WIDTH-1:0] a7_wdf_data      ,  //数据fifo读出的数据     
    input   wire  [DATA_WIDTH/8-1:0] wr_mask          ,          
                                                      
    //                                                
    input   wire                     app_rdy          ,//指示向UI提供的数据是是否能被接收
    input   wire                     app_wdf_rdy      ,
                                                      
    //OUTPUT                                          
    output  wire                     app_en           ,    
    output  reg                      app_cmd          ,       
    output  wire                     app_wdf_wren     ,
    output  reg     [ADDR_WIDRH-1:0] app_addr         ,   
    output  wire    [DATA_WIDTH-1:0] app_wdf_data     ,
    output  wire                     app_wdf_end      , 
    output  wire  [DATA_WIDTH/8-1:0] app_wdf_mask     ,  
                                                      
    output  wire                     data_req         , //数据请求信号,也即数据fifo的读使能      
    output  reg                      wr_end             //所有数据传输完成指示
    );
 

//内部变量定义
reg    [BL_WIDTH-1:0]    wr_bl   ;//缓存输入进来的突发长度
reg                      wr_flag ;//指示写模块有效信号,在a7_wr_start之后有效
reg    [BL_WIDTH-1:0]    data_cnt;//输入数据个数计数器
reg             [6:0]	 cmd_cnt ;//命令计数器
 
always @(posedge sclk or negedge sys_rst)
begin
    if (sys_rst)
    begin
        wr_bl           <= {BL_WIDTH{1'b0}}  ;
        app_addr        <= {ADDR_WIDRH{1'b0}};
        cnt             <= {BL_WIDTH{1'b0}}  ;
        wr_end          <= 1'b0              ;
        data_cnt        <= {BL_WIDTH{1'b0}}   ;
    end 
    else if (a7_wr_start) //外部输入的写开始信号,一个周期有效
    begin
        wr_flag         <= 1'b1               ;
        wr_bl           <= a7_wr_bl           ;
        app_addr        <= a7_wr_init_addr    ;
    end 
    else if (data_req && data_cnt == wr_bl - 1'b1)  
    begin
        wr_flag         <= 1'b0               ;
        data_cnt        <= {BL_WIDTH{1'b0}}   ;
        app_addr        <= {ADDR_WIDRH{1'b0}} ;
    end
    else if (data_req)
    begin
        app_addr        <= app_addr + 4'd8    ;
        data_cnt        <= data_cnt + 1'b1    ;
    end 
end 

//app_cmd
assign app_amd      = a7_wr_cmd  ;
//app_wdf_mask
assign app_wdf_mask = wr_mask    ;
//app_wdf_data
assign app_wdf_data = a7_wdf_data;
//app_wdf_end
assign app_wdf_end  = app_en     ;
//app_en
assign app_en       = (app_rdy && app_wdf_rdy && wr_flag) ? 1b'1: 1'b0;
//data_req
assign data_req     = (app_rdy && app_wdf_rdy && app_en ) ? 1b'1: 1'b0;

assign app_wdf_wren = (app_rdy && app_wdf_rdy && wr_flag) ? 1b'1: 1'b0;



//cmd_cnt
always@(posedge	sclk)
if(rst_n==1'b0)
	cmd_cnt	<=	7'b0;
else if(cmd_cnt == wr_bl-1'b1 && app_rdy==1'b1)
	cmd_cnt	<=	7'b0;	
else if(app_en==1'b1 && app_rdy == 1'b1)
	cmd_cnt	<=	cmd_cnt+1'b1;

//wr_end
always@(posedge	sclk)
if(rst_n==1'b0)
	wr_end	<=	1'b0;
else if(cmd_cnt == wr_bl-1'b1 && app_rdy==1'b1)
	wr_end	<=	1'b1;
else
	wr_end	<=	1'b0;
    
endmodule 

控制逻辑的核心可以概括为:由app_en 和app_wdf_rdy控制,app_en控制是否可以写,app_wdf_rdy控制数据是否被接收。
补充知识DDR读写效率测试与分析 :http://xilinx.eetrend.com/d6-xilinx/article/2016-12/10776.html

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值