Line 1... |
Line 1... |
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
//
|
|
// Filename: wbdmac.v
|
// Filename: wbdmac.v
|
//
|
//
|
// Project: Zip CPU -- a small, lightweight, RISC CPU soft core
|
// Project: Zip CPU -- a small, lightweight, RISC CPU soft core
|
//
|
//
|
// Purpose: Wishbone DMA controller
|
// Purpose: Wishbone DMA controller
|
Line 76... |
Line 75... |
// be read from the length register. If the internal buffer is
|
// be read from the length register. If the internal buffer is
|
// being used, then you can read how much has been read into that
|
// being used, then you can read how much has been read into that
|
// buffer by reading from bits 25..16 of this control/status
|
// buffer by reading from bits 25..16 of this control/status
|
// register.
|
// register.
|
//
|
//
|
// Creator: Dan Gisselquist
|
// Creator: Dan Gisselquist, Ph.D.
|
// Gisselquist Technology, LLC
|
// Gisselquist Technology, LLC
|
//
|
//
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
|
// Copyright (C) 2015-2017, Gisselquist Technology, LLC
|
//
|
//
|
// This program is free software (firmware): you can redistribute it and/or
|
// This program is free software (firmware): you can redistribute it and/or
|
// modify it under the terms of the GNU General Public License as published
|
// modify it under the terms of the GNU General Public License as published
|
// by the Free Software Foundation, either version 3 of the License, or (at
|
// by the Free Software Foundation, either version 3 of the License, or (at
|
// your option) any later version.
|
// your option) any later version.
|
Line 93... |
Line 92... |
// This program is distributed in the hope that it will be useful, but WITHOUT
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
|
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
// for more details.
|
// for more details.
|
//
|
//
|
|
// You should have received a copy of the GNU General Public License along
|
|
// with this program. (It's in the $(ROOT)/doc directory. Run make with no
|
|
// target there if the PDF file isn't present.) If not, see
|
|
// <http://www.gnu.org/licenses/> for a copy.
|
|
//
|
// License: GPL, v3, as defined and found on www.gnu.org,
|
// License: GPL, v3, as defined and found on www.gnu.org,
|
// http://www.gnu.org/licenses/gpl.html
|
// http://www.gnu.org/licenses/gpl.html
|
//
|
//
|
//
|
//
|
///////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
//
|
//
|
`define DMA_IDLE 3'b000
|
`define DMA_IDLE 3'b000
|
`define DMA_WAIT 3'b001
|
`define DMA_WAIT 3'b001
|
`define DMA_READ_REQ 3'b010
|
`define DMA_READ_REQ 3'b010
|
Line 166... |
Line 170... |
wire [(AW-1):0] bus_nracks;
|
wire [(AW-1):0] bus_nracks;
|
assign bus_nracks = { {(AW-LGMEMLEN-1){1'b0}}, nracks };
|
assign bus_nracks = { {(AW-LGMEMLEN-1){1'b0}}, nracks };
|
|
|
reg last_read_request, last_read_ack,
|
reg last_read_request, last_read_ack,
|
last_write_request, last_write_ack;
|
last_write_request, last_write_ack;
|
reg trigger, abort;
|
reg trigger, abort, user_halt;
|
|
|
initial dma_state = `DMA_IDLE;
|
initial dma_state = `DMA_IDLE;
|
initial o_interrupt = 1'b0;
|
initial o_interrupt = 1'b0;
|
initial cfg_len = {(AW){1'b0}};
|
initial cfg_len = {(AW){1'b0}};
|
initial cfg_blocklen_sub_one = {(LGMEMLEN){1'b1}};
|
initial cfg_blocklen_sub_one = {(LGMEMLEN){1'b1}};
|
Line 191... |
Line 195... |
// and thus to start.
|
// and thus to start.
|
if ((i_swb_stb)&&(i_swb_we))
|
if ((i_swb_stb)&&(i_swb_we))
|
begin
|
begin
|
case(i_swb_addr)
|
case(i_swb_addr)
|
2'b00: begin
|
2'b00: begin
|
if ((i_swb_data[27:16] == 12'hfed)
|
if ((i_swb_data[31:16] == 16'h0fed)
|
&&(cfg_len_nonzero))
|
&&(cfg_len_nonzero))
|
dma_state <= `DMA_WAIT;
|
dma_state <= `DMA_WAIT;
|
cfg_blocklen_sub_one
|
cfg_blocklen_sub_one
|
<= i_swb_data[(LGMEMLEN-1):0]
|
<= i_swb_data[(LGMEMLEN-1):0]
|
+ {(LGMEMLEN){1'b1}};
|
+ {(LGMEMLEN){1'b1}};
|
Line 219... |
Line 223... |
nwacks <= 0;
|
nwacks <= 0;
|
nwritten <= 0;
|
nwritten <= 0;
|
nread <= 0;
|
nread <= 0;
|
if (abort)
|
if (abort)
|
dma_state <= `DMA_IDLE;
|
dma_state <= `DMA_IDLE;
|
|
else if (user_halt)
|
|
dma_state <= `DMA_IDLE;
|
else if (trigger)
|
else if (trigger)
|
dma_state <= `DMA_READ_REQ;
|
dma_state <= `DMA_READ_REQ;
|
end
|
end
|
`DMA_READ_REQ: begin
|
`DMA_READ_REQ: begin
|
nwritten <= 0;
|
nwritten <= 0;
|
Line 238... |
Line 244... |
if (cfg_incs)
|
if (cfg_incs)
|
o_mwb_addr <= o_mwb_addr
|
o_mwb_addr <= o_mwb_addr
|
+ {{(AW-1){1'b0}},1'b1};
|
+ {{(AW-1){1'b0}},1'b1};
|
end
|
end
|
|
|
|
if (user_halt)
|
|
dma_state <= `DMA_READ_ACK;
|
if (i_mwb_err)
|
if (i_mwb_err)
|
begin
|
begin
|
cfg_len <= 0;
|
cfg_len <= 0;
|
dma_state <= `DMA_IDLE;
|
dma_state <= `DMA_IDLE;
|
end
|
end
|
|
|
if (abort)
|
if (abort)
|
dma_state <= `DMA_IDLE;
|
dma_state <= `DMA_IDLE;
|
if (i_mwb_ack)
|
if (i_mwb_ack)
|
begin
|
begin
|
nread <= nread+1;
|
nread <= nread+1;
|
Line 264... |
Line 273... |
end else if (i_mwb_ack)
|
end else if (i_mwb_ack)
|
begin
|
begin
|
nread <= nread+1;
|
nread <= nread+1;
|
if (last_read_ack) // (nread+1 == nracks)
|
if (last_read_ack) // (nread+1 == nracks)
|
dma_state <= `DMA_PRE_WRITE;
|
dma_state <= `DMA_PRE_WRITE;
|
|
if (user_halt)
|
|
dma_state <= `DMA_IDLE;
|
if (cfg_incs)
|
if (cfg_incs)
|
cfg_raddr <= cfg_raddr
|
cfg_raddr <= cfg_raddr
|
+ {{(AW-1){1'b0}},1'b1};
|
+ {{(AW-1){1'b0}},1'b1};
|
end
|
end
|
if (abort)
|
if (abort)
|
Line 301... |
Line 312... |
if (i_mwb_ack)
|
if (i_mwb_ack)
|
begin
|
begin
|
nwacks <= nwacks+1;
|
nwacks <= nwacks+1;
|
cfg_len <= cfg_len +{(AW){1'b1}}; // -1
|
cfg_len <= cfg_len +{(AW){1'b1}}; // -1
|
end
|
end
|
|
if (user_halt)
|
|
dma_state <= `DMA_WRITE_ACK;
|
if (abort)
|
if (abort)
|
dma_state <= `DMA_IDLE;
|
dma_state <= `DMA_IDLE;
|
end
|
end
|
`DMA_WRITE_ACK: begin
|
`DMA_WRITE_ACK: begin
|
if (i_mwb_err)
|
if (i_mwb_err)
|
Line 465... |
Line 478... |
always @(posedge i_clk)
|
always @(posedge i_clk)
|
abort <= (i_rst)||((i_swb_stb)&&(i_swb_we)
|
abort <= (i_rst)||((i_swb_stb)&&(i_swb_we)
|
&&(i_swb_addr == 2'b00)
|
&&(i_swb_addr == 2'b00)
|
&&(i_swb_data == 32'hffed0000));
|
&&(i_swb_data == 32'hffed0000));
|
|
|
|
initial user_halt = 1'b0;
|
|
always @(posedge i_clk)
|
|
user_halt <= ((user_halt)&&(dma_state != `DMA_IDLE))
|
|
||((i_swb_stb)&&(i_swb_we)&&(dma_state != `DMA_IDLE)
|
|
&&(i_swb_addr == 2'b00)
|
|
&&(i_swb_data == 32'hafed0000));
|
|
|
endmodule
|
endmodule
|
|
|
|
|
No newline at end of file
|
No newline at end of file
|