DMAC - MASTER
#Master
- Master interface를 통해 data를 read/write하기 위한 DMAC 내부 component
#State Diagram
module dmac_master(
clk,
reset_n,
//Master interface
M_req,
M_address,
M_wr,
M_dout,
M_grant,
M_din,
//Inner interface
dmac_opstart,
dmac_opdone,
dmac_opdone_clear,
dmac_state,
fifo_rden,
fifo_dout0_srcaddr,
fifo_dout1_destaddr,
fifo_dout2_datasize,
fifo_data_count
);
input clk;
input reset_n;
//Master interface
output M_req;
output [7:0] M_address;
output M_wr;
output [7:0] M_dout;
input M_grant;
input [7:0] M_din;
//Inner interface
input dmac_opstart;
output dmac_opdone;
input dmac_opdone_clear;
output [2:0] dmac_state;
output fifo_rden;
input [7:0] fifo_dout0_srcaddr, fifo_dout1_destaddr, fifo_dout2_datasize;
input [3:0] fifo_data_count;
//state encoding
parameter IDLE = 3'b000;
parameter DONE = 3'b001;
parameter FIFO_POP = 3'b010;
parameter BUS_REQUEST = 3'b011;
parameter MEMORY_READ = 3'b100;
parameter MEMORY_WRITE = 3'b101;
reg [2:0] state, next_state;
reg [7:0] r_SOURCE_ADDRESS, r_DESTINATION_ADDRESS, r_DATA_SIZE;
reg [7:0] next_SOURCE_ADDRESS, next_DESTINATION_ADDRESS, next_DATA_SIZE;
assign dmac_state = state;
/////////////////////////////////////////////////////////
//state register
/////////////////////////////////////////////////////////
always@(posedge clk or negedge reset_n)
begin
if(reset_n==0) state = IDLE;
else if(reset_n==1) state = next_state;
else state = 3'bxxx;
end
/////////////////////////////////////////////////////////
//next state
/////////////////////////////////////////////////////////
always@(state, dmac_opstart, dmac_opdone_clear, M_grant, next_DATA_SIZE, fifo_data_count)
begin
case(state)
IDLE:begin
if(dmac_opstart==1'b1) next_state = FIFO_POP;
else if(dmac_opstart==1'b0) next_state = IDLE;
else next_state = 3'bxxx;
end
DONE:begin
if(dmac_opdone_clear==1'b1) next_state = IDLE;
else if(dmac_opdone_clear==1'b0) next_state = DONE;
else next_state = 3'bxxx;
end
FIFO_POP:begin
if(next_DATA_SIZE!=8'h00) next_state = BUS_REQUEST;
else if(next_DATA_SIZE==8'h00)begin
if(fifo_data_count > 4'h0) next_state = FIFO_POP;
else if(fifo_data_count == 4'h0) next_state = DONE;
else next_state = 3'bxxx;
end
else next_state = 3'bxxx;
end
BUS_REQUEST:begin
if(M_grant==1'b1) next_state = MEMORY_READ;
else if(M_grant==1'b0) next_state = BUS_REQUEST;
else next_state = 3'bxxx;
end
MEMORY_READ: next_state = MEMORY_WRITE;
MEMORY_WRITE:begin
if(next_DATA_SIZE!=8'h00) next_state = MEMORY_READ;
else if(next_DATA_SIZE==8'h00)begin
if(fifo_data_count > 4'h0) next_state = FIFO_POP;
else if(fifo_data_count == 4'h0) next_state = DONE;
else next_state = 3'bxxx;
end
else next_state = 3'bxxx;
end
default: next_state = 3'bxxx;
endcase
end
assign dmac_opdone =(state==DONE)?1'b1:1'b0;
//About r_SOURCE_ADDRESS register
always@(posedge clk or negedge reset_n)
begin
if(reset_n == 1'b0) r_SOURCE_ADDRESS = 8'h00;
else if(reset_n == 1'b1) r_SOURCE_ADDRESS = next_SOURCE_ADDRESS;
else r_SOURCE_ADDRESS = 8'hxx;
end
//About next_SOURCE_ADDRESS
always@(state, fifo_dout0_srcaddr, r_SOURCE_ADDRESS)
begin
case(state)
FIFO_POP: next_SOURCE_ADDRESS = fifo_dout0_srcaddr;
BUS_REQUEST: next_SOURCE_ADDRESS = r_SOURCE_ADDRESS;
MEMORY_READ: next_SOURCE_ADDRESS = r_SOURCE_ADDRESS;
MEMORY_WRITE: next_SOURCE_ADDRESS = r_SOURCE_ADDRESS+8'h1;
default: next_SOURCE_ADDRESS = 8'h00;
endcase
end
//About r_DESTINATION_ADDRESS register
always@(posedge clk or negedge reset_n)
begin
if(reset_n == 1'b0) r_DESTINATION_ADDRESS = 8'h00;
else if(reset_n == 1'b1) r_DESTINATION_ADDRESS = next_DESTINATION_ADDRESS;
else r_DESTINATION_ADDRESS = 8'hxx;
end
//About next_DESTINATION_ADDRESS
always@(state, fifo_dout1_destaddr, r_DESTINATION_ADDRESS)
begin
case(state)
FIFO_POP: next_DESTINATION_ADDRESS = fifo_dout1_destaddr;
BUS_REQUEST: next_DESTINATION_ADDRESS = r_DESTINATION_ADDRESS;
MEMORY_READ: next_DESTINATION_ADDRESS = r_DESTINATION_ADDRESS;
MEMORY_WRITE: next_DESTINATION_ADDRESS = r_DESTINATION_ADDRESS+8'h1;
default: next_DESTINATION_ADDRESS = 8'h00;
endcase
end
//About r_DATA_SIZE register
always@(posedge clk or negedge reset_n)
begin
if(reset_n == 1'b0) r_DATA_SIZE = 8'h00;
else if(reset_n == 1'b1) r_DATA_SIZE = next_DATA_SIZE;
else r_DATA_SIZE = 8'hxx;
end
//About next_DATA_SIZE
always@(state, fifo_dout2_datasize, r_DATA_SIZE)
begin
case(state)
FIFO_POP: next_DATA_SIZE = fifo_dout2_datasize;
BUS_REQUEST: next_DATA_SIZE = r_DATA_SIZE;
MEMORY_READ: next_DATA_SIZE = r_DATA_SIZE-8'h1;
MEMORY_WRITE: next_DATA_SIZE = r_DATA_SIZE;
default: next_DATA_SIZE = 8'h00;
endcase
end
//About fifo_rden
reg fifo_rden;
always@(next_state)
begin
case(next_state)
FIFO_POP: fifo_rden = 1'b1;
default: fifo_rden = 1'b0;
endcase
end
/////////////////////////////////////////////////////////
//Output logic
/////////////////////////////////////////////////////////
//About M_req
reg M_req;
always@(state)
begin
case(state)
BUS_REQUEST: M_req = 1'b1;
MEMORY_READ: M_req = 1'b1;
MEMORY_WRITE: M_req = 1'b1;
default: M_req = 1'b0;
endcase
end
//About M_address
reg [7:0] M_address;
always@(state, r_SOURCE_ADDRESS, r_DESTINATION_ADDRESS)
begin
case(state)
MEMORY_READ: M_address = r_SOURCE_ADDRESS;
MEMORY_WRITE: M_address = r_DESTINATION_ADDRESS;
default: M_address = 8'h00;
endcase
end
//About M_wr
reg M_wr;
always@(state)
begin
case(state)
MEMORY_READ: M_wr = 1'b0;
MEMORY_WRITE: M_wr = 1'b1;
default: M_wr = 1'b0;
endcase
end
//About M_dout
reg [7:0] M_dout;
always@(state, M_din)
begin
case(state)
MEMORY_WRITE: M_dout = M_din;
default: M_dout = 8'h00;
endcase
end
endmodule