637 lines
18 KiB
Coq
637 lines
18 KiB
Coq
|
/////////////////////////////////////////////////////////////////////
|
||
|
//// ////
|
||
|
//// Internal DMA Engine ////
|
||
|
//// ////
|
||
|
//// ////
|
||
|
//// Author: Rudolf Usselmann ////
|
||
|
//// rudi@asics.ws ////
|
||
|
//// ////
|
||
|
//// ////
|
||
|
//// Downloaded from: http://www.opencores.org/cores/usb/ ////
|
||
|
//// ////
|
||
|
/////////////////////////////////////////////////////////////////////
|
||
|
//// ////
|
||
|
//// Copyright (C) 2000-2003 Rudolf Usselmann ////
|
||
|
//// www.asics.ws ////
|
||
|
//// rudi@asics.ws ////
|
||
|
//// ////
|
||
|
//// This source file may be used and distributed without ////
|
||
|
//// restriction provided that this copyright statement is not ////
|
||
|
//// removed from the file and that any derivative work contains ////
|
||
|
//// the original copyright notice and the associated disclaimer.////
|
||
|
//// ////
|
||
|
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
|
||
|
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
|
||
|
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
|
||
|
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
|
||
|
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ////
|
||
|
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ////
|
||
|
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ////
|
||
|
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ////
|
||
|
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ////
|
||
|
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ////
|
||
|
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ////
|
||
|
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ////
|
||
|
//// POSSIBILITY OF SUCH DAMAGE. ////
|
||
|
//// ////
|
||
|
/////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
// CVS Log
|
||
|
//
|
||
|
// $Id: usbf_idma.v,v 1.8 2003/10/17 02:36:57 rudi Exp $
|
||
|
//
|
||
|
// $Date: 2003/10/17 02:36:57 $
|
||
|
// $Revision: 1.8 $
|
||
|
// $Author: rudi $
|
||
|
// $Locker: $
|
||
|
// $State: Exp $
|
||
|
//
|
||
|
// Change History:
|
||
|
// $Log: usbf_idma.v,v $
|
||
|
// Revision 1.8 2003/10/17 02:36:57 rudi
|
||
|
// - Disabling bit stuffing and NRZI encoding during speed negotiation
|
||
|
// - Now the core can send zero size packets
|
||
|
// - Fixed register addresses for some of the higher endpoints
|
||
|
// (conversion between decimal/hex was wrong)
|
||
|
// - The core now does properly evaluate the function address to
|
||
|
// determine if the packet was intended for it.
|
||
|
// - Various other minor bugs and typos
|
||
|
//
|
||
|
// Revision 1.7 2001/11/04 12:22:45 rudi
|
||
|
//
|
||
|
// - Fixed previous fix (brocke something else ...)
|
||
|
// - Majore Synthesis cleanup
|
||
|
//
|
||
|
// Revision 1.6 2001/11/03 03:26:22 rudi
|
||
|
//
|
||
|
// - Fixed several interrupt and error condition reporting bugs
|
||
|
//
|
||
|
// Revision 1.5 2001/09/24 01:15:28 rudi
|
||
|
//
|
||
|
// Changed reset to be active high async.
|
||
|
//
|
||
|
// Revision 1.4 2001/09/23 08:39:33 rudi
|
||
|
//
|
||
|
// Renamed DEBUG and VERBOSE_DEBUG to USBF_DEBUG and USBF_VERBOSE_DEBUG ...
|
||
|
//
|
||
|
// Revision 1.3 2001/09/19 14:38:57 rudi
|
||
|
//
|
||
|
// Fixed TxValid handling bug.
|
||
|
//
|
||
|
// Revision 1.2 2001/09/13 13:14:02 rudi
|
||
|
//
|
||
|
// Fixed a problem that would sometimes prevent the core to come out of
|
||
|
// reset and immediately be operational ...
|
||
|
//
|
||
|
// Revision 1.1 2001/08/03 05:30:09 rudi
|
||
|
//
|
||
|
//
|
||
|
// 1) Reorganized directory structure
|
||
|
//
|
||
|
// Revision 1.2 2001/03/31 13:00:51 rudi
|
||
|
//
|
||
|
// - Added Core configuration
|
||
|
// - Added handling of OUT packets less than MAX_PL_SZ in DMA mode
|
||
|
// - Modified WISHBONE interface and sync logic
|
||
|
// - Moved SSRAM outside the core (added interface)
|
||
|
// - Many small bug fixes ...
|
||
|
//
|
||
|
// Revision 1.0 2001/03/07 09:17:12 rudi
|
||
|
//
|
||
|
//
|
||
|
// Changed all revisions to revision 1.0. This is because OpenCores CVS
|
||
|
// interface could not handle the original '0.1' revision ....
|
||
|
//
|
||
|
// Revision 0.1.0.1 2001/02/28 08:10:50 rudi
|
||
|
// Initial Release
|
||
|
//
|
||
|
//
|
||
|
|
||
|
`include "usbf_defines.v"
|
||
|
|
||
|
module usbf_idma( clk, rst,
|
||
|
|
||
|
// Packet Disassembler/Assembler interface
|
||
|
rx_data_st, rx_data_valid, rx_data_done,
|
||
|
send_data, tx_data_st, rd_next,
|
||
|
|
||
|
// Protocol Engine
|
||
|
rx_dma_en, tx_dma_en,
|
||
|
abort, idma_done,
|
||
|
buf_size, dma_en,
|
||
|
send_zero_length,
|
||
|
|
||
|
// Register File Manager Interface
|
||
|
adr, size, sizu_c,
|
||
|
|
||
|
// Memory Arb interface
|
||
|
madr, mdout, mdin, mwe, mreq, mack
|
||
|
);
|
||
|
|
||
|
parameter SSRAM_HADR = 14;
|
||
|
|
||
|
// Packet Disassembler/Assembler interface
|
||
|
input clk, rst;
|
||
|
input [7:0] rx_data_st;
|
||
|
input rx_data_valid;
|
||
|
input rx_data_done;
|
||
|
output send_data;
|
||
|
output [7:0] tx_data_st;
|
||
|
input rd_next;
|
||
|
|
||
|
// Protocol Engine
|
||
|
input rx_dma_en; // Allows the data to be stored
|
||
|
input tx_dma_en; // Allows for data to be retrieved
|
||
|
input abort; // Abort Transfer (time_out, crc_err or rx_error)
|
||
|
output idma_done; // DMA is done
|
||
|
input [13:0] buf_size; // Actual buffer size
|
||
|
input dma_en; // External DMA enabled
|
||
|
input send_zero_length;
|
||
|
|
||
|
// Register File Manager Interface
|
||
|
input [SSRAM_HADR + 2:0] adr; // Byte Address
|
||
|
input [13:0] size; // Size in bytes
|
||
|
output [10:0] sizu_c; // Up and Down counting size registers, used to update
|
||
|
|
||
|
// Memory Arb interface
|
||
|
output [SSRAM_HADR:0] madr; // word address
|
||
|
output [31:0] mdout;
|
||
|
input [31:0] mdin;
|
||
|
output mwe;
|
||
|
output mreq;
|
||
|
input mack;
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Local Wires and Registers
|
||
|
//
|
||
|
|
||
|
parameter [7:0] // synopsys enum state
|
||
|
IDLE = 8'b00000001,
|
||
|
WAIT_MRD = 8'b00000010,
|
||
|
MEM_WR = 8'b00000100,
|
||
|
MEM_WR1 = 8'b00001000,
|
||
|
MEM_WR2 = 8'b00010000,
|
||
|
MEM_RD1 = 8'b00100000,
|
||
|
MEM_RD2 = 8'b01000000,
|
||
|
MEM_RD3 = 8'b10000000;
|
||
|
|
||
|
reg [7:0] /* synopsys enum state */ state, next_state;
|
||
|
// synopsys state_vector state
|
||
|
|
||
|
reg tx_dma_en_r, rx_dma_en_r;
|
||
|
|
||
|
reg [SSRAM_HADR:0] adr_cw; // Internal word address counter
|
||
|
reg [2:0] adr_cb; // Internal byte address counter
|
||
|
reg [SSRAM_HADR:0] adrw_next; // next address
|
||
|
reg [SSRAM_HADR:0] adrw_next1; // next address (after overrun check)
|
||
|
reg [SSRAM_HADR:0] last_buf_adr; // Last Buffer Address
|
||
|
reg [2:0] adrb_next; // next byte address
|
||
|
reg [13:0] sizd_c; // Internal size counter
|
||
|
reg [10:0] sizu_c; // Internal size counter
|
||
|
wire adr_incw;
|
||
|
wire adr_incb;
|
||
|
wire siz_dec;
|
||
|
wire siz_inc;
|
||
|
|
||
|
reg word_done; // Indicates that a word has been
|
||
|
// assembled
|
||
|
reg mreq_d; // Memory request from State Machine
|
||
|
reg [31:0] dtmp_r; // Temp data assembly register
|
||
|
reg [31:0] dout_r; // Data output register
|
||
|
reg mwe_d; // Memory Write enable
|
||
|
reg dtmp_sel; // Selects tmp data register for pre-fetch
|
||
|
|
||
|
reg sizd_is_zero; // Indicates when all bytes have been
|
||
|
// transferred
|
||
|
wire sizd_is_zero_d;
|
||
|
|
||
|
reg [7:0] tx_data_st; // Data output to packet assembler
|
||
|
reg [31:0] rd_buf0, rd_buf1; // Mem Rd. buffers for TX
|
||
|
reg rd_first; // Indicates initial fill of buffers
|
||
|
|
||
|
reg idma_done; // DMA transfer is done
|
||
|
|
||
|
reg mack_r;
|
||
|
wire send_data; // Enable UTMI Transmitter
|
||
|
reg send_data_r;
|
||
|
|
||
|
reg word_done_r;
|
||
|
reg wr_last;
|
||
|
reg wr_last_en;
|
||
|
reg wr_done;
|
||
|
reg wr_done_r;
|
||
|
reg dtmp_sel_r;
|
||
|
reg mwe;
|
||
|
reg rx_data_done_r2;
|
||
|
wire fill_buf0, fill_buf1;
|
||
|
wire adrb_is_3;
|
||
|
|
||
|
reg rx_data_done_r;
|
||
|
reg rx_data_valid_r;
|
||
|
reg [7:0] rx_data_st_r;
|
||
|
|
||
|
reg send_zero_length_r;
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Memory Arb interface
|
||
|
//
|
||
|
|
||
|
// Memory Request
|
||
|
assign mreq = (mreq_d & !mack_r) | word_done_r;
|
||
|
|
||
|
// Output Data
|
||
|
assign mdout = dout_r;
|
||
|
|
||
|
// Memory Address
|
||
|
assign madr = adr_cw;
|
||
|
|
||
|
always @(posedge clk)
|
||
|
mwe <= mwe_d;
|
||
|
|
||
|
always @(posedge clk)
|
||
|
mack_r <= mreq & mack;
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Misc Logic
|
||
|
//
|
||
|
|
||
|
always @(posedge clk)
|
||
|
rx_data_valid_r <= rx_data_valid;
|
||
|
|
||
|
always @(posedge clk)
|
||
|
rx_data_st_r <= rx_data_st;
|
||
|
|
||
|
always @(posedge clk)
|
||
|
rx_data_done_r <= rx_data_done;
|
||
|
|
||
|
always @(posedge clk)
|
||
|
rx_data_done_r2 <= rx_data_done_r;
|
||
|
|
||
|
// Generate one cycle pulses for tx and rx dma enable
|
||
|
always @(posedge clk)
|
||
|
tx_dma_en_r <= tx_dma_en;
|
||
|
|
||
|
always @(posedge clk)
|
||
|
rx_dma_en_r <= rx_dma_en;
|
||
|
|
||
|
always @(posedge clk)
|
||
|
send_zero_length_r <= send_zero_length;
|
||
|
|
||
|
// address counter
|
||
|
always @(posedge clk)
|
||
|
if(rx_dma_en_r || tx_dma_en_r) adr_cw <= adr[SSRAM_HADR + 2:2];
|
||
|
else adr_cw <= adrw_next1;
|
||
|
|
||
|
always @(posedge clk)
|
||
|
last_buf_adr <= adr + { {SSRAM_HADR+2-13{1'b0}}, buf_size };
|
||
|
|
||
|
always @(dma_en or adrw_next or last_buf_adr)
|
||
|
if(adrw_next == last_buf_adr && dma_en) adrw_next1 = {SSRAM_HADR+1{1'b0}};
|
||
|
else adrw_next1 = adrw_next;
|
||
|
|
||
|
always @(adr_incw or adr_cw)
|
||
|
if(adr_incw) adrw_next = adr_cw + {{SSRAM_HADR{1'b0}}, 1'b1};
|
||
|
else adrw_next = adr_cw;
|
||
|
|
||
|
`ifdef USBF_ASYNC_RESET
|
||
|
always @(posedge clk or negedge rst)
|
||
|
`else
|
||
|
always @(posedge clk)
|
||
|
`endif
|
||
|
if(!rst) adr_cb <= 3'h0;
|
||
|
else
|
||
|
if(rx_dma_en_r || tx_dma_en_r) adr_cb <= adr[2:0];
|
||
|
else adr_cb <= adrb_next;
|
||
|
|
||
|
always @(adr_incb or adr_cb)
|
||
|
if(adr_incb) adrb_next = adr_cb + 3'h1;
|
||
|
else adrb_next = adr_cb;
|
||
|
|
||
|
assign adr_incb = rx_data_valid_r | rd_next;
|
||
|
assign adr_incw = !dtmp_sel_r & mack_r;
|
||
|
|
||
|
// Size Counter (counting backward from input size)
|
||
|
`ifdef USBF_ASYNC_RESET
|
||
|
always @(posedge clk or negedge rst)
|
||
|
`else
|
||
|
always @(posedge clk)
|
||
|
`endif
|
||
|
if(!rst) sizd_c <= 14'h3fff;
|
||
|
else
|
||
|
if(tx_dma_en || tx_dma_en_r) sizd_c <= size;
|
||
|
else
|
||
|
if(siz_dec) sizd_c <= sizd_c - 14'h1;
|
||
|
|
||
|
assign siz_dec = (rd_first & mack_r) | (rd_next & (sizd_c != 14'h0));
|
||
|
|
||
|
assign sizd_is_zero_d = sizd_c == 14'h0;
|
||
|
|
||
|
always @(posedge clk)
|
||
|
sizd_is_zero <= sizd_is_zero_d;
|
||
|
|
||
|
// Size Counter (counting up from zero)
|
||
|
`ifdef USBF_ASYNC_RESET
|
||
|
always @(posedge clk or negedge rst)
|
||
|
`else
|
||
|
always @(posedge clk)
|
||
|
`endif
|
||
|
if(!rst) sizu_c <= 11'h0;
|
||
|
else
|
||
|
// Do I need to add "abort" in the next line ???
|
||
|
if(rx_dma_en_r) sizu_c <= 11'h0;
|
||
|
else
|
||
|
if(siz_inc) sizu_c <= sizu_c + 11'h1;
|
||
|
|
||
|
assign siz_inc = rx_data_valid_r;
|
||
|
|
||
|
// DMA Done Indicator
|
||
|
always @(posedge clk)
|
||
|
idma_done <= (rx_data_done_r | sizd_is_zero_d); // & !tx_dma_en;
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// RX Logic
|
||
|
//
|
||
|
|
||
|
always @(posedge clk)
|
||
|
dtmp_sel_r <= dtmp_sel;
|
||
|
|
||
|
// Memory data input
|
||
|
always @(posedge clk)
|
||
|
if(dtmp_sel_r) dtmp_r <= mdin;
|
||
|
else
|
||
|
if(rx_data_valid_r)
|
||
|
begin
|
||
|
if(adr_cb[1:0] == 2'h0) dtmp_r[07:00] <= rx_data_st_r;
|
||
|
if(adr_cb[1:0] == 2'h1) dtmp_r[15:08] <= rx_data_st_r;
|
||
|
if(adr_cb[1:0] == 2'h2) dtmp_r[23:16] <= rx_data_st_r;
|
||
|
if(adr_cb[1:0] == 2'h3) dtmp_r[31:24] <= rx_data_st_r;
|
||
|
end
|
||
|
|
||
|
always @(posedge clk)
|
||
|
word_done <= ((adr_cb[1:0] == 2'h3) & rx_data_valid_r) | wr_last;
|
||
|
|
||
|
always @(posedge clk)
|
||
|
word_done_r <= word_done & !word_done_r;
|
||
|
|
||
|
// Store output data and address when we got a word
|
||
|
always @(posedge clk)
|
||
|
if(word_done) dout_r <= dtmp_r;
|
||
|
|
||
|
always @(posedge clk)
|
||
|
wr_last <= (adr_cb[1:0] != 2'h0) & !rx_data_valid_r & wr_last_en;
|
||
|
|
||
|
always @(posedge clk)
|
||
|
wr_done_r <= rx_data_done_r;
|
||
|
|
||
|
always @(posedge clk)
|
||
|
wr_done <= wr_done_r;
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// TX Logic
|
||
|
//
|
||
|
|
||
|
// Fill TX Buffers
|
||
|
always @(posedge clk)
|
||
|
if(fill_buf0) rd_buf0 <= mdin;
|
||
|
|
||
|
always @(posedge clk)
|
||
|
if(fill_buf1) rd_buf1 <= mdin;
|
||
|
|
||
|
always @(adrb_next or rd_buf0 or rd_buf1)
|
||
|
case(adrb_next[2:0]) // synopsys full_case parallel_case
|
||
|
3'h0: tx_data_st = rd_buf0[07:00];
|
||
|
3'h1: tx_data_st = rd_buf0[15:08];
|
||
|
3'h2: tx_data_st = rd_buf0[23:16];
|
||
|
3'h3: tx_data_st = rd_buf0[31:24];
|
||
|
3'h4: tx_data_st = rd_buf1[07:00];
|
||
|
3'h5: tx_data_st = rd_buf1[15:08];
|
||
|
3'h6: tx_data_st = rd_buf1[23:16];
|
||
|
3'h7: tx_data_st = rd_buf1[31:24];
|
||
|
endcase
|
||
|
|
||
|
assign fill_buf0 = !adr_cw[0] & mack_r;
|
||
|
assign fill_buf1 = adr_cw[0] & mack_r;
|
||
|
|
||
|
assign adrb_is_3 = adr_cb[1:0] == 2'h3;
|
||
|
|
||
|
`ifdef USBF_ASYNC_RESET
|
||
|
always @(posedge clk or negedge rst)
|
||
|
`else
|
||
|
always @(posedge clk)
|
||
|
`endif
|
||
|
if(!rst) send_data_r <= 1'b0;
|
||
|
else
|
||
|
if(rd_first) send_data_r <= 1'b1;
|
||
|
else
|
||
|
if(((sizd_c==14'h1) && rd_next) || sizd_is_zero_d) send_data_r <= 1'b0;
|
||
|
|
||
|
assign send_data = send_data_r | send_zero_length_r;
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// IDMA Load/Store State Machine
|
||
|
//
|
||
|
|
||
|
// store incoming data to memory until rx_data done
|
||
|
// First pre-fetch data from memory, so that bytes can be stuffed properly
|
||
|
|
||
|
`ifdef USBF_ASYNC_RESET
|
||
|
always @(posedge clk or negedge rst)
|
||
|
`else
|
||
|
always @(posedge clk)
|
||
|
`endif
|
||
|
if(!rst) state <= IDLE;
|
||
|
else state <= next_state;
|
||
|
|
||
|
always @(state or mack_r or abort or rx_dma_en_r or tx_dma_en_r or
|
||
|
sizd_is_zero or wr_last or wr_done or rx_data_done_r2 or
|
||
|
rd_next or adrb_is_3 or send_zero_length_r)
|
||
|
begin
|
||
|
next_state = state; // Default do not change state
|
||
|
mreq_d = 1'b0;
|
||
|
mwe_d = 1'b0;
|
||
|
rd_first = 1'b0;
|
||
|
dtmp_sel = 1'b0;
|
||
|
wr_last_en = 1'b0;
|
||
|
|
||
|
case(state) // synopsys full_case parallel_case
|
||
|
IDLE:
|
||
|
begin
|
||
|
|
||
|
// synopsys translate_off
|
||
|
`ifdef USBF_VERBOSE_DEBUG
|
||
|
$display("IDMA: Entered IDLE state (%t)", $time);
|
||
|
`endif
|
||
|
`ifdef USBF_DEBUG
|
||
|
if(rst)
|
||
|
begin
|
||
|
if(rx_dma_en_r === 1'bx) $display("ERROR: IDMA: IDLE: rx_dma_en_r is unknown. (%t)", $time);
|
||
|
if(tx_dma_en_r === 1'bx) $display("ERROR: IDMA: IDLE: tx_dma_en_r is unknown. (%t)", $time);
|
||
|
if(abort === 1'bx) $display("ERROR: IDMA: IDLE: abort is unknown. (%t)", $time);
|
||
|
end
|
||
|
`endif
|
||
|
// synopsys translate_on
|
||
|
|
||
|
if(rx_dma_en_r && !abort)
|
||
|
begin
|
||
|
next_state = WAIT_MRD;
|
||
|
end
|
||
|
if(tx_dma_en_r && !abort && !send_zero_length_r)
|
||
|
begin
|
||
|
next_state = MEM_RD1;
|
||
|
end
|
||
|
end
|
||
|
|
||
|
WAIT_MRD: // Pre-fetch a word from memory
|
||
|
begin
|
||
|
|
||
|
// synopsys translate_off
|
||
|
`ifdef USBF_VERBOSE_DEBUG
|
||
|
$display("IDMA: Entered WAIT_MRD state (%t)", $time);
|
||
|
`endif
|
||
|
`ifdef USBF_DEBUG
|
||
|
if(abort === 1'bx) $display("ERROR: IDMA: WAIT_MRD: abort is unknown. (%t)", $time);
|
||
|
if(mack_r === 1'bx) $display("ERROR: IDMA: WAIT_MRD: mack_r is unknown. (%t)", $time);
|
||
|
`endif
|
||
|
// synopsys translate_on
|
||
|
|
||
|
if(abort) next_state = IDLE;
|
||
|
else
|
||
|
if(mack_r) next_state = MEM_WR;
|
||
|
else
|
||
|
begin
|
||
|
dtmp_sel = 1'b1;
|
||
|
mreq_d = 1'b1;
|
||
|
end
|
||
|
end
|
||
|
|
||
|
MEM_WR:
|
||
|
begin
|
||
|
|
||
|
// synopsys translate_off
|
||
|
`ifdef USBF_VERBOSE_DEBUG
|
||
|
$display("IDMA: Entered MEM_WR state (%t)", $time);
|
||
|
`endif
|
||
|
`ifdef USBF_DEBUG
|
||
|
if(abort === 1'bx) $display("ERROR: IDMA: MEM_WR: abort is unknown. (%t)", $time);
|
||
|
if(rx_data_done_r2 === 1'bx) $display("ERROR: IDMA: MEM_WR: rx_data_done_r2 is unknown. (%t)", $time);
|
||
|
`endif
|
||
|
// synopsys translate_on
|
||
|
|
||
|
mwe_d = 1'b1;
|
||
|
if(abort) next_state = IDLE;
|
||
|
else
|
||
|
if(rx_data_done_r2)
|
||
|
begin
|
||
|
wr_last_en = 1'b1;
|
||
|
next_state = MEM_WR1;
|
||
|
end
|
||
|
|
||
|
end
|
||
|
MEM_WR1:
|
||
|
begin
|
||
|
|
||
|
// synopsys translate_off
|
||
|
`ifdef USBF_VERBOSE_DEBUG
|
||
|
$display("IDMA: Entered MEM_WR1 state (%t)", $time);
|
||
|
`endif
|
||
|
`ifdef USBF_DEBUG
|
||
|
if(abort === 1'bx) $display("ERROR: IDMA: MEM_WR1: abort is unknown. (%t)", $time);
|
||
|
if(wr_last === 1'bx) $display("ERROR: IDMA: MEM_WR1: wr_last is unknown. (%t)", $time);
|
||
|
if(wr_done === 1'bx) $display("ERROR: IDMA: MEM_WR1: wr_done is unknown. (%t)", $time);
|
||
|
`endif
|
||
|
// synopsys translate_on
|
||
|
|
||
|
mwe_d = 1'b1;
|
||
|
wr_last_en = 1'b1;
|
||
|
if(abort) next_state = IDLE;
|
||
|
else
|
||
|
if(wr_last) next_state = MEM_WR2;
|
||
|
else
|
||
|
if(wr_done) next_state = IDLE;
|
||
|
end
|
||
|
|
||
|
MEM_WR2:
|
||
|
begin
|
||
|
|
||
|
// synopsys translate_off
|
||
|
`ifdef USBF_VERBOSE_DEBUG
|
||
|
$display("IDMA: Entered MEM_WR2 state (%t)", $time);
|
||
|
`endif
|
||
|
`ifdef USBF_DEBUG
|
||
|
if(mack_r === 1'bx) $display("ERROR: IDMA: MEM_WR2: mack_r is unknown. (%t)", $time);
|
||
|
`endif
|
||
|
// synopsys translate_on
|
||
|
|
||
|
mwe_d = 1'b1;
|
||
|
if(mack_r) next_state = IDLE;
|
||
|
end
|
||
|
|
||
|
MEM_RD1:
|
||
|
begin
|
||
|
|
||
|
// synopsys translate_off
|
||
|
`ifdef USBF_VERBOSE_DEBUG
|
||
|
$display("IDMA: Entered MEM_RD1 state (%t)", $time);
|
||
|
`endif
|
||
|
`ifdef USBF_DEBUG
|
||
|
if(abort === 1'bx) $display("ERROR: IDMA: MEM_RD1: abort is unknown. (%t)", $time);
|
||
|
if(mack_r === 1'bx) $display("ERROR: IDMA: MEM_RD1: mack_r is unknown. (%t)", $time);
|
||
|
`endif
|
||
|
// synopsys translate_on
|
||
|
|
||
|
mreq_d = 1'b1;
|
||
|
if(mack_r) rd_first = 1'b1;
|
||
|
if(abort) next_state = IDLE;
|
||
|
else
|
||
|
if(mack_r) next_state = MEM_RD2;
|
||
|
end
|
||
|
MEM_RD2:
|
||
|
begin
|
||
|
|
||
|
// synopsys translate_off
|
||
|
`ifdef USBF_VERBOSE_DEBUG
|
||
|
$display("IDMA: Entered MEM_RD2 state (%t)", $time);
|
||
|
`endif
|
||
|
`ifdef USBF_DEBUG
|
||
|
if(abort === 1'bx) $display("ERROR: IDMA: MEM_RD2: abort is unknown. (%t)", $time);
|
||
|
if(mack_r === 1'bx) $display("ERROR: IDMA: MEM_RD2: mack_r is unknown. (%t)", $time);
|
||
|
`endif
|
||
|
// synopsys translate_on
|
||
|
|
||
|
mreq_d = 1'b1;
|
||
|
if(abort) next_state = IDLE;
|
||
|
else
|
||
|
if(mack_r) next_state = MEM_RD3;
|
||
|
end
|
||
|
MEM_RD3:
|
||
|
begin
|
||
|
|
||
|
// synopsys translate_off
|
||
|
`ifdef USBF_VERBOSE_DEBUG
|
||
|
$display("IDMA: Entered MEM_RD3 state (%t)", $time);
|
||
|
`endif
|
||
|
`ifdef USBF_DEBUG
|
||
|
if(abort === 1'bx) $display("ERROR: IDMA: MEM_RD3: abort is unknown. (%t)", $time);
|
||
|
if(sizd_is_zero===1'bx) $display("ERROR: IDMA: MEM_RD3: sizd_is_zero is unknown. (%t)", $time);
|
||
|
if(adrb_is_3 === 1'bx) $display("ERROR: IDMA: MEM_RD3: adrb_is_3 is unknown. (%t)", $time);
|
||
|
if(rd_next === 1'bx) $display("ERROR: IDMA: MEM_RD3: rd_next is unknown. (%t)", $time);
|
||
|
`endif
|
||
|
// synopsys translate_on
|
||
|
|
||
|
if(sizd_is_zero || abort) next_state = IDLE;
|
||
|
else
|
||
|
if(adrb_is_3 && rd_next) next_state = MEM_RD2;
|
||
|
end
|
||
|
endcase
|
||
|
|
||
|
end
|
||
|
|
||
|
endmodule
|
||
|
|