在线咨询
eetop公众号 创芯大讲堂 创芯人才网
切换到宽版

EETOP 创芯网论坛 (原名:电子顶级开发网)

手机号码,快捷登录

手机号码,快捷登录

找回密码

  登录   注册  

快捷导航
搜帖子
查看: 2119|回复: 0

[求助] 反面教材!!!!知道错误在哪!不知咋改!!!!

[复制链接]
发表于 2014-1-10 10:23:23 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册

x
/*************************************************************

说明:这里的数据位宽需要根据ddr2中的参数设置和fifo的例化得到
**************************************************************/


module data_flow(  
      input
sys_rst_n,

      input
phy_clk,       //ddr2时钟 双fifo读出时钟 和upp fifo写入时钟
      //双fifo操作接口
      input
fifo1_full,    //fifo的空满信号
      input
fifo2_full,
      input
fifo1_empty,
      input
fifo2_empty,
      output reg
rd_req1 = 1'b0,   //fifo的读请求
      output reg
rd_req2 = 1'b0,
      input[1:0] fifo_status,    //双fifo的当前状态指示
      input[63:0] q_fifo1,  //fifo的数据输出 需要与wr_burst_data对接
      input[63:0] q_fifo2,

      //ddr2侧的接口
      input  burst_finish,       //突发读写完成信号 由读写的各自完成信号相与而来
      input  wr_burst_data_req,  //写数据有效标志 说明已经进入了写操作中
      input  rd_burst_data_valid,//读数据有效 说明不冲突 进入了读操作
      output reg wr_burst_req = 1'b0,      //读写请求操作
      output reg rd_burst_req = 1'b0,
      output reg[63:0] wr_burst_data = 64'd0, //ddr2写入的数据64位  与ddr2模块对接
      input [63:0] rd_burst_data,  //从ddr2中读出数据 给upp的fifo 与data_in对接

/********************************************************/
      output reg[23:0] wr_burst_addr = 24'd0, //对ddr2的读写地址进行操作
      output reg[23:0] rd_burst_addr = 24'd0, //这里不赋给初始值得话将不能对其操作
      output reg[9:0]  wr_burst_len = 10'd0,  //对ddr2的读写数据长度进行操作
      output reg[9:0]  rd_burst_len = 10'd0,
      input  local_init_done,          //ddr2初始化完成信号

      //定时器信号
      output reg start_timer = 1'B0,         //当ddr2中的数据达到一定量时 启动定时器
      input start_upp,             //输入1  定时器完成10ms定时 启动upp传输

     //upp的fifo写请求信号
      output wire wr_req,              //upp中的fifo 写请求
      output [63:0] data_in
                 );


  
//双fifo中状态定义
parameter fifo_idle= 2'd0,
          fifo_write1  = 2'd1,

fifo_wr1_rd2 = 2'd2,

fifo_rd1_wr2 = 2'd3;
  

  
parameter  DDR2_IDLE = 3'd0,
           READ_DDR2 = 3'd1,
           FIFO1_WRITE_DDR2  = 3'd2,

  FIFO2_WRITE_DDR2  = 3'd3;

reg[2:0] state;        //当前状态 寄存器
reg[2:0] next_state;   //下一个状态寄存器


/*************************************************************
   驱动源:phy_clk(DDR2控制器提供给用户的读写同步时钟)

描述:ddr2控制器初始化完成后才进行其他操作,状态才能转移

     初始化未完成,或是复位有效,则进入空闲状态

  每个时钟周期都会将下一个状态转给当前状态
**************************************************************/

always@(posedge phy_clk)

begin
   if(!local_init_done || !sys_rst_n || (fifo_status == fifo_idle) || (fifo_status == fifo_write1) )

  state <= DDR2_IDLE;

else


     state <= next_state;  //下一个状态赋给当前状态

end

reg hold_readddr_req = 1'b0;

/**************************************************************
  读ddr2挂起操作  在写的时候如有读ddr2命令则  读等待 请求被挂起
*******************************************************************/
always@(posedge phy_clk)
   begin

   if( state == READ_DDR2 )

  hold_readddr_req <= 0;

   else if( start_upp )

  hold_readddr_req <= 1;  //读ddr请求挂起,知道进入读状态才清空

else

  hold_readddr_req <= hold_readddr_req;

end


/*************************************************************
   驱动源:状态改变,根据always中的输入变量来改变

描述:  一旦此模块中的输入变量改变便被执行一次

语法说明:always@(*)敏感变量由综合器根据always里面的输入变量自动添加,不用自己考虑

         如果没有@,那就是不会满足特定条件才执行,而是执行完一次后立马执行下一次,一直重复执行

如果写ddr条件满足则优先执行写ddr 如在写时读ddr有效则读请求挂起 等待读完
**************************************************************/

always@(*)

begin


case(state)         //初始化完成后由空闲状态转到读状态


DDR2_IDLE:  //若是写fifo的时钟太低的话,ddr2已经读完fifo 但是full信号还没消失 这存在bug


   begin  //当在空闲时 如有读状态且fifo为满时转到读fifo写ddr2状态


   if( (fifo_status == fifo_rd1_wr2) && fifo1_full )   //监控双fifo那边的状态


   begin


// rd_req1 = 1'b1;         //读请求立即为1,一旦上升沿来到便出来一个数据


        next_state = FIFO1_WRITE_DDR2;


end


   else if( (fifo_status == fifo_wr1_rd2) && fifo2_full )


   begin


  rd_req2 = 1'b1;


     next_state = FIFO2_WRITE_DDR2;      


end


else if( hold_readddr_req )          //start_upp 前5ms为0,后5ms为1


   next_state = READ_DDR2;   //每隔10ms时,状态换为读


   else


   next_state = next_state;


end


  
FIFO1_WRITE_DDR2:

      
   begin


  if( burst_finish & fifo1_empty )  //写完64个数据同时fifo1读空有效


     begin


     next_state = DDR2_IDLE;    //写完跳到空闲,同时读1停止


     rd_req1 = 1'b0;
  


     end


  else if( !wr_burst_data_req )    //当local_ready 无效是停止读fifo


     rd_req1 = 1'b0;//读1已经被置1 下个phy_clk发现ddr没准备好 则又关闭 正好出来一个数据放到ddr总线上


  else


     begin


     rd_req1 = 1'b1;


        next_state = FIFO1_WRITE_DDR2;   //否则状态保持不变


  end


   end


FIFO2_WRITE_DDR2:


   begin


   if( burst_finish & fifo2_empty )  //写完64个数据同时fifo1读空有效


     begin


     next_state = DDR2_IDLE;    //写完跳到空闲,同时读2停止


     rd_req2 = 1'b0;   
  


     end


else if( !wr_burst_data_req )    //当local_ready 无效是停止读fifo


     rd_req2 = 1'b0;


   else


  begin


     rd_req2 = 1'b1;


        next_state = FIFO2_WRITE_DDR2;   //否则状态保持不变


  end


end


READ_DDR2:

           begin
  


if(burst_finish)


  begin


next_state = DDR2_IDLE;   //读ddr2到fifo中 128个地址后 转为空闲


  end


else


next_state = READ_DDR2;


  end


default:  


next_state = DDR2_IDLE;


endcase

end

/*************************************************************
   驱动源:phy_clk

描述:对地址进行操作,每读完一次地址加128,写完一次地址加64,乒乓操作完成3次后启动定时器,不关闭

     ddr2相当于一个缓冲,始终对地址0-768操作
**************************************************************/

always@( posedge phy_clk )  
  begin
  
if( wr_burst_addr >= 24'd768 )

  wr_burst_addr <= 24'd0;                   //写地址清零,如此循环

    else if( state == FIFO1_WRITE_DDR2 && next_state == DDR2_IDLE )     

  wr_burst_addr <= wr_burst_addr + 24'd64;      

else if( state == FIFO2_WRITE_DDR2 && next_state == DDR2_IDLE )   

  wr_burst_addr <= wr_burst_addr + 24'd64;  

else

  wr_burst_addr <= wr_burst_addr;
   end

always@( posedge phy_clk )
    if( wr_burst_addr >= 24'd384 )          //当存完384个内存单元后启动定时器,一旦启动就不停,除了复位时

  start_timer <= 1'b1;   

else

     start_timer  <= start_timer ;

  
always@( posedge phy_clk )
   begin

   if( rd_burst_addr >= 24'd768 )

  rd_burst_addr <= 24'd0;   
//读地址清零,如此循环

else if( state == READ_DDR2 && next_state == DDR2_IDLE )

      rd_burst_addr <= rd_burst_addr + 24'd128;

else

   rd_burst_addr <= rd_burst_addr;


end

/*************************************************************
   驱动源:phy_clk(DDR2控制器提供的读写同步时钟)

描述:提供写请求信号   wr_burst_req
        写数据长度       wr_burst_len

     同时准备接收写数据准备好有效位 wr_burst_data_req

     ddr2控制器的写请求要操作两次,但是在顶层不用管  

  写之前给个写请求信号就好

说明:有个bug,如果wr_burst_data_req不能立即为1,也就是读写有冲突的时候

      数据会丢失?????????
**************************************************************/

always@(posedge phy_clk)

begin

if((next_state == FIFO1_WRITE_DDR2 && state != FIFO1_WRITE_DDR2) || (next_state == FIFO2_WRITE_DDR2 && state != FIFO2_WRITE_DDR2)) //由非读状态马上要转到读状态时的处理

begin

wr_burst_req <= 1'b1;     //突发写请求有效  写请求置1

wr_burst_len <= 10'd64;  //突发写数据长度128

end

else if((wr_burst_data_req &&  state == FIFO1_WRITE_DDR2) || (wr_burst_data_req &&  state == FIFO2_WRITE_DDR2))   //上边的请求信号有效后下一个时钟周期  写请求有效 说明没有读写冲突 进入写状态 开始写

begin

wr_burst_req <= 1'b0;     //写数据请求置1后  写请求清零开始写数据

wr_burst_len <= 10'd64;

end

else                             //否则的话保持之前状态

begin

   wr_burst_req <= wr_burst_req;

wr_burst_len <= 10'd64;


end

end
/**************************************************************************
   fifo的数值赋给ddr2,数据流不间断,一旦读有效便将数据接口放到ddr2上
**************************************************************************/

always@(posedge phy_clk)
   begin

   if( rd_req1 )

  wr_burst_data <= q_fifo1;

else if( rd_req2 )

  wr_burst_data <= q_fifo2;

else

  wr_burst_data <= 64'd0;

end



/*************************************************************
   驱动源:phy_clk(DDR2控制器提供的读写同步时钟)

描述:提供读请求信号rd_burst_req

     即将读取的数据长度rd_burst_len  

  同时准备接收读数据准备好有效位 rd_burst_data_valid  

  burst_finish与rd_burst_data_valid同时变得无效,读最后一个数据

  的同时burst_finish开始有效
**************************************************************/

always@(posedge phy_clk)

begin

if(next_state == READ_DDR2 && state != READ_DDR2)//由非读状态装换为读状态

begin

rd_burst_req <= 1'b1;      //读请求置一 激活ddr 过几个周期后 读数据有效

rd_burst_len <= 10'd128;   //读数据长度

end

else if(rd_burst_data_valid )    //读数据有效的时候将读请求清零  

begin

rd_burst_req <= 1'b0;

rd_burst_len <= 10'd128;

end

else                             //若是读数据无效则保持状态

begin

rd_burst_req <= rd_burst_req;

rd_burst_len <= 10'd128;

end

end
assign wr_req = rd_burst_data_valid;
assign data_in = wr_req ? rd_burst_data : 16'd0;


endmodule



Warning (10240): Verilog HDL Always Construct warning at data_flow.v(97): inferring latch(es) for variable "rd_req1", which holds its previous value in one or more paths through the always construct
Warning (10240): Verilog HDL Always Construct warning at data_flow.v(97): inferring latch(es) for variable "next_state", which holds its previous value in one or more paths through the always construct
Warning (10240): Verilog HDL Always Construct warning at data_flow.v(97): inferring latch(es) for variable "rd_req2", which holds its previous value in one or more paths through the always construct

这个是警告!!!
我感觉是next_state被锁住了,功能仿真没问题,实际调试有问题,rd_req不变!!!! 求大神指导下,小弟刚学这个不就!
代码是控制乒乓操作的fifo向ddr2中写数据 fifo一旦写满 就向ddr2中写数据
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

站长推荐 上一条 /2 下一条


小黑屋| 手机版| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-11-25 22:26 , Processed in 0.022598 second(s), 10 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
快速回复 返回顶部 返回列表