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

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

手机号码,快捷登录

手机号码,快捷登录

找回密码

  登录   注册  

快捷导航
搜帖子
查看: 3659|回复: 7

[求助] verilog代码奇怪的问题求助!!!!!!

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

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

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

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,   //fifo的读请求
      output reg
rd_req2,
      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,      //读写请求操作
      output reg rd_burst_req,
      output reg[63:0] wr_burst_data, //ddr2写入的数据64位  与ddr2模块对接
      input [63:0] rd_burst_data,  //从ddr2中读出数据 给upp的fifo 与data_in对接
      output reg[23:0] wr_burst_addr, //对ddr2的读写地址进行操作
      output reg[23:0] rd_burst_addr,
      output reg[9:0]  wr_burst_len,  //对ddr2的读写数据长度进行操作
      output reg[9:0]  rd_burst_len,
      input  local_init_done,     //ddr2初始化完成信号

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

     //upp的fifo写请求信号
      output reg wr_req,              //upp中的fifo 写请求
      output reg[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 = 2'd0,
           READ_DDR2 = 2'd1,
           FIFO1_WRITE_DDR2  = 2'd2,

  FIFO2_WRITE_DDR2  = 2'd3;

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


reg[15:0] wr_cnt = 16'd0;
reg[15:0] rd_cnt = 16'd0;


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

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

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

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

always@(posedge phy_clk)

begin

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


  state <= DDR2_IDLE;

end

else


   begin

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

end

end

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

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

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

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

always@(*)

begin

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

DDR2_IDLE:

   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( start_upp )          //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

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

   end


FIFO2_WRITE_DDR2:

   begin

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

     begin

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

     rd_req2 <= 1'b0;   
  

     end

   else

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

end



READ_DDR2:
           begin
  

if(burst_finish)

  begin


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

//wr_req <= 1'b0;
//同时写uppfifo请求无效

  end

else

next_state <= READ_DDR2;

  end

default:  

next_state <= DDR2_IDLE;

endcase
end

reg a;
wire fifo1_finish;
wire fifo2_finish;
assign fifo1_finish = ( state == FIFO1_WRITE_DDR2 && next_state == DDR2_IDLE );
assign fifo2_finish = ( state == FIFO2_WRITE_DDR2 && next_state == DDR2_IDLE );
/*************************************************************
   驱动源:phy_clk

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

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

always@( posedge phy_clk )
  begin
    if( fifo1_finish )   

   begin


  a <= 1'b1;


  wr_burst_addr <= wr_burst_addr + 24'd64;

      end        

else if( fifo2_finish )


    begin


   wr_burst_addr <= wr_burst_addr + 24'd64;


a <= 1'b0;


end


else if( wr_burst_addr >= 24'd768 )


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


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


start_timer <= 1'b1;                      //开启定时器 不开启后不关闭


else


wr_burst_addr <= wr_burst_addr;

  end


always@( posedge phy_clk )
   begin

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


      rd_burst_addr <= rd_burst_addr + 24'd128;


   else if( rd_burst_addr >= 24'd768 )


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


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,也就是读写有冲突的时候

      数据会丢失?????????有数据0出现  不过在这里应用不会存在冲突的情况
**************************************************************/

always@(posedge phy_clk)

begin

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

begin

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

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

wr_cnt <= 16'd0;          //写数据个数清零 准备写数据         

//rd_req1 <= 1'b1;


wr_burst_data <= q_fifo1;  //fifo与ddr2对接

end

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

   begin

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

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

wr_cnt <= 16'd0;          //写数据个数清零 准备写数据         

//rd_req2 <= 1'b1;

   wr_burst_data <= q_fifo2;

end

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

begin

   //rd_req1 <= 1'b1;

wr_burst_data <= q_fifo1;

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

wr_burst_len <= 10'd64;

wr_cnt <= wr_cnt + 16'd1;  //同时写计数器加1  用来作为写入数据的值 cnt=0被读入

end

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

begin

   //rd_req2 <= 1'b1;          //如果DDR2有应答的话,读请求有效 否则读请求无效

wr_burst_data <= q_fifo2;

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

wr_burst_len <= 10'd64;

wr_cnt <= wr_cnt + 16'd1;  //同时写计数器加1  用来作为写入数据的值 cnt=0被读入

end


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

begin

   //rd_req1 <= 1'b0;

//rd_req2 <= 1'b0;

wr_burst_data <= 64'd0;

wr_burst_req <= wr_burst_req;

wr_burst_len <= 10'd64;

wr_cnt <= wr_cnt;

end

end



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

描述:提供读请求信号rd_burst_req

     即将读取的数据长度rd_burst_len  

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

always@(posedge phy_clk)

begin

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

begin

rd_burst_req <= 1'b1;      //读请求置一

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

rd_cnt <= 16'd1;           //读数据寄存器

end

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

begin

   wr_req <= 1'b1;           //写fifo

rd_burst_req <= 1'b0;

rd_burst_len <= 10'd128;

rd_cnt <= rd_cnt + 16'd1;  //读数据计数器加1

data_in <= rd_burst_data;  //ddr2的数据写入fifo

end

else if(burst_finish)            //会多写一个数据 不过fifo有写保护 ?????

   wr_req <= 1'b0;  

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

begin

rd_burst_req <= rd_burst_req;

rd_burst_len <= 10'd128;

rd_cnt <= rd_cnt;

end

end

endmodule


问题描述:红色代码部分仿真的时候可以进入,a <= 1'b1;也执行了,但是 后边的加法 wr_burst_addr <= wr_burst_addr + 24'd64;始终不能执行,郁闷啊!求大神指点!!!!!

 楼主| 发表于 2014-1-3 14:27:35 | 显示全部楼层
这段代码是前端一个异步双fifo乒乓操作,并将数据放到DDR2中,需要的时候再从DDR2中读出,通过UPP传给dsp
发表于 2014-1-3 14:53:13 | 显示全部楼层
你这个ALWAYS块写的就很奇葩,显然没写过工程代码,你要是用VERDI的话很容易就能查出问题,先把你的ELSE分支顺序调整好,判断 wr_burst_addr 的分支放在做加法的前面!
 楼主| 发表于 2014-1-3 15:18:24 | 显示全部楼层
回复 3# caojun121123


   谢谢指点哈!我把代码调整为:
always@( posedge phy_clk )
  begin
  
if( wr_burst_addr >= 24'd768 )

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


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

start_timer <= 1'b1;  
         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

我只想将DDR2的0-768的地址空间 用来当缓存   改完后还是一样的    state == FIFO1_WRITE_DDR2 && next_state == DDR2_IDLE 这个条件的确是满足了   但是下边的代码没有执行
 楼主| 发表于 2014-1-3 15:37:33 | 显示全部楼层
回复 3# caojun121123


   问题解决了:reg[23:0] wr_burst_addr = 24'd0;                    reg[23:0] rd_burst_addr = 24'd0;  这里需要赋给初始值就可以了,谢谢指点!
发表于 2014-1-3 16:18:51 | 显示全部楼层
用时序逻辑产生fifo1_finish和fifo2_finish。
发表于 2015-6-17 11:53:02 | 显示全部楼层
学习了!
发表于 2015-7-6 22:13:08 | 显示全部楼层
学习学习
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

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


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

GMT+8, 2024-11-25 22:31 , Processed in 0.030726 second(s), 9 queries , Gzip On, Redis On.

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