dma_ddr 的编写 通过mig控制ddr3
此外还有别的模块 本模块是 其中一个
`timescale 1ns/1ps
module dma_ctrl (
input wire ui_clk , //100MHZ 用户时钟
input wire ui_rst_n ,
//写fifo的写端口
input wire wf_wr_clk , //由数据产生模块的时钟来决定
input wire wf_wr_en ,
input wire [15:0] wf_wr_data ,
//读fifo的读端口
input wire rf_rd_clk , //由数据接收模块的时钟来决定
input wire rf_rd_en ,
output wire [15:0] rf_rd_data ,
output reg rf_rd_req , //数据请求接收信号
//----native接口------
//命令控制端口
output wire [27:0] app_addr ,
output reg [2:0] app_cmd ,
output reg app_en ,
input wire app_rdy ,
//写数据端口
output wire [127:0] app_wdf_data ,
output wire app_wdf_end ,
output reg app_wdf_wren ,
input wire app_wdf_rdy ,
output wire [15:0] app_wdf_mask ,
//读数据端口
input wire [127:0] app_rd_data ,
input wire app_rd_data_end ,
input wire app_rd_data_vali
);
parameter FIFO_BURST_LEN = 128; //16*8
parameter ADDR_AMX = 40000; //200*200
localparam IDLE = 3'b001; //空闲
localparam WR_DATA = 3'b010; //写
localparam RD_DATA = 3'b100; //读
reg [2:0] c_state,n_state;
wire [7 : 0] wf_data_count; //写fifo中还剩多少个数据(128bit)
wire [7 : 0] rf_data_count; //读fifo中还剩多少个数据(128bit)
reg [8:0] cnt_addr; //地址计数器 0 - 127
reg [31:0] cnt_wr_data; //写数据个数计数器
reg [27:0] app_wr_addr; //写地址线
reg [27:0] app_rd_addr; //读地址线
reg flag; //防止程序一上电就进入读数据状态,防止读空
wire wf_rd_en;
assign wf_rd_en = app_wdf_wren && app_wdf_rdy;
assign app_addr = (c_state == WR_DATA ) ? app_wr_addr : app_rd_addr;
assign app_wdf_end = app_wdf_wren;
assign app_wdf_mask = 0;
always @(posedge ui_clk ) begin
if(!ui_rst_n)
flag <= 0;
else if(app_wr_addr == ADDR_AMX >> 2)
flag <= 1;
else
flag <= flag;
end
//----三段式状态机。一 。将次态赋值给现态
always @(posedge ui_clk ) begin
if(!ui_rst_n)
c_state <= IDLE;
else
c_state <= n_state;
end
//----三段式状态机。二 。状态跳转描述
always @(*) begin
if(!ui_rst_n)
n_state = IDLE;
else begin
case (c_state)
IDLE : begin
if(wf_data_count > FIFO_BURST_LEN)
n_state = WR_DATA;
else if(rf_data_count < FIFO_BURST_LEN && flag)
n_state = RD_DATA;
else
n_state = IDLE;
end
WR_DATA : begin
if(app_en && app_rdy && cnt_addr == FIFO_BURST_LEN - 1)
n_state = IDLE;
else
n_state = WR_DATA;
end
RD_DATA : begin
if(app_en && app_rdy && cnt_addr == FIFO_BURST_LEN - 1)
n_state = IDLE;
else
n_state = RD_DATA;
end
default: n_state = IDLE;
endcase
end
end
//----三段式状态机。三 。对中间变量及输出结果赋值
always @(posedge ui_clk ) begin
if(!ui_rst_n)
rf_rd_req <= 0;
else if(rf_data_count > 100)
rf_rd_req <= 1;
else
rf_rd_req <= rf_rd_req;
end
always @(posedge ui_clk ) begin
if(!ui_rst_n)
app_wr_addr <= 0;
else if(c_state == WR_DATA && app_en && app_rdy)begin
if(app_wr_addr == ADDR_AMX - 8) //固定突发长度:8
app_wr_addr <= 0;
else
app_wr_addr <= app_wr_addr + 8;
end
else
app_wr_addr <= app_wr_addr;
end
always @(posedge ui_clk ) begin
if(!ui_rst_n)
app_rd_addr <= 0;
else if(c_state == RD_DATA && app_en && app_rdy)begin
if(app_rd_addr == ADDR_AMX - 8) //固定突发长度:8
app_rd_addr <= 0;
else
app_rd_addr <= app_rd_addr + 8;
end
else
app_rd_addr <= app_rd_addr;
end
always @(posedge ui_clk ) begin
if(!ui_rst_n)
app_cmd <= 0;
else if(c_state == WR_DATA)
app_cmd <= 0;
else if(c_state == RD_DATA)
app_cmd <= 1;
else
app_cmd <= app_cmd;
end
always @(posedge ui_clk ) begin
if(!ui_rst_n)
app_en <= 0;
else if(c_state == WR_DATA || c_state == RD_DATA)begin
if(cnt_addr == FIFO_BURST_LEN - 1 && app_rdy)
app_en <= 0;
else
app_en <= 1;
end
else
app_en <= 0;
end
always @(posedge ui_clk ) begin
if(!ui_rst_n)
app_wdf_wren <= 0;
else if(c_state == WR_DATA && app_wdf_rdy)begin
if(cnt_wr_data == FIFO_BURST_LEN - 1 )
app_wdf_wren <= 0;
else
app_wdf_wren <= 1;
end
else
app_wdf_wren <= 0;
end
always @(posedge ui_clk ) begin
if(!ui_rst_n)
cnt_wr_data <= 0;
else if(c_state == WR_DATA)begin
if(cnt_wr_data == FIFO_BURST_LEN - 1 && app_wdf_wren && app_wdf_rdy)
cnt_wr_data <= cnt_wr_data;
else if(app_wdf_wren && app_wdf_rdy)
cnt_wr_data <= cnt_wr_data + 1;
else
cnt_wr_data <= cnt_wr_data;
end
else
cnt_wr_data <= 0;
end
wf_fifo wf_fifo_u (
.wr_clk(wf_wr_clk), // input wire wr_clk
.rd_clk(ui_clk), // input wire rd_clk
.din(wf_wr_data), // input wire [15 : 0] din
.wr_en(wf_wr_en), // input wire wr_en
.rd_en(wf_rd_en), // input wire rd_en
.dout(app_wdf_data), // output wire [127 : 0] dout
// .full(full), // output wire full
// .empty(empty), // output wire empty
.rd_data_count(wf_data_count) // output wire [7 : 0] rd_data_count
);
rf_fifo rf_fifo_u (
.wr_clk(ui_clk), // input wire wr_clk
.rd_clk(rf_rd_clk), // input wire rd_clk
.din(app_rd_data), // input wire [127 : 0] din
.wr_en(app_rd_data_vali), // input wire wr_en
.rd_en(rf_rd_en), // input wire rd_en
.dout(rf_rd_data), // output wire [15 : 0] dout
// .full(full), // output wire full
// .empty(empty), // output wire empty
.wr_data_count(rf_data_count) // output wire [7 : 0] wr_data_count
);
endmodule