📄 avalon_wr_dma_fifo.v
字号:
// ================================================================================
// (c) 2004 Altera Corporation. All rights reserved.
// Altera products are protected under numerous U.S. and foreign patents, maskwork
// rights, copyrights and other intellectual property laws.
//
// This reference design file, and your use thereof, is subject to and governed
// by the terms and conditions of the applicable Altera Reference Design License
// Agreement (either as signed by you, agreed by you upon download or as a
// "click-through" agreement upon installation andor found at www.altera.com).
// By using this reference design file, you indicate your acceptance of such terms
// and conditions between you and Altera Corporation. In the event that you do
// not agree with such terms and conditions, you may not use the reference design
// file and please promptly destroy any copies you have made.
//
// This reference design file is being provided on an "as-is" basis and as an
// accommodation and therefore all warranties, representations or guarantees of
// any kind (whether express, implied or statutory) including, without limitation,
// warranties of merchantability, non-infringement, or fitness for a particular
// purpose, are specifically disclaimed. By making this reference design file
// available, Altera expressly does not recommend, suggest or require that this
// reference design file be used in combination with any other product not
// provided by Altera.
// ================================================================================
// ================================================================================
// This module uses implements a FIFO plus Avalon DMA write master.
// ================================================================================
`timescale 1ns/1ns
module avalon_wr_dma_fifo
(
clk_f,
clk_av,
reset_n,
sof,
// FIFO write interface
wr,
wdata,
full,
eof_in,
// Control registers
wr_mcontrol,
m_enable_bit,
fb_done,
mfb_reg,
// Avalon DMA master
m_address,
m_write_n,
m_writedata,
m_waitrequest
);
parameter DEVICE = "Cyclone";
input clk_f;
input clk_av;
input reset_n;
input sof;
// FIFO write interface
input wr;
input [31:0] wdata;
output full;
input eof_in;
// Control registers
input wr_mcontrol;
input m_enable_bit;
output fb_done;
input [31:0] mfb_reg;
// Avalon DMA master
output [31:0] m_address;
output m_write_n;
output [31:0] m_writedata;
input m_waitrequest;
reg [3:0] master_state;
parameter idle = 4'b0000,
wr1 = 4'b1000,
wr2 = 4'b1001,
wr3 = 4'b1010,
write = 4'b1100,
wr_wait = 4'b0100;
//---------------------------------------------------------------------------
// Control registers
//---------------------------------------------------------------------------
reg [31:0] s_readdata;
reg [31:0] m_address;
reg [31:0] m_dataout;
wire [6:0] available;
reg [4:0] burst;
wire cycle_end;
reg fb_done;
reg wr_mcontrol_r;
always @(posedge clk_av or negedge reset_n)
if (~reset_n)
wr_mcontrol_r <= 1'b0;
else
wr_mcontrol_r <= wr_mcontrol;
reg enable;
// *** sof should be synchronised to local clock
// - is it long enough (1 clock at 27MHz) to be detected at all clock rates?
always @(posedge clk_av or negedge reset_n)
if (~reset_n)
enable <= 1'b0;
else if (~m_enable_bit)
enable <= 1'b0;
else if (sof & m_enable_bit)
enable <= 1'b1;
//---------------------------------------------------------------------------
// DMA Master
//
// When enabled, writes bursts of 8 from FIFO to Avalon.
//---------------------------------------------------------------------------
reg eof_in_r;
wire eof;
reg eof_in_sync1;
reg eof_in_sync2;
reg final_burst;
reg eof_sync1;
reg eof_sync2;
always @(posedge clk_f or negedge reset_n)
if (~reset_n)
begin
eof_sync1 <= 1'b0;
eof_sync2 <= 1'b0;
end
else
begin
eof_sync1 <= eof;
eof_sync2 <= eof_sync1;
end
// Remember end of frame
always @(posedge clk_f or negedge reset_n)
if (~reset_n)
eof_in_r <= 1'b0;
else if (~enable)
eof_in_r <= 1'b0;
else if (eof_in)
eof_in_r <= 1'b1;
else if (eof_sync1 & ~eof_sync2)
eof_in_r <= 1'b0;
always @(posedge clk_av or negedge reset_n)
if (~reset_n)
begin
eof_in_sync1 <= 1'b0;
eof_in_sync2 <= 1'b0;
end
else
begin
eof_in_sync1 <= eof_in_r;
eof_in_sync2 <= eof_in_sync1;
end
always @(posedge clk_av or negedge reset_n)
if (~reset_n)
final_burst <= 1'b0;
else if (~enable)
final_burst <= 1'b0;
else if (eof_in_sync1 & ~eof_in_sync2)
final_burst <= 1'b1;
else if (eof)
final_burst <= 1'b0;
always @(posedge clk_av or negedge reset_n)
if (~reset_n)
master_state <= idle;
else if (~enable)
master_state <= idle;
else
case (master_state)
idle:
if (enable & (available >= 9'd32))
master_state <= wr1;
else if (final_burst & (available >= 9'h0))
master_state <= wr1;
else
master_state <= idle;
wr1:
master_state <= wr2;
wr2:
master_state <= write;
write:
if (cycle_end & (burst == 5'h2))
master_state <= wr_wait;
else
master_state <= write;
wr_wait:
if (cycle_end & (burst == 5'h0))
master_state <= idle;
else
master_state <= wr_wait;
default: master_state <= idle;
endcase
wire m_write_n = ~master_state[2];
wire rd_en = master_state[3] & ~(~m_write_n & m_waitrequest);
// detect end of current cycle
assign cycle_end = ~m_write_n & ~m_waitrequest;
// detect end of final burst
assign eof = final_burst & cycle_end & (available == 9'h0);
wire reload = fb_done & (master_state == wr_wait) & cycle_end & (burst == 5'h0);
always @(posedge clk_av or negedge reset_n)
if (~reset_n)
fb_done <= 1'b0;
else if (~enable)
fb_done <= 1'b0;
else if (eof)
fb_done <= 1'b1;
else if (wr_mcontrol_r)
fb_done <= 1'b0;
always @(posedge clk_av or negedge reset_n)
if (~reset_n)
burst <= 5'b0;
else if (~enable)
burst <= 5'b0;
else if ((master_state == idle) & enable & (available >= 9'd32))
burst <= 5'd31;
else if ((master_state == idle) & enable & final_burst & (available >= 9'h0))
// *** What if available == 1 ???
burst <= available[4:0]-1;
else if (cycle_end)
burst <= burst - (|burst);
always @(posedge clk_av or negedge reset_n)
if (~reset_n)
m_address <= 32'b0;
else if (reload)
// auto reload
m_address <= mfb_reg;
else if (wr_mcontrol_r)
// processor controlled re-load
m_address <= mfb_reg;
else if (cycle_end)
// increment
m_address <= m_address + 32'h4;
reg [31:0] m_writedata;
wire [31:0] fifo_rdata;
reg [31:0] fifo_buffer;
reg wait_r;
always @(posedge clk_av or negedge reset_n)
if (~reset_n)
wait_r <= 1'b0;
else
wait_r <= ~m_write_n & m_waitrequest;
always @(posedge clk_av or negedge reset_n)
if (~reset_n)
fifo_buffer <= 32'b0;
else if (~m_write_n & m_waitrequest & ~wait_r)
fifo_buffer <= fifo_rdata;
always @(posedge clk_av or negedge reset_n)
if (~reset_n)
m_writedata <= 32'b0;
else if (cycle_end & wait_r)
m_writedata <= fifo_buffer;
else if ((master_state == wr2) | cycle_end)
m_writedata <= fifo_rdata;
//---------------------------------------------------------------------------
// Instantiate the FIFO
//---------------------------------------------------------------------------
dual_port_fifo #(DEVICE, 7, 32) u1_fifo
(
.rst_n (~(~reset_n | sof)),
// Write side
.clk_wr (clk_f),
.wr (wr),
.wdata (wdata),
.wr_almost_full (),
.wr_full (full),
.reset_fifo_rd (),
// Read side
.clk_rd (clk_av),
.rd_en (rd_en),
.rdata (fifo_rdata),
.rd_empty (),
.rd_available (available),
.full_error (),
.empty_error ()
);
endmodule // avalon_wr_dma_fifo
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -