//=======================================================================
|
//=======================================================================
|
// Project Monophony
|
// Project Monophony
|
// Wire-Frame 3D Graphics Accelerator IP Core
|
// Wire-Frame 3D Graphics Accelerator IP Core
|
//
|
//
|
// File:
|
// File:
|
// fm_dispatch_dma.v
|
// fm_dispatch_dma.v
|
//
|
//
|
// Abstract:
|
// Abstract:
|
// DMA controller sequencer
|
// DMA controller sequencer
|
//
|
//
|
// Author:
|
// Author:
|
// Kenji Ishimaru (info.wf3d@gmail.com)
|
// Kenji Ishimaru (info.info.wf3d@gmail.com)
|
//
|
//
|
//======================================================================
|
//======================================================================
|
//
|
//
|
// Copyright (c) 2016, Kenji Ishimaru
|
// Copyright (c) 2016, Kenji Ishimaru
|
// All rights reserved.
|
// All rights reserved.
|
//
|
//
|
// Redistribution and use in source and binary forms, with or without
|
// Redistribution and use in source and binary forms, with or without
|
// modification, are permitted provided that the following conditions are met:
|
// modification, are permitted provided that the following conditions are met:
|
//
|
//
|
// -Redistributions of source code must retain the above copyright notice,
|
// -Redistributions of source code must retain the above copyright notice,
|
// this list of conditions and the following disclaimer.
|
// this list of conditions and the following disclaimer.
|
// -Redistributions in binary form must reproduce the above copyright notice,
|
// -Redistributions in binary form must reproduce the above copyright notice,
|
// this list of conditions and the following disclaimer in the documentation
|
// this list of conditions and the following disclaimer in the documentation
|
// and/or other materials provided with the distribution.
|
// and/or other materials provided with the distribution.
|
//
|
//
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
//
|
//
|
// Revision History
|
// Revision History
|
|
|
module fm_dispatch_dma (
|
module fm_dispatch_dma (
|
clk_core,
|
clk_core,
|
rst_x,
|
rst_x,
|
// system port
|
// system port
|
i_dma_start,
|
i_dma_start,
|
i_dma_mode,
|
i_dma_mode,
|
o_dma_end,
|
o_dma_end,
|
i_dma_top_address0,
|
i_dma_top_address0,
|
i_dma_top_address1,
|
i_dma_top_address1,
|
i_dma_top_address2,
|
i_dma_top_address2,
|
i_dma_top_address3,
|
i_dma_top_address3,
|
i_dma_length,
|
i_dma_length,
|
i_dma_be,
|
i_dma_be,
|
i_dma_wd0,
|
i_dma_wd0,
|
i_dma_wd1,
|
i_dma_wd1,
|
// memory port
|
// memory port
|
o_req,
|
o_req,
|
o_wr,
|
o_wr,
|
o_adrs,
|
o_adrs,
|
o_len,
|
o_len,
|
i_ack,
|
i_ack,
|
o_strw,
|
o_strw,
|
o_be,
|
o_be,
|
o_wd,
|
o_wd,
|
i_ackw
|
i_ackw
|
);
|
);
|
`include "polyphony_params.v"
|
`include "polyphony_params.v"
|
////////////////////////////
|
////////////////////////////
|
// Parameter definition
|
// Parameter definition
|
////////////////////////////
|
////////////////////////////
|
parameter P_IDLE = 3'h0;
|
parameter P_IDLE = 3'h0;
|
parameter P_SETUP = 3'h1;
|
parameter P_SETUP = 3'h1;
|
parameter P_REQ = 3'h2;
|
parameter P_REQ = 3'h2;
|
parameter P_DOUT = 3'h3;
|
parameter P_DOUT = 3'h3;
|
parameter P_NEXT = 3'h4;
|
parameter P_NEXT = 3'h4;
|
//////////////////////////////////
|
//////////////////////////////////
|
// I/O port definition
|
// I/O port definition
|
//////////////////////////////////
|
//////////////////////////////////
|
input clk_core;
|
input clk_core;
|
input rst_x;
|
input rst_x;
|
// system port
|
// system port
|
input i_dma_start;
|
input i_dma_start;
|
input [3:0] i_dma_mode;
|
input [3:0] i_dma_mode;
|
output o_dma_end;
|
output o_dma_end;
|
input [19:0] i_dma_top_address0; // 32w:bit[29:10]
|
input [19:0] i_dma_top_address0; // 32w:bit[29:10]
|
input [19:0] i_dma_top_address1;
|
input [19:0] i_dma_top_address1;
|
input [19:0] i_dma_top_address2;
|
input [19:0] i_dma_top_address2;
|
input [19:0] i_dma_top_address3;
|
input [19:0] i_dma_top_address3;
|
input [17:0] i_dma_length;
|
input [17:0] i_dma_length;
|
input [3:0] i_dma_be;
|
input [3:0] i_dma_be;
|
input [31:0] i_dma_wd0;
|
input [31:0] i_dma_wd0;
|
input [31:0] i_dma_wd1;
|
input [31:0] i_dma_wd1;
|
// memory port
|
// memory port
|
output o_req;
|
output o_req;
|
output o_wr;
|
output o_wr;
|
output [P_IB_ADDR_WIDTH-1:0] o_adrs;
|
output [P_IB_ADDR_WIDTH-1:0] o_adrs;
|
output [P_IB_LEN_WIDTH-1:0] o_len;
|
output [P_IB_LEN_WIDTH-1:0] o_len;
|
input i_ack;
|
input i_ack;
|
output o_strw;
|
output o_strw;
|
output [P_IB_BE_WIDTH-1:0] o_be;
|
output [P_IB_BE_WIDTH-1:0] o_be;
|
output [P_IB_DATA_WIDTH-1:0] o_wd;
|
output [P_IB_DATA_WIDTH-1:0] o_wd;
|
input i_ackw;
|
input i_ackw;
|
|
|
//////////////////////////////////
|
//////////////////////////////////
|
// reg
|
// reg
|
//////////////////////////////////
|
//////////////////////////////////
|
reg [2:0] r_state;
|
reg [2:0] r_state;
|
reg [P_IB_ADDR_WIDTH-1:0] r_adrs;
|
reg [P_IB_ADDR_WIDTH-1:0] r_adrs;
|
reg [17:0] r_length; // 32bits length
|
reg [17:0] r_length; // 32bits length
|
reg [4:0] r_len; // 32bits or 64bits
|
reg [4:0] r_len; // 32bits or 64bits
|
reg [4:0] r_cnt;
|
reg [4:0] r_cnt;
|
reg [3:0] r_dma_kind;
|
reg [3:0] r_dma_kind;
|
|
|
//////////////////////////////////
|
//////////////////////////////////
|
// wire
|
// wire
|
//////////////////////////////////
|
//////////////////////////////////
|
`ifdef PP_BUSWIDTH_64
|
`ifdef PP_BUSWIDTH_64
|
wire [5:0] w_next_len; // 32bits or 64bits
|
wire [5:0] w_next_len; // 32bits or 64bits
|
`else
|
`else
|
wire [4:0] w_next_len; // 32bits or 64bits
|
wire [4:0] w_next_len; // 32bits or 64bits
|
`endif
|
`endif
|
wire [17:0] w_remain_length; // 32bits length
|
wire [17:0] w_remain_length; // 32bits length
|
wire w_dma_end;
|
wire w_dma_end;
|
wire [19:0] w_set_address;
|
wire [19:0] w_set_address;
|
wire w_all_dma_end;
|
wire w_all_dma_end;
|
wire w_sel_wd;
|
wire w_sel_wd;
|
wire [3:0] w_next_kind;
|
wire [3:0] w_next_kind;
|
//////////////////////////////////
|
//////////////////////////////////
|
// assign
|
// assign
|
//////////////////////////////////
|
//////////////////////////////////
|
assign w_next_len = f_len(r_length);
|
assign w_next_len = f_len(r_length);
|
assign w_remain_length = r_length - {13'b0,w_next_len};
|
assign w_remain_length = r_length - {13'b0,w_next_len};
|
assign w_set_address = f_adrs(r_dma_kind,
|
assign w_set_address = f_adrs(r_dma_kind,
|
i_dma_top_address0,
|
i_dma_top_address0,
|
i_dma_top_address1,
|
i_dma_top_address1,
|
i_dma_top_address2,
|
i_dma_top_address2,
|
i_dma_top_address3);
|
i_dma_top_address3);
|
assign w_next_kind = f_kind_update(r_dma_kind);
|
assign w_next_kind = f_kind_update(r_dma_kind);
|
assign w_dma_end = (r_length == 18'd0);
|
assign w_dma_end = (r_length == 18'd0);
|
assign w_all_dma_end = (r_dma_kind == 4'b0);
|
assign w_all_dma_end = (r_dma_kind == 4'b0);
|
assign o_dma_end = (r_state == P_SETUP) & w_all_dma_end;
|
assign o_dma_end = (r_state == P_SETUP) & w_all_dma_end;
|
|
|
assign w_sel_wd = f_sel_wd(r_dma_kind);
|
assign w_sel_wd = f_sel_wd(r_dma_kind);
|
assign o_req = (r_state == P_REQ);
|
assign o_req = (r_state == P_REQ);
|
assign o_wr = 1'b1;
|
assign o_wr = 1'b1;
|
assign o_adrs = r_adrs;
|
assign o_adrs = r_adrs;
|
assign o_len = {1'b0,r_len};
|
assign o_len = {1'b0,r_len};
|
assign o_strw = (r_state == P_REQ) | (r_state == P_DOUT);
|
assign o_strw = (r_state == P_REQ) | (r_state == P_DOUT);
|
`ifdef PP_BUSWIDTH_64
|
`ifdef PP_BUSWIDTH_64
|
assign o_be = {i_dma_be,i_dma_be};
|
assign o_be = {i_dma_be,i_dma_be};
|
assign o_wd = (w_sel_wd) ? {i_dma_wd1,i_dma_wd1} : {i_dma_wd0,i_dma_wd0};
|
assign o_wd = (w_sel_wd) ? {i_dma_wd1,i_dma_wd1} : {i_dma_wd0,i_dma_wd0};
|
`else
|
`else
|
assign o_be = i_dma_be;
|
assign o_be = i_dma_be;
|
assign o_wd = (w_sel_wd) ? i_dma_wd1 : i_dma_wd0;
|
assign o_wd = (w_sel_wd) ? i_dma_wd1 : i_dma_wd0;
|
`endif
|
`endif
|
|
|
//////////////////////////////////
|
//////////////////////////////////
|
// always
|
// always
|
//////////////////////////////////
|
//////////////////////////////////
|
|
|
// memory fill/ burst sequence (near interface)
|
// memory fill/ burst sequence (near interface)
|
always @(posedge clk_core or negedge rst_x) begin
|
always @(posedge clk_core or negedge rst_x) begin
|
if (~rst_x) begin
|
if (~rst_x) begin
|
r_len <= 5'b0;
|
r_len <= 5'b0;
|
r_cnt <= 5'b0;
|
r_cnt <= 5'b0;
|
r_state <= P_IDLE;
|
r_state <= P_IDLE;
|
r_adrs <= {P_IB_ADDR_WIDTH{1'b0}};
|
r_adrs <= {P_IB_ADDR_WIDTH{1'b0}};
|
r_length <= 18'd0;
|
r_length <= 18'd0;
|
r_dma_kind <= 4'b0;
|
r_dma_kind <= 4'b0;
|
end else begin
|
end else begin
|
case (r_state)
|
case (r_state)
|
P_IDLE : begin
|
P_IDLE : begin
|
if (i_dma_start) begin // memory fill start (address0)
|
if (i_dma_start) begin // memory fill start (address0)
|
r_length <= i_dma_length;
|
r_length <= i_dma_length;
|
r_cnt <= 5'b1;
|
r_cnt <= 5'b1;
|
r_dma_kind <= i_dma_mode;
|
r_dma_kind <= i_dma_mode;
|
r_state <= P_SETUP;
|
r_state <= P_SETUP;
|
end
|
end
|
end
|
end
|
P_SETUP : begin
|
P_SETUP : begin
|
// decide burst length
|
// decide burst length
|
`ifdef PP_BUSWIDTH_64
|
`ifdef PP_BUSWIDTH_64
|
r_adrs[28:9] <= w_set_address;
|
r_adrs[28:9] <= w_set_address;
|
r_adrs[8:0] <= 9'h0;
|
r_adrs[8:0] <= 9'h0;
|
r_len <= w_next_len[5:1];
|
r_len <= w_next_len[5:1];
|
`else
|
`else
|
r_adrs[29:10] <= w_set_address;
|
r_adrs[29:10] <= w_set_address;
|
r_adrs[9:0] <= 10'h0;
|
r_adrs[9:0] <= 10'h0;
|
r_len <= w_next_len;
|
r_len <= w_next_len;
|
`endif
|
`endif
|
r_length <= w_remain_length;
|
r_length <= w_remain_length;
|
if (w_all_dma_end) begin
|
if (w_all_dma_end) begin
|
r_state <= P_IDLE;
|
r_state <= P_IDLE;
|
end else begin
|
end else begin
|
r_state <= P_REQ;
|
r_state <= P_REQ;
|
end
|
end
|
end
|
end
|
P_REQ : begin
|
P_REQ : begin
|
if (i_ack) begin
|
if (i_ack) begin
|
if (r_len == 1) begin // not burst
|
if (r_len == 1) begin // not burst
|
r_state <= P_NEXT;
|
r_state <= P_NEXT;
|
end else begin
|
end else begin
|
r_state <= P_DOUT;
|
r_state <= P_DOUT;
|
end
|
end
|
r_cnt <= r_cnt + 1'b1;
|
r_cnt <= r_cnt + 1'b1;
|
end
|
end
|
end
|
end
|
P_DOUT : begin
|
P_DOUT : begin
|
if (i_ackw) begin
|
if (i_ackw) begin
|
r_cnt <= r_cnt + 1'b1;
|
r_cnt <= r_cnt + 1'b1;
|
if (r_cnt == r_len) begin
|
if (r_cnt == r_len) begin
|
r_state <= P_NEXT;
|
r_state <= P_NEXT;
|
end
|
end
|
end
|
end
|
end
|
end
|
P_NEXT : begin
|
P_NEXT : begin
|
if (w_dma_end) begin
|
if (w_dma_end) begin
|
r_dma_kind <= w_next_kind;
|
r_dma_kind <= w_next_kind;
|
r_length <= i_dma_length;
|
r_length <= i_dma_length;
|
r_cnt <= 5'd1;
|
r_cnt <= 5'd1;
|
r_state <= P_SETUP;
|
r_state <= P_SETUP;
|
end else begin
|
end else begin
|
r_cnt <= 5'd1;
|
r_cnt <= 5'd1;
|
r_adrs <= r_adrs + r_len;
|
r_adrs <= r_adrs + r_len;
|
`ifdef PP_BUSWIDTH_64
|
`ifdef PP_BUSWIDTH_64
|
r_len <= w_next_len[5:1];
|
r_len <= w_next_len[5:1];
|
`else
|
`else
|
r_len <= w_next_len;
|
r_len <= w_next_len;
|
`endif
|
`endif
|
r_length <= w_remain_length;
|
r_length <= w_remain_length;
|
r_state <= P_REQ;
|
r_state <= P_REQ;
|
end
|
end
|
end
|
end
|
endcase
|
endcase
|
end
|
end
|
end
|
end
|
//////////////////////////////////
|
//////////////////////////////////
|
// function
|
// function
|
//////////////////////////////////
|
//////////////////////////////////
|
`ifdef PP_BUSWIDTH_64
|
`ifdef PP_BUSWIDTH_64
|
function [5:0] f_len; // return per64
|
function [5:0] f_len; // return per64
|
`else
|
`else
|
function [4:0] f_len; // return per32
|
function [4:0] f_len; // return per32
|
`endif
|
`endif
|
input [17:0] c_len; // 32-bit length
|
input [17:0] c_len; // 32-bit length
|
reg cmp;
|
reg cmp;
|
begin
|
begin
|
`ifdef PP_BUSWIDTH_64
|
`ifdef PP_BUSWIDTH_64
|
cmp = |c_len[17:5];
|
cmp = |c_len[17:5];
|
if (cmp) f_len = 6'h20; // c_len > 'h20
|
if (cmp) f_len = 6'h20; // c_len > 'h20
|
else f_len = {1'b0,c_len[4:0]};
|
else f_len = {1'b0,c_len[4:0]};
|
`else
|
`else
|
cmp = |c_len[17:4];
|
cmp = |c_len[17:4];
|
if (cmp) f_len = 5'h10; // c_len > 'h10, 32bits x 16 burst
|
if (cmp) f_len = 5'h10; // c_len > 'h10, 32bits x 16 burst
|
else f_len = {1'b0,c_len[3:0]};
|
else f_len = {1'b0,c_len[3:0]};
|
`endif
|
`endif
|
end
|
end
|
endfunction
|
endfunction
|
|
|
function [19:0] f_adrs;
|
function [19:0] f_adrs;
|
input [3:0] kind;
|
input [3:0] kind;
|
input [19:0] a0;
|
input [19:0] a0;
|
input [19:0] a1;
|
input [19:0] a1;
|
input [19:0] a2;
|
input [19:0] a2;
|
input [19:0] a3;
|
input [19:0] a3;
|
reg cmp;
|
reg cmp;
|
begin
|
begin
|
if (kind[0])f_adrs = a0;
|
if (kind[0])f_adrs = a0;
|
else if (kind[1])f_adrs = a1;
|
else if (kind[1])f_adrs = a1;
|
else if (kind[2])f_adrs = a2;
|
else if (kind[2])f_adrs = a2;
|
else f_adrs = a3;
|
else f_adrs = a3;
|
end
|
end
|
endfunction
|
endfunction
|
|
|
function [4:0] f_kind_update;
|
function [4:0] f_kind_update;
|
input [3:0] kind;
|
input [3:0] kind;
|
reg [3:0] result;
|
reg [3:0] result;
|
integer i;
|
integer i;
|
begin
|
begin
|
if (kind[0]) result = {kind[3:1],1'b0};
|
if (kind[0]) result = {kind[3:1],1'b0};
|
else if (kind[1]) result = {kind[3:2],2'b0};
|
else if (kind[1]) result = {kind[3:2],2'b0};
|
else if (kind[2]) result = {kind[3],3'b0};
|
else if (kind[2]) result = {kind[3],3'b0};
|
else result = 4'b0;
|
else result = 4'b0;
|
f_kind_update = result;
|
f_kind_update = result;
|
end
|
end
|
endfunction
|
endfunction
|
|
|
function f_sel_wd;
|
function f_sel_wd;
|
input [3:0] kind;
|
input [3:0] kind;
|
reg result;
|
reg result;
|
integer i;
|
integer i;
|
begin
|
begin
|
if (kind[0]) result = 1'b0;
|
if (kind[0]) result = 1'b0;
|
else if (kind[1]) result = 1'b0;
|
else if (kind[1]) result = 1'b0;
|
else if (kind[2]) result = 1'b1;
|
else if (kind[2]) result = 1'b1;
|
else result = 1'b1;
|
else result = 1'b1;
|
f_sel_wd = result;
|
f_sel_wd = result;
|
end
|
end
|
endfunction
|
endfunction
|
endmodule
|
endmodule
|
|
|