mirror of
https://github.com/aolofsson/oh.git
synced 2025-01-30 02:32:53 +08:00
Implemented DMA state machine
- Work in progress
This commit is contained in:
parent
26515bc1e9
commit
9bec938914
@ -4,34 +4,185 @@
|
||||
//# Author: Andreas Olofsson #
|
||||
//# License: MIT (see below) #
|
||||
//#############################################################################
|
||||
|
||||
`include "edma_regmap.vh"
|
||||
module edma_ctrl (/*AUTOARG*/
|
||||
// Outputs
|
||||
dma_state, outerloop, master_active, update,
|
||||
fetch_access, fetch_packet, dma_state, update, update2d,
|
||||
master_active,
|
||||
// Inputs
|
||||
clk, nreset, dma_en, chainmode, mastermode, access_in, wait_in
|
||||
clk, nreset, dma_en, chainmode, manualmode, mastermode, count,
|
||||
curr_descr, next_descr, reg_wait_in, access_in, wait_in
|
||||
);
|
||||
|
||||
// clk, reset, config
|
||||
input clk; // main clock
|
||||
input nreset; // async active low reset
|
||||
input dma_en; // dma is enabled
|
||||
input chainmode; // chainmode configuration
|
||||
input mastermode; // dma configured in mastermode
|
||||
parameter AW = 32; // address width
|
||||
localparam PW = 2*AW+40; // fetch packet width
|
||||
parameter ID = 4'b0000; // group id for DMA regs [10:8]
|
||||
|
||||
// packet control
|
||||
input access_in; // slave access
|
||||
input wait_in; // controls machine stall
|
||||
// clk, reset, config
|
||||
input clk; // main clock
|
||||
input nreset; // async active low reset
|
||||
input dma_en; // dma is enabled
|
||||
input chainmode; // chainmode configuration
|
||||
input manualmode; // descriptor fetch
|
||||
input mastermode; // dma configured in mastermode
|
||||
input [31:0] count; // current transfer count
|
||||
input [15:0] curr_descr;
|
||||
input [15:0] next_descr;
|
||||
|
||||
// descriptor fetch interface
|
||||
output fetch_access; // fetch descriptor
|
||||
output [PW-1:0] fetch_packet; // fetch packet
|
||||
input reg_wait_in; // register access wait
|
||||
|
||||
// slave access
|
||||
input access_in; // slave access
|
||||
input wait_in; // master/slave transfer stall
|
||||
|
||||
// status
|
||||
output [2:0] dma_state; // state of dma
|
||||
output outerloop; // dma currently in outerloop (2D)
|
||||
output master_active;// master is active
|
||||
output update; // update registers
|
||||
output [3:0] dma_state; // state of dma
|
||||
output update; // update registers
|
||||
output update2d; // dma currently in outerloop (2D)
|
||||
output master_active; // master is active
|
||||
|
||||
//###########################################################################
|
||||
//# BODY
|
||||
//###########################################################################
|
||||
|
||||
reg [3:0] dma_state;
|
||||
wire [15:0] descr;
|
||||
wire [15:0] fetch_addr;
|
||||
wire [AW-1:0] srcaddr_out;
|
||||
wire [4:0] reg_addr;
|
||||
|
||||
//###########################################
|
||||
//# STATE MACHINE
|
||||
//###########################################
|
||||
|
||||
`define DMA_IDLE 4'b0000 // dma idle
|
||||
`define DMA_FETCH0 4'b0001 // fetch cfg, next-ptr, stride_in
|
||||
`define DMA_FETCH1 4'b0010 // fetch cnt_out,cnt_in, stride_out
|
||||
`define DMA_FETCH2 4'b0011 // fetch srcaddr, dstaddr
|
||||
`define DMA_FETCH3 4'b0100 // fetch srcaddr64, dstaddr64
|
||||
`define DMA_FETCH4 4'b0101 // stall (no bypass)
|
||||
`define DMA_INNER 4'b0110 // dma inner loop
|
||||
`define DMA_OUTER 4'b0111 // dma outer loop
|
||||
`define DMA_DONE 4'b1000 // dma outer loop
|
||||
`define DMA_ERROR 4'b1001 // dma error
|
||||
|
||||
always @ (posedge clk or negedge nreset)
|
||||
if(!nreset)
|
||||
dma_state[3:0] <= `DMA_IDLE;
|
||||
else if(dma_error)
|
||||
dma_state[3:0] <= `DMA_ERROR;
|
||||
else
|
||||
case(dma_state[3:0])
|
||||
`DMA_IDLE:
|
||||
casez({dma_en,manualmode})
|
||||
2'b0? : dma_state[3:0] <= `DMA_IDLE;
|
||||
2'b11 : dma_state[3:0] <= `DMA_INNER;
|
||||
2'b10 : dma_state[3:0] <= `DMA_FETCH0;
|
||||
endcase // casez (dma_reg_write_config)
|
||||
`DMA_FETCH0:
|
||||
dma_state[3:0] <= reg_wait_in ? `DMA_FETCH0 : `DMA_FETCH1;
|
||||
`DMA_FETCH1:
|
||||
dma_state[3:0] <= reg_wait_in ? `DMA_FETCH1 : `DMA_FETCH2;
|
||||
`DMA_FETCH2:
|
||||
dma_state[3:0] <= reg_wait_in ? `DMA_FETCH2 : `DMA_FETCH3;
|
||||
`DMA_FETCH3:
|
||||
dma_state[3:0] <= reg_wait_in ? `DMA_FETCH3 : `DMA_FETCH3;
|
||||
`DMA_FETCH4:
|
||||
dma_state[3:0] <= reg_wait_in ? `DMA_FETCH4 : `DMA_INNER;
|
||||
`DMA_INNER:
|
||||
casez({update,incount_zero,outcount_zero})
|
||||
3'b0?? : dma_state[3:0] <= `DMA_INNER;
|
||||
3'b10? : dma_state[3:0] <= `DMA_INNER;
|
||||
3'b110 : dma_state[3:0] <= `DMA_OUTER;
|
||||
3'b111 : dma_state[3:0] <= `DMA_DONE;
|
||||
endcase
|
||||
`DMA_OUTER:
|
||||
dma_state[3:0] <= update ? `DMA_INNER : `DMA_OUTER;
|
||||
`DMA_DONE:
|
||||
casez({chainmode,manualmode})
|
||||
2'b0? : dma_state[3:0] <= `DMA_DONE;
|
||||
2'b11 : dma_state[3:0] <= `DMA_IDLE;
|
||||
2'b10 : dma_state[3:0] <= `DMA_FETCH0;
|
||||
endcase
|
||||
`DMA_ERROR:
|
||||
dma_state[3:0] <= dma_en ? `DMA_ERROR: `DMA_IDLE;
|
||||
endcase
|
||||
|
||||
//###########################################
|
||||
//# ACTIVE SIGNALS
|
||||
//###########################################
|
||||
|
||||
assign dma_error = 1'b0; //TODO: define error conditions
|
||||
|
||||
assign update = ~wait_in & (master_active | access_in);
|
||||
|
||||
assign update2d = update & (dma_state[3:0]==`DMA_OUTER);
|
||||
|
||||
assign master_active = mastermode &
|
||||
((dma_state[3:0]==`DMA_INNER) |
|
||||
(dma_state[3:0]==`DMA_OUTER));
|
||||
|
||||
|
||||
assign incount_zero = ~(|count[15:0]);
|
||||
|
||||
assign outcount_zero = ~(|count[31:16]);
|
||||
|
||||
//###########################################
|
||||
//# DESCRIPTOR FETCH ENGINE
|
||||
//###########################################
|
||||
|
||||
assign fetch_access = (dma_state[3:0]==`DMA_FETCH0) |
|
||||
(dma_state[3:0]==`DMA_FETCH1) |
|
||||
(dma_state[3:0]==`DMA_FETCH2);
|
||||
|
||||
|
||||
// fetch address
|
||||
assign descr[15:0] = (dma_state[3:0]==`DMA_FETCH0) ? next_descr[15:0] :
|
||||
curr_descr[15:0];
|
||||
|
||||
oh_mux3 #(.DW(16))
|
||||
mux3d (.out (fetch_addr[15:0]),
|
||||
.in0 (descr[15:0]), .sel0 (dma_state[3:0]==`DMA_FETCH0),
|
||||
.in1 (descr[15:0]+16'd8), .sel1 (dma_state[3:0]==`DMA_FETCH1),
|
||||
.in2 (descr[15:0]+16'd16), .sel2 (dma_state[3:0]==`DMA_FETCH2)
|
||||
);
|
||||
|
||||
|
||||
//address of first reg to fetch
|
||||
oh_mux3 #(.DW(5))
|
||||
mux3s (.out (reg_addr[4:0]),
|
||||
.in0 (`EDMA_CONFIG), .sel0 (dma_state[3:0]==`DMA_FETCH0),
|
||||
.in1 (`EDMA_COUNT), .sel1 (dma_state[3:0]==`DMA_FETCH1),
|
||||
.in2 (`EDMA_SRCADDR), .sel2 (dma_state[3:0]==`DMA_FETCH2)
|
||||
);
|
||||
|
||||
// constructing the address to return fetch to
|
||||
assign srcaddr_out[AW-1:0] = {{(AW-11){1'b0}}, //31-11
|
||||
ID, //10-7
|
||||
reg_addr[4:0], //6-2
|
||||
2'b0}; //1-0
|
||||
|
||||
// constructing fetch packet
|
||||
emesh2packet #(.AW(AW))
|
||||
e2p (//outputs
|
||||
.packet_out (fetch_packet[PW-1:0]),
|
||||
//inputs
|
||||
.write_out (1'b0),
|
||||
.datamode_out (2'b11),
|
||||
.ctrlmode_out (5'b0),
|
||||
.dstaddr_out ({{(AW-16){1'b0}},fetch_addr[15:0]}),
|
||||
.data_out ({(AW){1'b0}}),
|
||||
.srcaddr_out (srcaddr_out[AW-1:0]));
|
||||
|
||||
assign update = ~wait_in &
|
||||
(master_active | access_in);
|
||||
|
||||
endmodule // edma_ctrl
|
||||
// Local Variables:
|
||||
// verilog-library-directories:("." "../hdl" "../../common/hdl" "../../emesh/hdl")
|
||||
// End:
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// The MIT License (MIT) //
|
||||
|
Loading…
x
Reference in New Issue
Block a user