//=======================================================================
|
//=======================================================================
|
// Project Monophony
|
// Project Monophony
|
// Wire-Frame 3D Graphics Accelerator IP Core
|
// Wire-Frame 3D Graphics Accelerator IP Core
|
//
|
//
|
// File:
|
// File:
|
// fm_hvc_dma.v
|
// fm_hvc_dma.v
|
//
|
//
|
// Abstract:
|
// Abstract:
|
// VGA LCD Controller DMAC
|
// VGA LCD Controller DMAC
|
//
|
//
|
// Author:
|
// Author:
|
// Kenji Ishimaru (kenji.ishimaru@prtissimo.com)
|
// Kenji Ishimaru (info.wf3d@gmail.com)
|
//
|
//
|
//======================================================================
|
//======================================================================
|
//
|
//
|
// Copyright (c) 2015, Kenji Ishimaru
|
// Copyright (c) 2015, 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_hvc_dma (
|
module fm_hvc_dma (
|
clk_core,
|
clk_core,
|
rst_x,
|
rst_x,
|
i_color_mode,
|
i_color_mode,
|
i_video_start,
|
i_video_start,
|
i_vsync,
|
i_vsync,
|
i_hsync,
|
i_hsync,
|
i_fb0_offset,
|
i_fb0_offset,
|
i_fb0_ms_offset,
|
|
i_fb1_offset,
|
i_fb1_offset,
|
i_fb1_ms_offset,
|
|
i_front_buffer,
|
i_front_buffer,
|
i_aa_en,
|
|
i_fifo_available,
|
i_fifo_available,
|
o_fifo_available_ack,
|
o_fifo_available_ack,
|
o_vsync,
|
o_vsync,
|
o_vsync_edge,
|
o_vsync_edge,
|
// dram if
|
// dram if
|
o_req,
|
o_req,
|
o_adrs,
|
o_adrs,
|
o_len,
|
o_len,
|
i_ack
|
i_ack
|
);
|
);
|
|
|
////////////////////////////
|
////////////////////////////
|
// Parameter definition
|
// Parameter definition
|
////////////////////////////
|
////////////////////////////
|
parameter P_IDLE = 3'd0;
|
parameter P_IB_ADDR_WIDTH ='d24;
|
parameter P_REQ = 3'd1;
|
parameter P_IB_LEN_WIDTH = 'd6;
|
parameter P_REQ_AA = 3'd2;
|
|
parameter P_WAIT_FIFO_AVL = 3'd3;
|
|
parameter P_WAIT_AVL_FALL = 3'd4;
|
|
|
|
parameter P_BURST_SIZE = 6'd32;
|
localparam P_IDLE = 3'd0;
|
parameter P_BURST_SIZE_H = 6'd16;
|
localparam P_REQ = 3'd1;
|
|
localparam P_REQ_AA = 3'd2;
|
|
localparam P_WAIT_FIFO_AVL = 3'd3;
|
|
localparam P_WAIT_AVL_FALL = 3'd4;
|
|
|
|
`ifdef PP_BUSWIDTH_64
|
|
localparam P_BURST_SIZE = 6'd16;
|
|
localparam P_BURST_SIZE_H = 6'd8;
|
|
`else
|
|
localparam P_BURST_SIZE = 6'd32;
|
|
localparam P_BURST_SIZE_H = 6'd16;
|
|
`endif
|
//////////////////////////////////
|
//////////////////////////////////
|
// I/O port definition
|
// I/O port definition
|
//////////////////////////////////
|
//////////////////////////////////
|
input clk_core;
|
input clk_core;
|
input rst_x;
|
input rst_x;
|
input [1:0] i_color_mode;
|
input [1:0] i_color_mode;
|
input i_video_start;
|
input i_video_start;
|
input i_vsync;
|
input i_vsync;
|
input i_hsync;
|
input i_hsync;
|
|
`ifdef PP_BUSWIDTH_64
|
|
input [11:0] i_fb0_offset;
|
|
input [11:0] i_fb1_offset;
|
|
`else
|
input [6:0] i_fb0_offset;
|
input [6:0] i_fb0_offset;
|
input [3:0] i_fb0_ms_offset;
|
|
input [6:0] i_fb1_offset;
|
input [6:0] i_fb1_offset;
|
input [3:0] i_fb1_ms_offset;
|
`endif
|
input i_front_buffer;
|
input i_front_buffer;
|
input i_aa_en;
|
|
input i_fifo_available;
|
input i_fifo_available;
|
output o_fifo_available_ack;
|
output o_fifo_available_ack;
|
output o_vsync;
|
output o_vsync;
|
output o_vsync_edge;
|
output o_vsync_edge;
|
// dram if
|
// dram if
|
output o_req;
|
output o_req;
|
output [23:0] o_adrs;
|
output [P_IB_ADDR_WIDTH-1:0]
|
output [5:0] o_len; // 32 burst x 10
|
o_adrs;
|
|
output [P_IB_LEN_WIDTH-1:0]
|
|
o_len; // 32 burst x 10
|
input i_ack;
|
input i_ack;
|
|
|
//////////////////////////////////
|
//////////////////////////////////
|
// reg
|
// reg
|
//////////////////////////////////
|
//////////////////////////////////
|
reg [2:0] r_state;
|
reg [2:0] r_state;
|
reg r_req;
|
reg r_req;
|
// reg [13:0] r_cur_adrs_l;
|
`ifdef PP_BUSWIDTH_64
|
|
reg [13:0] r_cur_adrs_l;
|
|
`else
|
reg [12:0] r_cur_adrs_l;
|
reg [12:0] r_cur_adrs_l;
|
|
`endif
|
reg [3:0] r_req_cnt;
|
reg [3:0] r_req_cnt;
|
// syncro register
|
// syncro register
|
reg r_vsync_1z;
|
reg r_vsync_1z;
|
reg r_vsync_2z;
|
reg r_vsync_2z;
|
reg r_vsync_3z;
|
reg r_vsync_3z;
|
|
|
reg r_hsync_1z;
|
reg r_hsync_1z;
|
reg r_hsync_2z;
|
reg r_hsync_2z;
|
reg r_hsync_3z;
|
reg r_hsync_3z;
|
|
|
reg r_fifo_available_1z;
|
reg r_fifo_available_1z;
|
reg r_fifo_available_2z;
|
reg r_fifo_available_2z;
|
reg r_fifo_available_3z;
|
reg r_fifo_available_3z;
|
reg r_fifo_available_ack;
|
reg r_fifo_available_ack;
|
//////////////////////////////////
|
//////////////////////////////////
|
// wire
|
// wire
|
//////////////////////////////////
|
//////////////////////////////////
|
wire w_set_initial_adrs;
|
wire w_set_initial_adrs;
|
wire w_v_rise;
|
wire w_v_rise;
|
wire w_h_start;
|
wire w_h_start;
|
wire w_adrs_inc;
|
wire w_adrs_inc;
|
wire w_line_end;
|
wire w_line_end;
|
wire w_req_cnt_clear;
|
wire w_req_cnt_clear;
|
|
|
|
`ifdef PP_BUSWIDTH_64
|
|
wire [11:0] w_fb_offset;
|
|
wire [11:0] w_offset;
|
|
`else
|
wire [6:0] w_fb_offset;
|
wire [6:0] w_fb_offset;
|
wire [6:0] w_fb_ms_offset;
|
|
wire [6:0] w_offset;
|
wire [6:0] w_offset;
|
|
`endif
|
wire w_hburst;
|
wire w_hburst;
|
//////////////////////////////////
|
//////////////////////////////////
|
// assign
|
// assign
|
//////////////////////////////////
|
//////////////////////////////////
|
assign o_req = r_req;
|
assign o_req = r_req;
|
assign w_hburst = (i_color_mode == 2'd3)&(r_req_cnt == 4'd2);
|
assign w_hburst = (i_color_mode == 2'd3)&(r_req_cnt == 4'd2);
|
assign o_len = (w_hburst) ? P_BURST_SIZE_H : P_BURST_SIZE;
|
assign o_len = (w_hburst) ? P_BURST_SIZE_H : P_BURST_SIZE;
|
assign o_fifo_available_ack = r_fifo_available_ack;
|
assign o_fifo_available_ack = r_fifo_available_ack;
|
|
|
assign w_set_initial_adrs = w_v_rise;
|
assign w_set_initial_adrs = w_v_rise;
|
assign w_adrs_inc = (i_aa_en) ? (r_state == P_REQ_AA) & i_ack:
|
assign w_adrs_inc = (r_state == P_REQ) & i_ack;
|
(r_state == P_REQ) & i_ack;
|
|
|
|
assign w_h_start = i_video_start & r_hsync_2z & !r_hsync_3z; // rise of hsync
|
assign w_h_start = i_video_start & r_hsync_2z & !r_hsync_3z; // rise of hsync
|
assign w_v_rise = r_vsync_2z & !r_vsync_3z; // rising edge of vsync
|
assign w_v_rise = r_vsync_2z & !r_vsync_3z; // rising edge of vsync
|
assign w_line_end = (i_color_mode == 2'd3) ? (r_req_cnt == 4'd3) :// 80 times:
|
assign w_line_end = (i_color_mode == 2'd3) ? (r_req_cnt == 4'd3) :// 80 times, 32burstx2, 16burstx1
|
(i_color_mode == 2'd2) ? (r_req_cnt == 4'd5) :// 160 times
|
(i_color_mode == 2'd2) ? (r_req_cnt == 4'd5) :// 160 times, 32burstx5
|
(r_req_cnt == 4'd10); // 320 times
|
(r_req_cnt == 4'd10); // 320 times, 32burstx10
|
|
// 80 times, 16burstx2, 8burstx1 (64)
|
assign w_req_cnt_clear = (w_line_end & !r_fifo_available_2z &
|
assign w_req_cnt_clear = (w_line_end & !r_fifo_available_2z &
|
(r_state == P_WAIT_AVL_FALL)) |
|
(r_state == P_WAIT_AVL_FALL)) |
|
(w_line_end & (r_state == P_WAIT_FIFO_AVL) & (i_color_mode == 'd3));
|
(w_line_end & (r_state == P_WAIT_FIFO_AVL) & (i_color_mode == 'd3));
|
|
|
// assign o_adrs = {w_offset, r_cur_adrs_l,4'b0}; // w_offset[21:18]
|
`ifdef PP_BUSWIDTH_64
|
assign o_adrs = {w_offset,r_cur_adrs_l,4'b0}; // w_offset[23:17]
|
assign o_adrs = {w_offset, r_cur_adrs_l,3'b0};
|
|
`else
|
|
assign o_adrs = {w_offset, r_cur_adrs_l,4'b0};
|
|
`endif
|
|
|
assign w_fb_offset = (i_front_buffer) ? i_fb1_offset : i_fb0_offset;
|
assign w_fb_offset = (i_front_buffer) ? i_fb1_offset : i_fb0_offset;
|
assign w_fb_ms_offset = (i_front_buffer) ? i_fb1_ms_offset : i_fb0_ms_offset;
|
assign w_offset = w_fb_offset;
|
assign w_offset = (r_state == P_REQ_AA) ? w_fb_ms_offset : w_fb_offset;
|
|
|
|
assign o_vsync = r_vsync_2z;
|
assign o_vsync = r_vsync_2z;
|
assign o_vsync_edge = !r_vsync_2z & r_vsync_3z; // falling edge
|
assign o_vsync_edge = !r_vsync_2z & r_vsync_3z; // falling edge
|
|
|
//////////////////////////////////
|
//////////////////////////////////
|
// always
|
// always
|
//////////////////////////////////
|
//////////////////////////////////
|
// request state
|
// request state
|
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_state <= P_IDLE;
|
r_state <= P_IDLE;
|
r_req <= 1'b0;
|
r_req <= 1'b0;
|
r_fifo_available_ack <= 1'b0;
|
r_fifo_available_ack <= 1'b0;
|
end else begin
|
end else begin
|
case (r_state)
|
case (r_state)
|
P_IDLE: begin
|
P_IDLE: begin
|
if (w_h_start) begin
|
if (w_h_start) begin
|
r_req <= 1'b1;
|
r_req <= 1'b1;
|
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 (i_aa_en) begin
|
|
r_req <= 1'b1;
|
|
r_state <= P_REQ_AA;
|
|
end else begin
|
|
r_req <= 1'b0;
|
|
r_state <= P_WAIT_FIFO_AVL;
|
|
end
|
|
end
|
|
end
|
|
P_REQ_AA: begin
|
|
if (i_ack) begin
|
|
r_req <= 1'b0;
|
r_req <= 1'b0;
|
r_state <= P_WAIT_FIFO_AVL;
|
r_state <= P_WAIT_FIFO_AVL;
|
end
|
end
|
end
|
end
|
P_WAIT_FIFO_AVL: begin
|
P_WAIT_FIFO_AVL: begin
|
if (r_req_cnt < 4'd4) begin
|
if (r_req_cnt < 4'd4) begin
|
if (w_line_end) begin
|
if (w_line_end) begin
|
r_state <= P_IDLE;
|
r_state <= P_IDLE;
|
end else begin
|
end else begin
|
r_req <= 1'b1;
|
r_req <= 1'b1;
|
r_state <= P_REQ;
|
r_state <= P_REQ;
|
end
|
end
|
end else begin
|
end else begin
|
if (r_fifo_available_2z) begin
|
if (r_fifo_available_2z) begin
|
r_fifo_available_ack <= 1'b1;
|
r_fifo_available_ack <= 1'b1;
|
r_state <= P_WAIT_AVL_FALL;
|
r_state <= P_WAIT_AVL_FALL;
|
end
|
end
|
end
|
end
|
end
|
end
|
P_WAIT_AVL_FALL: begin
|
P_WAIT_AVL_FALL: begin
|
if (!r_fifo_available_2z) begin
|
if (!r_fifo_available_2z) begin
|
r_fifo_available_ack <= 1'b0;
|
r_fifo_available_ack <= 1'b0;
|
if (w_line_end) begin
|
if (w_line_end) begin
|
r_state <= P_IDLE;
|
r_state <= P_IDLE;
|
end else begin
|
end else begin
|
r_req <= 1'b1;
|
r_req <= 1'b1;
|
r_state <= P_REQ;
|
r_state <= P_REQ;
|
end
|
end
|
end
|
end
|
end
|
end
|
endcase
|
endcase
|
end
|
end
|
end
|
end
|
|
|
// current address
|
// current address
|
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_cur_adrs_l <= 13'h0; // for simulation
|
r_cur_adrs_l <= 'h0; // for simulation
|
end else begin
|
end else begin
|
if (w_set_initial_adrs) begin
|
if (w_set_initial_adrs) begin
|
r_cur_adrs_l <= 13'h0;
|
r_cur_adrs_l <= 'h0;
|
end else if (w_adrs_inc) begin
|
end else if (w_adrs_inc) begin
|
if (w_hburst)
|
if (w_hburst)
|
r_cur_adrs_l <= r_cur_adrs_l + 1'b1; // same as + 16
|
r_cur_adrs_l <= r_cur_adrs_l + 1'b1; // same as + 16
|
else
|
else
|
r_cur_adrs_l <= r_cur_adrs_l + 2'b10; // same as + 32
|
r_cur_adrs_l <= r_cur_adrs_l + 2'b10; // same as + 32
|
end
|
end
|
end
|
end
|
end
|
end
|
|
|
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_req_cnt <= 4'd0;
|
r_req_cnt <= 4'd0;
|
end else begin
|
end else begin
|
if (w_req_cnt_clear) r_req_cnt <= 4'd0;
|
if (w_req_cnt_clear) r_req_cnt <= 4'd0;
|
else if (w_adrs_inc) r_req_cnt <= r_req_cnt + 1'b1;
|
else if (w_adrs_inc) r_req_cnt <= r_req_cnt + 1'b1;
|
end
|
end
|
end
|
end
|
|
|
// syncro register
|
// syncro register
|
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_vsync_1z <= 1'b1;
|
r_vsync_1z <= 1'b1;
|
r_vsync_2z <= 1'b1;
|
r_vsync_2z <= 1'b1;
|
r_vsync_3z <= 1'b1;
|
r_vsync_3z <= 1'b1;
|
r_hsync_1z <= 1'b1;
|
r_hsync_1z <= 1'b1;
|
r_hsync_2z <= 1'b1;
|
r_hsync_2z <= 1'b1;
|
r_hsync_3z <= 1'b1;
|
r_hsync_3z <= 1'b1;
|
r_fifo_available_1z <= 1'b0;
|
r_fifo_available_1z <= 1'b0;
|
r_fifo_available_2z <= 1'b0;
|
r_fifo_available_2z <= 1'b0;
|
end else begin
|
end else begin
|
r_vsync_1z <= i_vsync;
|
r_vsync_1z <= i_vsync;
|
r_vsync_2z <= r_vsync_1z;
|
r_vsync_2z <= r_vsync_1z;
|
r_vsync_3z <= r_vsync_2z;
|
r_vsync_3z <= r_vsync_2z;
|
r_hsync_1z <= i_hsync;
|
r_hsync_1z <= i_hsync;
|
r_hsync_2z <= r_hsync_1z;
|
r_hsync_2z <= r_hsync_1z;
|
r_hsync_3z <= r_hsync_2z;
|
r_hsync_3z <= r_hsync_2z;
|
r_fifo_available_1z <= i_fifo_available;
|
r_fifo_available_1z <= i_fifo_available;
|
r_fifo_available_2z <= r_fifo_available_1z;
|
r_fifo_available_2z <= r_fifo_available_1z;
|
end
|
end
|
end
|
end
|
|
|
|
|
|
|
endmodule
|
endmodule
|
|
|