|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?注册
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中写数据 |
|