/*************************************************************
说明:这里的数据位宽需要根据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;始终不能执行,郁闷啊!求大神指点!!!!!
|