OpenCores
URL https://opencores.org/ocsvn/opengfx430/opengfx430/trunk

Subversion Repositories opengfx430

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /opengfx430/trunk
    from Rev 2 to Rev 3
    Reverse comparison

Rev 2 → Rev 3

/core/rtl/verilog/ogfx_gpu_reg.v
0,0 → 1,685
//----------------------------------------------------------------------------
// Copyright (C) 2015 Authors
//
// This source file may be used and distributed without restriction provided
// that this copyright statement is not removed from the file and that any
// derivative work contains the original copyright notice and the associated
// disclaimer.
//
// This source file is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This source is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
// License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this source; if not, write to the Free Software Foundation,
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
//----------------------------------------------------------------------------
//
// *File Name: ogfx_gpu_reg.v
//
// *Module Description:
// Configuration registers of the Graphic-Processing unit
//
// *Author(s):
// - Olivier Girard, olgirard@gmail.com
//
//----------------------------------------------------------------------------
// $Rev$
// $LastChangedBy$
// $LastChangedDate$
//----------------------------------------------------------------------------
`ifdef OGFX_NO_INCLUDE
`else
`include "openGFX430_defines.v"
`endif
 
module ogfx_gpu_reg (
 
// OUTPUTs
cfg_dst_px_addr_o, // Destination pixel address configuration
cfg_dst_cl_swp_o, // Destination Column/Line-Swap configuration
cfg_dst_x_swp_o, // Destination X-Swap configuration
cfg_dst_y_swp_o, // Destination Y-Swap configuration
cfg_fill_color_o, // Fill color (for rectangle fill operation)
cfg_pix_op_sel_o, // Pixel operation to be performed during the copy
cfg_rec_width_o, // Rectangle width configuration
cfg_rec_height_o, // Rectangle height configuration
cfg_src_px_addr_o, // Source pixel address configuration
cfg_src_cl_swp_o, // Source Column/Line-Swap configuration
cfg_src_x_swp_o, // Source X-Swap configuration
cfg_src_y_swp_o, // Source Y-Swap configuration
cfg_transparent_color_o, // Transparent color (for rectangle transparent copy operation)
 
gpu_cmd_done_evt_o, // GPU command done event
gpu_cmd_error_evt_o, // GPU command error event
gpu_get_data_o, // GPU get next data
 
exec_fill_o, // Rectangle fill on going
exec_copy_o, // Rectangle copy on going
exec_copy_trans_o, // Rectangle transparent copy on going
trig_exec_o, // Trigger rectangle execution
 
// INPUTs
mclk, // Main system clock
puc_rst, // Main system reset
 
gpu_data_i, // GPU data
gpu_data_avail_i, // GPU data available
gfx_mode_i, // Video mode (1xx:16bpp / 011:8bpp / 010:4bpp / 001:2bpp / 000:1bpp)
gpu_enable_i, // GPU enable
 
gpu_exec_done_i // GPU execution done
);
 
// OUTPUTs
//=========
output [`APIX_MSB:0] cfg_dst_px_addr_o; // Destination pixel address configuration
output cfg_dst_cl_swp_o; // Destination Column/Line-Swap configuration
output cfg_dst_x_swp_o; // Destination X-Swap configuration
output cfg_dst_y_swp_o; // Destination Y-Swap configuration
output [15:0] cfg_fill_color_o; // Fill color (for rectangle fill operation)
output [3:0] cfg_pix_op_sel_o; // Pixel operation to be performed during the copy
output [`LPIX_MSB:0] cfg_rec_width_o; // Rectangle width configuration
output [`LPIX_MSB:0] cfg_rec_height_o; // Rectangle height configuration
output [`APIX_MSB:0] cfg_src_px_addr_o; // Source pixel address configuration
output cfg_src_cl_swp_o; // Source Column/Line-Swap configuration
output cfg_src_x_swp_o; // Source X-Swap configuration
output cfg_src_y_swp_o; // Source Y-Swap configuration
output [15:0] cfg_transparent_color_o; // Transparent color (for rectangle transparent copy operation)
 
output gpu_cmd_done_evt_o; // GPU command done event
output gpu_cmd_error_evt_o; // GPU command error event
output gpu_get_data_o; // GPU get next data
 
output exec_fill_o; // Rectangle fill on going
output exec_copy_o; // Rectangle copy on going
output exec_copy_trans_o; // Rectangle transparent copy on going
output trig_exec_o; // Trigger rectangle execution
 
// INPUTs
//=========
input mclk; // Main system clock
input puc_rst; // Main system reset
 
input [15:0] gpu_data_i; // GPU data
input gpu_data_avail_i; // GPU data available
input [2:0] gfx_mode_i; // Video mode (1xx:16bpp / 011:8bpp / 010:4bpp / 001:2bpp / 000:1bpp)
input gpu_enable_i; // GPU enable
 
input gpu_exec_done_i; // GPU execution done
 
//=============================================================================
// 1) WIRE, REGISTERS AND PARAMETER DECLARATION
//=============================================================================
 
// Video modes decoding
wire gfx_mode_1_bpp = (gfx_mode_i == 3'b000);
wire gfx_mode_2_bpp = (gfx_mode_i == 3'b001);
wire gfx_mode_4_bpp = (gfx_mode_i == 3'b010);
wire gfx_mode_8_bpp = (gfx_mode_i == 3'b011);
wire gfx_mode_16_bpp = ~(gfx_mode_8_bpp | gfx_mode_4_bpp | gfx_mode_2_bpp | gfx_mode_1_bpp);
 
// Remaining wires/registers
reg exec_fill_o;
reg exec_copy_o;
reg exec_copy_trans_o;
 
reg [1:0] src_offset_sel;
reg src_x_swp;
reg src_y_swp;
reg src_cl_swp;
reg [3:0] pix_op_sel;
reg [1:0] dst_offset_sel;
reg dst_x_swp;
reg dst_y_swp;
reg dst_cl_swp;
 
reg [3:0] reg_access;
wire [3:0] reg_access_nxt;
 
reg [15:0] fill_color;
reg [`LPIX_MSB:0] rec_width;
reg [`LPIX_MSB:0] rec_height;
wire [`APIX_MSB:0] src_px_addr;
wire [`APIX_MSB:0] src_px_addr_align;
wire [`APIX_MSB:0] dst_px_addr;
wire [`APIX_MSB:0] dst_px_addr_align;
wire [`APIX_MSB:0] of0_addr;
wire [`APIX_MSB:0] of1_addr;
wire [`APIX_MSB:0] of2_addr;
wire [`APIX_MSB:0] of3_addr;
reg [15:0] transparent_color;
 
wire [`APIX_MSB:0] src_offset_addr;
wire [`APIX_MSB:0] dst_offset_addr;
 
 
//=============================================================================
// 2) GPU COMMAND STATE MACHINE
//=============================================================================
//
// EXEC_FILL - Execute rectangle fill command
// {2'b00, reserved<4:0>, pxop[3:0], dst_offset[1:0], dst_X-Swp, dst_Y-Swp, dst_CL-Swp}
// {fill_color[15:0]}
//
// EXEC_COPY - Execute rectangle copy command
// {2'b01, src_offset[1:0], src_X-Swp, src_Y-Swp, src_CL-Swp, pxop[3:0], dst_offset[1:0], dst_X-Swp, dst_Y-Swp, dst_CL-Swp}
//
// EXEC_COPY_TRANS - Execute rectangle copy with transparency command
// {2'b10, src_offset[1:0], src_X-Swp, src_Y-Swp, src_CL-Swp, pxop[3:0], dst_offset[1:0], dst_X-Swp, dst_Y-Swp, dst_CL-Swp}
//
// REC_WIDTH - Set rectangle width
// {4'b1100, width[11:0]}
//
// REC_HEIGHT - Set rectangle height
// {4'b1101, height[11:0]}
//
// SRC_PX_ADDR - Set source address
// {4'b1111, 2'b10, 10'b0000000000}
// {addr[31:16] }
// {addr[15:0] }
//
// DST_PX_ADDR - Set destination address
// {4'b1111, 2'b10, 10'b0000000001}
// {addr[31:16] }
// {addr[15:0] }
//
// OF0_ADDR - Set address offset 0
// {4'b1111, 2'b10, 10'b0000010000}
// {addr[31:16] }
// {addr[15:0] }
//
// OF1_ADDR - Set address offset 1
// {4'b1111, 2'b10, 10'b0000010001}
// {addr[31:16] }
// {addr[15:0] }
//
// OF2_ADDR - Set address offset 2
// {4'b1111, 2'b10, 10'b0000010010}
// {addr[31:16] }
// {addr[15:0] }
//
// OF3_ADDR - Set address offset 3
// {4'b1111, 2'b10, 10'b0000010011}
// {addr[31:16] }
// {addr[15:0] }
//
// SET_FILL - Set fill color
// {4'b1111, 2'b01, 10'b0000100000}
// {fill_color[15:0] }
//
// SET_TRANSPARENT - Set transparent color
// {4'b1111, 2'b01, 10'b0000100001}
// {transparent_color[15:0] }
//
//-----------------------------------------------------------------------------
 
// State definition
parameter CMD_WAIT = 4'h0;
parameter CMD_READ = 4'h1;
parameter DATA1B_WAIT = 4'h2;
parameter DATA1B_READ = 4'h3;
parameter DATA2B1_WAIT = 4'h4;
parameter DATA2B1_READ = 4'h5;
parameter DATA2B2_WAIT = 4'h6;
parameter DATA2B2_READ = 4'h7;
parameter EXEC_START = 4'h8;
parameter EXEC = 4'h9;
parameter ERROR = 4'hA;
 
// State machine
reg [3:0] gpu_state;
reg [3:0] gpu_state_nxt;
 
// Arcs control
wire cmd_available = gpu_data_avail_i;
 
wire cmd_not_valid = ((gpu_data_i[15:14]!= `OP_EXEC_FILL ) &
(gpu_data_i[15:14]!= `OP_EXEC_COPY ) &
(gpu_data_i[15:14]!= `OP_EXEC_COPY_TRANS) &
(gpu_data_i[15:12]!= `OP_REC_WIDTH ) &
(gpu_data_i[15:12]!= `OP_REC_HEIGHT ) &
(gpu_data_i[15:0] != `OP_SRC_PX_ADDR ) &
(gpu_data_i[15:0] != `OP_DST_PX_ADDR ) &
(gpu_data_i[15:0] != `OP_OF0_ADDR ) &
(gpu_data_i[15:0] != `OP_OF1_ADDR ) &
(gpu_data_i[15:0] != `OP_OF2_ADDR ) &
(gpu_data_i[15:0] != `OP_OF3_ADDR ) &
(gpu_data_i[15:0] != `OP_SET_FILL ) &
(gpu_data_i[15:0] != `OP_SET_TRANSPARENT));
 
wire cmd_has_1b_data = (gpu_data_i[15:14]== `OP_EXEC_FILL ) |
(gpu_data_i[15:0] == `OP_SET_FILL ) |
(gpu_data_i[15:0] == `OP_SET_TRANSPARENT);
 
wire cmd_has_2b_data = (gpu_data_i[15:0] == `OP_SRC_PX_ADDR ) |
(gpu_data_i[15:0] == `OP_DST_PX_ADDR ) |
(gpu_data_i[15:0] == `OP_OF0_ADDR ) |
(gpu_data_i[15:0] == `OP_OF1_ADDR ) |
(gpu_data_i[15:0] == `OP_OF2_ADDR ) |
(gpu_data_i[15:0] == `OP_OF3_ADDR );
 
wire cmd_has_exec = exec_fill_o | exec_copy_o | exec_copy_trans_o;
 
wire data_available = gpu_data_avail_i;
 
 
// State transition
always @(gpu_state or cmd_available or cmd_not_valid or cmd_has_1b_data or cmd_has_2b_data or cmd_has_exec or data_available or gpu_exec_done_i)
case (gpu_state)
CMD_WAIT : gpu_state_nxt = cmd_available ? CMD_READ : CMD_WAIT ;
CMD_READ : gpu_state_nxt = cmd_not_valid ? ERROR :
cmd_has_1b_data ? DATA1B_WAIT :
cmd_has_2b_data ? DATA2B1_WAIT :
cmd_has_exec ? EXEC_START : CMD_WAIT ;
 
DATA1B_WAIT : gpu_state_nxt = data_available ? DATA1B_READ : DATA1B_WAIT ;
DATA1B_READ : gpu_state_nxt = cmd_has_exec ? EXEC_START : CMD_WAIT ;
 
DATA2B1_WAIT : gpu_state_nxt = data_available ? DATA2B1_READ : DATA2B1_WAIT ;
DATA2B1_READ : gpu_state_nxt = DATA2B2_WAIT ;
 
DATA2B2_WAIT : gpu_state_nxt = data_available ? DATA2B2_READ : DATA2B2_WAIT ;
DATA2B2_READ : gpu_state_nxt = cmd_has_exec ? EXEC_START : CMD_WAIT ;
 
EXEC_START : gpu_state_nxt = gpu_exec_done_i ? CMD_WAIT : EXEC ;
EXEC : gpu_state_nxt = gpu_exec_done_i ? CMD_WAIT : EXEC ;
ERROR : gpu_state_nxt = ERROR ;
// pragma coverage off
default : gpu_state_nxt = CMD_WAIT ;
// pragma coverage on
endcase
 
 
// State machine
always @(posedge mclk or posedge puc_rst)
if (puc_rst) gpu_state <= CMD_WAIT;
else if (~gpu_enable_i) gpu_state <= CMD_WAIT;
else gpu_state <= gpu_state_nxt;
 
 
// Event generation, fifo data request
assign gpu_cmd_done_evt_o = (gpu_state!=ERROR) & (gpu_state!=CMD_WAIT) & (gpu_state_nxt==CMD_WAIT);
assign gpu_cmd_error_evt_o = (gpu_state==ERROR);
assign gpu_get_data_o = (gpu_state==CMD_READ) | (gpu_state==DATA1B_READ) | (gpu_state==DATA2B1_READ) | (gpu_state==DATA2B2_READ);
 
// Execution triggers
assign trig_exec_o = (exec_fill_o |
exec_copy_o |
exec_copy_trans_o) & (gpu_state==EXEC_START);
 
 
//=============================================================================
// 3) CONFIGURATION REGISTERS
//=============================================================================
 
// Detect execution commands
always @(posedge mclk or posedge puc_rst)
if (puc_rst) exec_fill_o <= 1'b0;
else if ((gpu_state==CMD_WAIT) & cmd_available) exec_fill_o <= (gpu_data_i[15:14]==`OP_EXEC_FILL);
else if ((gpu_state_nxt==CMD_WAIT) ) exec_fill_o <= 1'b0;
 
always @(posedge mclk or posedge puc_rst)
if (puc_rst) exec_copy_o <= 1'b0;
else if ((gpu_state==CMD_WAIT) & cmd_available) exec_copy_o <= (gpu_data_i[15:14]==`OP_EXEC_COPY);
else if ((gpu_state_nxt==CMD_WAIT) ) exec_copy_o <= 1'b0;
 
always @(posedge mclk or posedge puc_rst)
if (puc_rst) exec_copy_trans_o <= 1'b0;
else if ((gpu_state==CMD_WAIT) & cmd_available) exec_copy_trans_o <= (gpu_data_i[15:14]==`OP_EXEC_COPY_TRANS);
else if ((gpu_state_nxt==CMD_WAIT) ) exec_copy_trans_o <= 1'b0;
 
// Detect register accesses
parameter REG_EXEC_FILL = 4'h1;
parameter REG_REC_WIDTH = 4'h2;
parameter REG_REC_HEIGHT = 4'h3;
parameter REG_SRC_PX_ADDR = 4'h4;
parameter REG_DST_PX_ADDR = 4'h5;
parameter REG_OF0_ADDR = 4'h6;
parameter REG_OF1_ADDR = 4'h7;
parameter REG_OF2_ADDR = 4'h8;
parameter REG_OF3_ADDR = 4'h9;
parameter REG_SET_FILL = 4'hA;
parameter REG_SET_TRANSPARENT = 4'hB;
 
assign reg_access_nxt = ({4{gpu_data_i[15:14]== `OP_EXEC_FILL }} & REG_EXEC_FILL ) |
({4{gpu_data_i[15:12]== `OP_REC_WIDTH }} & REG_REC_WIDTH ) |
({4{gpu_data_i[15:12]== `OP_REC_HEIGHT }} & REG_REC_HEIGHT ) |
({4{gpu_data_i[15:0] == `OP_SRC_PX_ADDR }} & REG_SRC_PX_ADDR ) |
({4{gpu_data_i[15:0] == `OP_DST_PX_ADDR }} & REG_DST_PX_ADDR ) |
({4{gpu_data_i[15:0] == `OP_OF0_ADDR }} & REG_OF0_ADDR ) |
({4{gpu_data_i[15:0] == `OP_OF1_ADDR }} & REG_OF1_ADDR ) |
({4{gpu_data_i[15:0] == `OP_OF2_ADDR }} & REG_OF2_ADDR ) |
({4{gpu_data_i[15:0] == `OP_OF3_ADDR }} & REG_OF3_ADDR ) |
({4{gpu_data_i[15:0] == `OP_SET_FILL }} & REG_SET_FILL ) |
({4{gpu_data_i[15:0] == `OP_SET_TRANSPARENT}} & REG_SET_TRANSPARENT) ;
 
always @(posedge mclk or posedge puc_rst)
if (puc_rst) reg_access <= 4'h0;
else if (gpu_state==CMD_READ) reg_access <= reg_access_nxt;
else if (gpu_state_nxt==CMD_WAIT) reg_access <= 4'h0;
 
 
//=============================================================================
// 4) CONFIGURATION REGISTERS
//=============================================================================
 
//------------------------------------------------
// EXECUTION CONFIG Register
//------------------------------------------------
 
wire exec_all_cfg_wr = (exec_fill_o | exec_copy_o | exec_copy_trans_o) & (gpu_state==CMD_READ);
wire exec_src_cfg_wr = ( exec_copy_o | exec_copy_trans_o) & (gpu_state==CMD_READ);
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst)
begin
src_offset_sel <= 2'b00;
src_x_swp <= 1'b0;
src_y_swp <= 1'b0;
src_cl_swp <= 1'b0;
end
else if (exec_src_cfg_wr)
begin
src_offset_sel <= gpu_data_i[13:12];
src_x_swp <= gpu_data_i[11];
src_y_swp <= gpu_data_i[10];
src_cl_swp <= gpu_data_i[9];
end
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst)
begin
pix_op_sel <= 4'b0000;
dst_offset_sel <= 2'b00;
dst_x_swp <= 1'b0;
dst_y_swp <= 1'b0;
dst_cl_swp <= 1'b0;
end
else if (exec_all_cfg_wr)
begin
pix_op_sel <= gpu_data_i[8:5];
dst_offset_sel <= gpu_data_i[4:3];
dst_x_swp <= gpu_data_i[2];
dst_y_swp <= gpu_data_i[1];
dst_cl_swp <= gpu_data_i[0];
end
 
assign cfg_src_x_swp_o = src_x_swp;
assign cfg_src_y_swp_o = src_y_swp;
assign cfg_src_cl_swp_o = src_cl_swp;
assign cfg_pix_op_sel_o = pix_op_sel;
assign cfg_dst_x_swp_o = dst_x_swp;
assign cfg_dst_y_swp_o = dst_y_swp;
assign cfg_dst_cl_swp_o = dst_cl_swp;
 
//------------------------------------------------
// FILL_COLOR Register
//------------------------------------------------
 
wire fill_color_wr = ((reg_access==REG_EXEC_FILL) |
(reg_access==REG_SET_FILL ) ) & (gpu_state==DATA1B_READ);
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) fill_color <= 16'h0000;
else if (fill_color_wr) fill_color <= gpu_data_i;
 
assign cfg_fill_color_o = fill_color;
 
//------------------------------------------------
// REC_WIDTH Register
//------------------------------------------------
 
wire rec_width_wr = (reg_access_nxt==REG_REC_WIDTH) & (gpu_state==CMD_READ);
 
wire [`LPIX_MSB:0] rec_w_h_nxt = (|gpu_data_i[`LPIX_MSB:0]) ? gpu_data_i[`LPIX_MSB:0] :
{{`LPIX_MSB{1'b0}}, 1'b1};
 
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) rec_width <= {{`LPIX_MSB{1'b0}}, 1'b1};
else if (rec_width_wr) rec_width <= rec_w_h_nxt;
 
assign cfg_rec_width_o = rec_width;
 
//------------------------------------------------
// REC_HEIGHT Register
//------------------------------------------------
 
wire rec_height_wr = (reg_access_nxt==REG_REC_HEIGHT) & (gpu_state==CMD_READ);
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) rec_height <= {{`LPIX_MSB{1'b0}}, 1'b1};
else if (rec_height_wr) rec_height <= rec_w_h_nxt;
 
assign cfg_rec_height_o = rec_height;
 
//------------------------------------------------
// SRC_PX_ADDR_HI Register
//------------------------------------------------
`ifdef VRAM_BIGGER_4_KW
reg [`APIX_HI_MSB:0] src_px_addr_hi;
 
wire src_px_addr_hi_wr = (reg_access==REG_SRC_PX_ADDR) & (gpu_state==DATA2B1_READ);
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) src_px_addr_hi <= {`APIX_HI_MSB+1{1'b0}};
else if (src_px_addr_hi_wr) src_px_addr_hi <= gpu_data_i[`APIX_HI_MSB:0];
`endif
 
//------------------------------------------------
// SRC_PX_ADDR_LO Register
//------------------------------------------------
reg [`APIX_LO_MSB:0] src_px_addr_lo;
 
wire src_px_addr_lo_wr = (reg_access==REG_SRC_PX_ADDR) & (gpu_state==DATA2B2_READ);
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) src_px_addr_lo <= {`APIX_LO_MSB+1{1'b0}};
else if (src_px_addr_lo_wr) src_px_addr_lo <= gpu_data_i[`APIX_LO_MSB:0];
 
`ifdef VRAM_BIGGER_4_KW
assign src_px_addr = {src_px_addr_hi[`APIX_HI_MSB:0], src_px_addr_lo};
`else
assign src_px_addr = {src_px_addr_lo[`APIX_LO_MS:0]};
`endif
 
assign src_px_addr_align = src_px_addr + src_offset_addr;
assign cfg_src_px_addr_o = {`APIX_MSB+1{gfx_mode_1_bpp }} & {src_px_addr_align[`APIX_MSB:0] } |
{`APIX_MSB+1{gfx_mode_2_bpp }} & {src_px_addr_align[`APIX_MSB-1:0], 1'b0 } |
{`APIX_MSB+1{gfx_mode_4_bpp }} & {src_px_addr_align[`APIX_MSB-2:0], 2'b00 } |
{`APIX_MSB+1{gfx_mode_8_bpp }} & {src_px_addr_align[`APIX_MSB-3:0], 3'b000 } |
{`APIX_MSB+1{gfx_mode_16_bpp}} & {src_px_addr_align[`APIX_MSB-4:0], 4'b0000} ;
 
//------------------------------------------------
// DST_PX_ADDR_HI Register
//------------------------------------------------
`ifdef VRAM_BIGGER_4_KW
reg [`APIX_HI_MSB:0] dst_px_addr_hi;
 
wire dst_px_addr_hi_wr = (reg_access==REG_DST_PX_ADDR) & (gpu_state==DATA2B1_READ);
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) dst_px_addr_hi <= {`APIX_HI_MSB+1{1'b0}};
else if (dst_px_addr_hi_wr) dst_px_addr_hi <= gpu_data_i[`APIX_HI_MSB:0];
`endif
 
//------------------------------------------------
// DST_PX_ADDR_LO Register
//------------------------------------------------
reg [`APIX_LO_MSB:0] dst_px_addr_lo;
 
wire dst_px_addr_lo_wr = (reg_access==REG_DST_PX_ADDR) & (gpu_state==DATA2B2_READ);
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) dst_px_addr_lo <= {`APIX_LO_MSB+1{1'b0}};
else if (dst_px_addr_lo_wr) dst_px_addr_lo <= gpu_data_i[`APIX_LO_MSB:0];
 
`ifdef VRAM_BIGGER_4_KW
assign dst_px_addr = {dst_px_addr_hi[`APIX_HI_MSB:0], dst_px_addr_lo};
`else
assign dst_px_addr = {dst_px_addr_lo[`APIX_LO_MS:0]};
`endif
 
assign dst_px_addr_align = dst_px_addr + dst_offset_addr;
assign cfg_dst_px_addr_o = {`APIX_MSB+1{gfx_mode_1_bpp }} & {dst_px_addr_align[`APIX_MSB:0] } |
{`APIX_MSB+1{gfx_mode_2_bpp }} & {dst_px_addr_align[`APIX_MSB-1:0], 1'b0 } |
{`APIX_MSB+1{gfx_mode_4_bpp }} & {dst_px_addr_align[`APIX_MSB-2:0], 2'b00 } |
{`APIX_MSB+1{gfx_mode_8_bpp }} & {dst_px_addr_align[`APIX_MSB-3:0], 3'b000 } |
{`APIX_MSB+1{gfx_mode_16_bpp}} & {dst_px_addr_align[`APIX_MSB-4:0], 4'b0000} ;
 
//------------------------------------------------
// OF0_ADDR_HI Register
//------------------------------------------------
`ifdef VRAM_BIGGER_4_KW
reg [`APIX_HI_MSB:0] of0_addr_hi;
 
wire of0_addr_hi_wr = (reg_access==REG_OF0_ADDR) & (gpu_state==DATA2B1_READ);
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) of0_addr_hi <= {`APIX_HI_MSB+1{1'b0}};
else if (of0_addr_hi_wr) of0_addr_hi <= gpu_data_i[`APIX_HI_MSB:0];
`endif
 
//------------------------------------------------
// OF0_ADDR_LO Register
//------------------------------------------------
reg [`APIX_LO_MSB:0] of0_addr_lo;
 
wire of0_addr_lo_wr = (reg_access==REG_OF0_ADDR) & (gpu_state==DATA2B2_READ);
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) of0_addr_lo <= {`APIX_LO_MSB+1{1'b0}};
else if (of0_addr_lo_wr) of0_addr_lo <= gpu_data_i[`APIX_LO_MSB:0];
 
`ifdef VRAM_BIGGER_4_KW
assign of0_addr = {of0_addr_hi[`APIX_HI_MSB:0], of0_addr_lo};
`else
assign of0_addr = {of0_addr_lo[`APIX_LO_MS:0]};
`endif
 
//------------------------------------------------
// OF1_ADDR_HI Register
//------------------------------------------------
`ifdef VRAM_BIGGER_4_KW
reg [`APIX_HI_MSB:0] of1_addr_hi;
 
wire of1_addr_hi_wr = (reg_access==REG_OF1_ADDR) & (gpu_state==DATA2B1_READ);
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) of1_addr_hi <= {`APIX_HI_MSB+1{1'b0}};
else if (of1_addr_hi_wr) of1_addr_hi <= gpu_data_i[`APIX_HI_MSB:0];
`endif
 
//------------------------------------------------
// OF1_ADDR_LO Register
//------------------------------------------------
reg [`APIX_LO_MSB:0] of1_addr_lo;
 
wire of1_addr_lo_wr = (reg_access==REG_OF1_ADDR) & (gpu_state==DATA2B2_READ);
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) of1_addr_lo <= {`APIX_LO_MSB+1{1'b0}};
else if (of1_addr_lo_wr) of1_addr_lo <= gpu_data_i[`APIX_LO_MSB:0];
 
`ifdef VRAM_BIGGER_4_KW
assign of1_addr = {of1_addr_hi[`APIX_HI_MSB:0], of1_addr_lo};
`else
assign of1_addr = {of1_addr_lo[`APIX_LO_MS:0]};
`endif
 
//------------------------------------------------
// OF2_ADDR_HI Register
//------------------------------------------------
`ifdef VRAM_BIGGER_4_KW
reg [`APIX_HI_MSB:0] of2_addr_hi;
 
wire of2_addr_hi_wr = (reg_access==REG_OF2_ADDR) & (gpu_state==DATA2B1_READ);
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) of2_addr_hi <= {`APIX_HI_MSB+1{1'b0}};
else if (of2_addr_hi_wr) of2_addr_hi <= gpu_data_i[`APIX_HI_MSB:0];
`endif
 
//------------------------------------------------
// OF2_ADDR_LO Register
//------------------------------------------------
reg [`APIX_LO_MSB:0] of2_addr_lo;
 
wire of2_addr_lo_wr = (reg_access==REG_OF2_ADDR) & (gpu_state==DATA2B2_READ);
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) of2_addr_lo <= {`APIX_LO_MSB+1{1'b0}};
else if (of2_addr_lo_wr) of2_addr_lo <= gpu_data_i[`APIX_LO_MSB:0];
 
`ifdef VRAM_BIGGER_4_KW
assign of2_addr = {of2_addr_hi[`APIX_HI_MSB:0], of2_addr_lo};
`else
assign of2_addr = {of2_addr_lo[`APIX_LO_MS:0]};
`endif
 
//------------------------------------------------
// OF3_ADDR_HI Register
//------------------------------------------------
`ifdef VRAM_BIGGER_4_KW
reg [`APIX_HI_MSB:0] of3_addr_hi;
 
wire of3_addr_hi_wr = (reg_access==REG_OF3_ADDR) & (gpu_state==DATA2B1_READ);
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) of3_addr_hi <= {`APIX_HI_MSB+1{1'b0}};
else if (of3_addr_hi_wr) of3_addr_hi <= gpu_data_i[`APIX_HI_MSB:0];
`endif
 
//------------------------------------------------
// OF3_ADDR_LO Register
//------------------------------------------------
reg [`APIX_LO_MSB:0] of3_addr_lo;
 
wire of3_addr_lo_wr = (reg_access==REG_OF3_ADDR) & (gpu_state==DATA2B2_READ);
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) of3_addr_lo <= {`APIX_LO_MSB+1{1'b0}};
else if (of3_addr_lo_wr) of3_addr_lo <= gpu_data_i[`APIX_LO_MSB:0];
 
`ifdef VRAM_BIGGER_4_KW
assign of3_addr = {of3_addr_hi[`APIX_HI_MSB:0], of3_addr_lo};
`else
assign of3_addr = {of3_addr_lo[`APIX_LO_MS:0]};
`endif
 
// Offset address selection
assign src_offset_addr = (src_offset_sel==2'h0) ? of0_addr :
(src_offset_sel==2'h1) ? of1_addr :
(src_offset_sel==2'h2) ? of2_addr : of3_addr;
 
assign dst_offset_addr = (dst_offset_sel==2'h0) ? of0_addr :
(dst_offset_sel==2'h1) ? of1_addr :
(dst_offset_sel==2'h2) ? of2_addr : of3_addr;
 
 
//------------------------------------------------
// TRANSPARENT_COLOR Register
//------------------------------------------------
 
wire transparent_color_wr = (reg_access==REG_SET_TRANSPARENT) & (gpu_state==DATA1B_READ);
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) transparent_color <= 16'h0000;
else if (transparent_color_wr) transparent_color <= gpu_data_i;
 
assign cfg_transparent_color_o = transparent_color;
 
endmodule // ogfx_gpu_reg
 
`ifdef OGFX_NO_INCLUDE
`else
`include "openGFX430_undefines.v"
`endif
/core/rtl/verilog/ogfx_gpu.v
0,0 → 1,225
//----------------------------------------------------------------------------
// Copyright (C) 2015 Authors
//
// This source file may be used and distributed without restriction provided
// that this copyright statement is not removed from the file and that any
// derivative work contains the original copyright notice and the associated
// disclaimer.
//
// This source file is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This source is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
// License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this source; if not, write to the Free Software Foundation,
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
//----------------------------------------------------------------------------
//
// *File Name: ogfx_gpu.v
//
// *Module Description:
// Graphic-Processing unit of the graphic controller.
// This block can perform the following hardware
// accelerations:
//
// -
// -
//
// *Author(s):
// - Olivier Girard, olgirard@gmail.com
//
//----------------------------------------------------------------------------
// $Rev$
// $LastChangedBy$
// $LastChangedDate$
//----------------------------------------------------------------------------
`ifdef OGFX_NO_INCLUDE
`else
`include "openGFX430_defines.v"
`endif
 
module ogfx_gpu (
 
// OUTPUTs
gpu_cmd_done_evt_o, // GPU command done event
gpu_cmd_error_evt_o, // GPU command error event
gpu_get_data_o, // GPU get next data
 
vid_ram_addr_o, // Video-RAM address
vid_ram_din_o, // Video-RAM data
vid_ram_wen_o, // Video-RAM write strobe (active low)
vid_ram_cen_o, // Video-RAM chip enable (active low)
 
// INPUTs
mclk, // Main system clock
puc_rst, // Main system reset
 
display_width_i, // Display width
 
gfx_mode_i, // Video mode (1xx:16bpp / 011:8bpp / 010:4bpp / 001:2bpp / 000:1bpp)
 
gpu_data_i, // GPU data
gpu_data_avail_i, // GPU data available
gpu_enable_i, // GPU enable
 
vid_ram_dout_i, // Video-RAM data input
vid_ram_dout_rdy_nxt_i // Video-RAM data output ready during next cycle
);
 
// OUTPUTs
//=========
output gpu_cmd_done_evt_o; // GPU command done event
output gpu_cmd_error_evt_o; // GPU command error event
output gpu_get_data_o; // GPU get next data
 
output [`VRAM_MSB:0] vid_ram_addr_o; // Video-RAM address
output [15:0] vid_ram_din_o; // Video-RAM data
output vid_ram_wen_o; // Video-RAM write strobe (active low)
output vid_ram_cen_o; // Video-RAM chip enable (active low)
 
// INPUTs
//=========
input mclk; // Main system clock
input puc_rst; // Main system reset
 
input [`LPIX_MSB:0] display_width_i; // Display width
 
input [2:0] gfx_mode_i; // Video mode (1xx:16bpp / 011:8bpp / 010:4bpp / 001:2bpp / 000:1bpp)
 
input [15:0] gpu_data_i; // GPU data
input gpu_data_avail_i; // GPU data available
input gpu_enable_i; // GPU enable
 
input [15:0] vid_ram_dout_i; // Video-RAM data input
input vid_ram_dout_rdy_nxt_i; // Video-RAM data output ready during next cycle
 
 
//=============================================================================
// 1) WIRE, REGISTERS AND PARAMETER DECLARATION
//=============================================================================
 
wire exec_fill;
wire exec_copy;
wire exec_copy_trans;
wire trig_exec;
 
wire [`APIX_MSB:0] cfg_dst_px_addr;
wire cfg_dst_cl_swp;
wire cfg_dst_x_swp;
wire cfg_dst_y_swp;
wire [15:0] cfg_fill_color;
wire [3:0] cfg_pix_op_sel;
wire [`LPIX_MSB:0] cfg_rec_width;
wire [`LPIX_MSB:0] cfg_rec_height;
wire [`APIX_MSB:0] cfg_src_px_addr;
wire cfg_src_cl_swp;
wire cfg_src_x_swp;
wire cfg_src_y_swp;
wire [15:0] cfg_transparent_color;
 
wire gpu_exec_done;
 
 
//=============================================================================
// 2) GPU CONGIGURATION & CONTROL REGISTERS
//=============================================================================
 
ogfx_gpu_reg ogfx_gpu_reg_inst (
 
// OUTPUTs
.gpu_cmd_done_evt_o (gpu_cmd_done_evt_o ), // GPU command done event
.gpu_cmd_error_evt_o (gpu_cmd_error_evt_o ), // GPU command error event
.gpu_get_data_o (gpu_get_data_o ), // GPU get next data
 
.exec_fill_o (exec_fill ), // Rectangle fill on going
.exec_copy_o (exec_copy ), // Rectangle copy on going
.exec_copy_trans_o (exec_copy_trans ), // Rectangle transparent copy on going
.trig_exec_o (trig_exec ), // Trigger rectangle execution
 
.cfg_dst_px_addr_o (cfg_dst_px_addr ), // Destination pixel address configuration
.cfg_dst_cl_swp_o (cfg_dst_cl_swp ), // Destination Column/Line-Swap configuration
.cfg_dst_x_swp_o (cfg_dst_x_swp ), // Destination X-Swap configuration
.cfg_dst_y_swp_o (cfg_dst_y_swp ), // Destination Y-Swap configuration
.cfg_fill_color_o (cfg_fill_color ), // Fill color (for rectangle fill operation)
.cfg_pix_op_sel_o (cfg_pix_op_sel ), // Pixel operation to be performed during the copy
.cfg_rec_width_o (cfg_rec_width ), // Rectangle width configuration
.cfg_rec_height_o (cfg_rec_height ), // Rectangle height configuration
.cfg_src_px_addr_o (cfg_src_px_addr ), // Source pixel address configuration
.cfg_src_cl_swp_o (cfg_src_cl_swp ), // Source Column/Line-Swap configuration
.cfg_src_x_swp_o (cfg_src_x_swp ), // Source X-Swap configuration
.cfg_src_y_swp_o (cfg_src_y_swp ), // Source Y-Swap configuration
.cfg_transparent_color_o (cfg_transparent_color ), // Transparent color (for rectangle transparent copy operation)
 
 
// INPUTs
.mclk (mclk ), // Main system clock
.puc_rst (puc_rst ), // Main system reset
 
.gpu_data_i (gpu_data_i ), // GPU data
.gpu_data_avail_i (gpu_data_avail_i ), // GPU data available
.gfx_mode_i (gfx_mode_i ), // Video mode (1xx:16bpp / 011:8bpp / 010:4bpp / 001:2bpp / 000:1bpp)
.gpu_enable_i (gpu_enable_i ), // GPU enable
 
.gpu_exec_done_i (gpu_exec_done ) // GPU execution done
);
 
//=============================================================================
// 3) 2D-DMA
//=============================================================================
 
ogfx_gpu_dma ogfx_gpu_dma_inst (
 
// OUTPUTs
.gpu_exec_done_o (gpu_exec_done ), // GPU execution done
 
.vid_ram_addr_o (vid_ram_addr_o ), // Video-RAM address
.vid_ram_din_o (vid_ram_din_o ), // Video-RAM data
.vid_ram_wen_o (vid_ram_wen_o ), // Video-RAM write strobe (active low)
.vid_ram_cen_o (vid_ram_cen_o ), // Video-RAM chip enable (active low)
 
// INPUTs
.mclk (mclk ), // Main system clock
.puc_rst (puc_rst ), // Main system reset
 
.cfg_dst_px_addr_i (cfg_dst_px_addr ), // Destination pixel address configuration
.cfg_dst_cl_swp_i (cfg_dst_cl_swp ), // Destination Column/Line-Swap configuration
.cfg_dst_x_swp_i (cfg_dst_x_swp ), // Destination X-Swap configuration
.cfg_dst_y_swp_i (cfg_dst_y_swp ), // Destination Y-Swap configuration
.cfg_fill_color_i (cfg_fill_color ), // Fill color (for rectangle fill operation)
.cfg_pix_op_sel_i (cfg_pix_op_sel ), // Pixel operation to be performed during the copy
.cfg_rec_width_i (cfg_rec_width ), // Rectangle width configuration
.cfg_rec_height_i (cfg_rec_height ), // Rectangle height configuration
.cfg_src_px_addr_i (cfg_src_px_addr ), // Source pixel address configuration
.cfg_src_cl_swp_i (cfg_src_cl_swp ), // Source Column/Line-Swap configuration
.cfg_src_x_swp_i (cfg_src_x_swp ), // Source X-Swap configuration
.cfg_src_y_swp_i (cfg_src_y_swp ), // Source Y-Swap configuration
.cfg_transparent_color_i (cfg_transparent_color ), // Transparent color (for rectangle transparent copy operation)
 
.display_width_i (display_width_i ), // Display width
 
.gfx_mode_i (gfx_mode_i ), // Video mode (1xx:16bpp / 011:8bpp / 010:4bpp / 001:2bpp / 000:1bpp)
 
.gpu_enable_i (gpu_enable_i ), // GPU enable
 
.exec_fill_i (exec_fill ), // Rectangle fill on going
.exec_copy_i (exec_copy ), // Rectangle copy on going
.exec_copy_trans_i (exec_copy_trans ), // Rectangle transparent copy on going
.trig_exec_i (trig_exec ), // Trigger rectangle execution
 
.vid_ram_dout_i (vid_ram_dout_i ), // Video-RAM data input
.vid_ram_dout_rdy_nxt_i (vid_ram_dout_rdy_nxt_i) // Video-RAM data output ready during next cycle
);
 
endmodule // ogfx_gpu
 
`ifdef OGFX_NO_INCLUDE
`else
`include "openGFX430_undefines.v"
`endif
/core/rtl/verilog/ogfx_reg_vram_addr.v
0,0 → 1,150
//----------------------------------------------------------------------------
// Copyright (C) 2015 Authors
//
// This source file may be used and distributed without restriction provided
// that this copyright statement is not removed from the file and that any
// derivative work contains the original copyright notice and the associated
// disclaimer.
//
// This source file is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This source is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
// License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this source; if not, write to the Free Software Foundation,
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
//----------------------------------------------------------------------------
//
// *File Name: ogfx_calc_vram_addr.v
//
// *Module Description:
// Compute next Video-Ram address
//
// *Author(s):
// - Olivier Girard, olgirard@gmail.com
//
//----------------------------------------------------------------------------
// $Rev$
// $LastChangedBy$
// $LastChangedDate$
//----------------------------------------------------------------------------
`ifdef OGFX_NO_INCLUDE
`else
`include "openGFX430_defines.v"
`endif
 
module ogfx_reg_vram_addr (
 
// OUTPUTs
vid_ram_addr_nxt_o, // Next Video-RAM address
 
// INPUTs
mclk, // Main system clock
puc_rst, // Main system reset
display_width_i, // Display width
gfx_mode_1_bpp_i, // Graphic mode 1 bpp resolution
gfx_mode_2_bpp_i, // Graphic mode 2 bpp resolution
gfx_mode_4_bpp_i, // Graphic mode 4 bpp resolution
gfx_mode_8_bpp_i, // Graphic mode 8 bpp resolution
gfx_mode_16_bpp_i, // Graphic mode 16 bpp resolution
vid_ram_addr_i, // Video-RAM address
vid_ram_addr_init_i, // Video-RAM address initialization
vid_ram_addr_step_i, // Video-RAM address step
vid_ram_width_i, // Video-RAM width
vid_ram_msk_mode_i, // Video-RAM Mask mode enable
vid_ram_win_mode_i, // Video-RAM Windows mode enable
vid_ram_win_x_swap_i, // Video-RAM X-Swap configuration
vid_ram_win_y_swap_i, // Video-RAM Y-Swap configuration
vid_ram_win_cl_swap_i // Video-RAM CL-Swap configuration
);
 
// OUTPUTs
//=========
output [`APIX_MSB:0] vid_ram_addr_nxt_o; // Next Video-RAM address
 
// INPUTs
//=========
input mclk; // Main system clock
input puc_rst; // Main system reset
input [`LPIX_MSB:0] display_width_i; // Display width
input gfx_mode_1_bpp_i; // Graphic mode 1 bpp resolution
input gfx_mode_2_bpp_i; // Graphic mode 2 bpp resolution
input gfx_mode_4_bpp_i; // Graphic mode 4 bpp resolution
input gfx_mode_8_bpp_i; // Graphic mode 8 bpp resolution
input gfx_mode_16_bpp_i; // Graphic mode 16 bpp resolution
input [`APIX_MSB:0] vid_ram_addr_i; // Video-RAM address
input vid_ram_addr_init_i; // Video-RAM address initialization
input vid_ram_addr_step_i; // Video-RAM address step
input [`LPIX_MSB:0] vid_ram_width_i; // Video-RAM width
input vid_ram_msk_mode_i; // Video-RAM Mask mode enable
input vid_ram_win_mode_i; // Video-RAM Windows mode enable
input vid_ram_win_x_swap_i; // Video-RAM X-Swap configuration
input vid_ram_win_y_swap_i; // Video-RAM Y-Swap configuration
input vid_ram_win_cl_swap_i; // Video-RAM CL-Swap configuration
 
 
//=============================================================================
// 1) PARAMETER DECLARATION
//=============================================================================
reg [`APIX_MSB:0] vid_ram_line_addr;
reg [`LPIX_MSB:0] vid_ram_column_count;
 
// Detect when the current line refresh is done
wire vid_ram_line_done = vid_ram_addr_step_i & (vid_ram_column_count>=(vid_ram_width_i-{{`LPIX_MSB{1'b0}}, 1'b1}));
 
// Compute increment value depending on mask mode
wire [`APIX_MSB:0] plus_one_val = {`APIX_MSB+1{gfx_mode_1_bpp_i & ~vid_ram_msk_mode_i}} & { {{`VRAM_MSB{1'b0}}, 1'b1}, 4'b0000} |
{`APIX_MSB+1{gfx_mode_2_bpp_i & ~vid_ram_msk_mode_i}} & {1'b0, {{`VRAM_MSB{1'b0}}, 1'b1}, 3'b000 } |
{`APIX_MSB+1{gfx_mode_4_bpp_i & ~vid_ram_msk_mode_i}} & {2'b00, {{`VRAM_MSB{1'b0}}, 1'b1}, 2'b00 } |
{`APIX_MSB+1{gfx_mode_8_bpp_i & ~vid_ram_msk_mode_i}} & {3'b000, {{`VRAM_MSB{1'b0}}, 1'b1}, 1'b0 } |
{`APIX_MSB+1{gfx_mode_16_bpp_i | vid_ram_msk_mode_i}} & {4'b0000, {{`VRAM_MSB{1'b0}}, 1'b1} } ;
 
// Mux between initialization value and display width
wire [`LPIX_MSB:0] vid_ram_width_mux = vid_ram_addr_init_i ? vid_ram_width_i : display_width_i ;
 
// Zero extension for LINT cleanup
wire [`APIX_MSB*3:0] vid_ram_width_norm = {{`APIX_MSB*3-`LPIX_MSB{1'b0}}, vid_ram_width_mux};
 
// Select base address for next calculation
wire [`APIX_MSB:0] next_base_addr = (vid_ram_addr_init_i | ~vid_ram_line_done | ~vid_ram_win_mode_i) ? vid_ram_addr_i :
vid_ram_line_addr ;
// Compute next address
wire [`APIX_MSB:0] next_addr = next_base_addr
+ (vid_ram_width_norm[`APIX_MSB:0] & {`APIX_MSB+1{(~vid_ram_addr_init_i & vid_ram_win_mode_i) ? (~vid_ram_win_y_swap_i & (vid_ram_win_cl_swap_i ^ vid_ram_line_done)) : 1'b0}})
- (vid_ram_width_norm[`APIX_MSB:0] & {`APIX_MSB+1{(~vid_ram_addr_init_i & vid_ram_win_mode_i) ? ( vid_ram_win_y_swap_i & (vid_ram_win_cl_swap_i ^ vid_ram_line_done)) : 1'b0}})
+ (plus_one_val & {`APIX_MSB+1{(~vid_ram_addr_init_i & vid_ram_win_mode_i) ? (~vid_ram_win_x_swap_i & ~(vid_ram_win_cl_swap_i ^ vid_ram_line_done)) : (~vid_ram_win_mode_i & ~vid_ram_addr_init_i)}})
- (plus_one_val & {`APIX_MSB+1{(~vid_ram_addr_init_i & vid_ram_win_mode_i) ? ( vid_ram_win_x_swap_i & ~(vid_ram_win_cl_swap_i ^ vid_ram_line_done)) : 1'b0}});
 
wire update_line_addr = (vid_ram_addr_init_i | vid_ram_line_done) & vid_ram_win_mode_i;
wire update_pixel_addr = update_line_addr | vid_ram_addr_step_i;
 
// Start RAM address of currentely refreshed line
always @(posedge mclk or posedge puc_rst)
if (puc_rst) vid_ram_line_addr <= {`APIX_MSB+1{1'b0}};
else if (update_line_addr) vid_ram_line_addr <= next_addr;
 
// Current RAM address of the currentely refreshed pixel
wire [`APIX_MSB:0] vid_ram_addr_nxt_o = update_pixel_addr ? next_addr : vid_ram_addr_i;
 
// Count the pixel number in the current line
// (used to detec the end of a line)
always @(posedge mclk or posedge puc_rst)
if (puc_rst) vid_ram_column_count <= {`LPIX_MSB+1{1'b0}};
else if (vid_ram_addr_init_i) vid_ram_column_count <= {`LPIX_MSB+1{1'b0}};
else if (vid_ram_line_done) vid_ram_column_count <= {`LPIX_MSB+1{1'b0}};
else if (vid_ram_addr_step_i) vid_ram_column_count <= vid_ram_column_count + {{`LPIX_MSB+1-5{1'b0}}, plus_one_val[4:0]};
 
 
endmodule // ogfx_reg_vram_addr
 
`ifdef OGFX_NO_INCLUDE
`else
`include "openGFX430_undefines.v"
`endif
/core/rtl/verilog/ogfx_if_lt24.v
0,0 → 1,471
//----------------------------------------------------------------------------
// Copyright (C) 2015 Authors
//
// This source file may be used and distributed without restriction provided
// that this copyright statement is not removed from the file and that any
// derivative work contains the original copyright notice and the associated
// disclaimer.
//
// This source file is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This source is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
// License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this source; if not, write to the Free Software Foundation,
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
//----------------------------------------------------------------------------
//
// *File Name: ogfx_if_lt24.v
//
// *Module Description:
// Interface to the LT24 LCD display.
//
// *Author(s):
// - Olivier Girard, olgirard@gmail.com
//
//----------------------------------------------------------------------------
// $Rev$
// $LastChangedBy$
// $LastChangedDate$
//----------------------------------------------------------------------------
`ifdef OGFX_NO_INCLUDE
`else
`include "openGFX430_defines.v"
`endif
 
module ogfx_if_lt24 (
 
// OUTPUTs
event_fsm_done_o, // Event - FSM is done
event_fsm_start_o, // Event - FSM is starting
 
lt24_cs_n_o, // LT24 Chip select (Active low)
lt24_d_o, // LT24 Data output
lt24_d_en_o, // LT24 Data output enable
lt24_rd_n_o, // LT24 Read strobe (Active low)
lt24_rs_o, // LT24 Command/Param selection (Cmd=0/Param=1)
lt24_wr_n_o, // LT24 Write strobe (Active low)
 
refresh_active_o, // Display refresh on going
refresh_data_request_o, // Display refresh new data request
 
status_o, // Status - FSM
 
// INPUTs
mclk, // Main system clock
puc_rst, // Main system reset
 
cfg_lt24_clk_div_i, // Clock Divider configuration for LT24 interface
cfg_lt24_display_size_i, // Display size (number of pixels)
cfg_lt24_refresh_i, // Refresh rate configuration for LT24 interface
cfg_lt24_refresh_sync_en_i, // Refresh sync enable configuration for LT24 interface
cfg_lt24_refresh_sync_val_i, // Refresh sync value configuration for LT24 interface
 
cmd_dfill_i, // Display refresh data
cmd_dfill_trig_i, // Trigger a full display refresh
 
cmd_generic_cmd_val_i, // Generic command value
cmd_generic_has_param_i, // Generic command to be sent has parameter(s)
cmd_generic_param_val_i, // Generic command parameter value
cmd_generic_trig_i, // Trigger generic command transmit (or new parameter available)
 
cmd_refresh_i, // Display refresh command
 
lt24_d_i, // LT24 Data input
 
refresh_data_i, // Display refresh data
refresh_data_ready_i // Display refresh new data is ready
);
 
// OUTPUTs
//=========
output event_fsm_done_o; // LT24 FSM done event
output event_fsm_start_o; // LT24 FSM start event
 
output lt24_cs_n_o; // LT24 Chip select (Active low)
output [15:0] lt24_d_o; // LT24 Data output
output lt24_d_en_o; // LT24 Data output enable
output lt24_rd_n_o; // LT24 Read strobe (Active low)
output lt24_rs_o; // LT24 Command/Param selection (Cmd=0/Param=1)
output lt24_wr_n_o; // LT24 Write strobe (Active low)
 
output refresh_active_o; // Display refresh on going
output refresh_data_request_o; // Display refresh new data request
 
output [4:0] status_o; // LT24 FSM Status
 
// INPUTs
//=========
input mclk; // Main system clock
input puc_rst; // Main system reset
 
input [2:0] cfg_lt24_clk_div_i; // Clock Divider configuration for LT24 interface
input [`SPIX_MSB:0] cfg_lt24_display_size_i; // Display size (number of pixels)
input [11:0] cfg_lt24_refresh_i; // Refresh rate configuration for LT24 interface
input cfg_lt24_refresh_sync_en_i; // Refresh sync enable configuration for LT24 interface
input [9:0] cfg_lt24_refresh_sync_val_i; // Refresh sync value configuration for LT24 interface
 
input [15:0] cmd_dfill_i; // Display refresh data
input cmd_dfill_trig_i; // Trigger a full display refresh
 
input [7:0] cmd_generic_cmd_val_i; // Generic command value
input cmd_generic_has_param_i; // Generic command to be sent has parameter(s)
input [15:0] cmd_generic_param_val_i; // Generic command parameter value
input cmd_generic_trig_i; // Trigger generic command transmit (or new parameter available)
 
input cmd_refresh_i; // Display refresh command
 
input [15:0] lt24_d_i; // LT24 Data input
 
input [15:0] refresh_data_i; // Display refresh data
input refresh_data_ready_i; // Display refresh new data is ready
 
 
//=============================================================================
// 1) WIRE, REGISTERS AND PARAMETER DECLARATION
//=============================================================================
 
// State machine registers
reg [4:0] lt24_state;
reg [4:0] lt24_state_nxt;
 
// Others
reg refresh_trigger;
wire status_gts_match;
 
// State definition
parameter STATE_IDLE = 0, // IDLE state
 
STATE_CMD_LO = 1, // Generic command to LT24
STATE_CMD_HI = 2,
STATE_CMD_PARAM_LO = 3,
STATE_CMD_PARAM_HI = 4,
STATE_CMD_PARAM_WAIT = 5,
 
STATE_RAMWR_INIT_CMD_LO = 6, // Initialize display buffer with data
STATE_RAMWR_INIT_CMD_HI = 7,
STATE_RAMWR_INIT_DATA_LO = 8,
STATE_RAMWR_INIT_DATA_HI = 9,
 
STATE_SCANLINE_CMD_LO = 10, // Wait for right scanline
STATE_SCANLINE_CMD_HI = 11,
STATE_SCANLINE_DUMMY_LO = 12,
STATE_SCANLINE_DUMMY_HI = 13,
STATE_SCANLINE_GTS1_LO = 14,
STATE_SCANLINE_GTS1_HI = 15,
STATE_SCANLINE_GTS2_LO = 16,
STATE_SCANLINE_GTS2_HI = 17,
 
 
STATE_RAMWR_REFR_CMD_LO = 18, // Refresh display buffer
STATE_RAMWR_REFR_CMD_HI = 19,
STATE_RAMWR_REFR_WAIT = 20,
STATE_RAMWR_REFR_DATA_LO = 21,
STATE_RAMWR_REFR_DATA_HI = 22;
 
 
//============================================================================
// 5) STATE MACHINE SENDING IMAGE DATA TO A SPECIFIED DISPLAY
//============================================================================
 
//--------------------------------
// LT24 Controller Clock Timer
//--------------------------------
reg [3:0] lt24_timer;
 
wire lt24_timer_done = lt24_d_en_o ? (lt24_timer == {1'b0, cfg_lt24_clk_div_i}) :
(lt24_timer == {cfg_lt24_clk_div_i, 1'b0}) ; // Use slower timing for read accesses
 
wire lt24_timer_run = (lt24_state != STATE_IDLE) &
(lt24_state != STATE_CMD_PARAM_WAIT) &
(lt24_state != STATE_RAMWR_REFR_WAIT) &
~lt24_timer_done;
 
wire lt24_timer_init = (lt24_timer_done & // Init if counter reaches limit:
!((lt24_state == STATE_CMD_PARAM_HI) & cmd_generic_has_param_i) & // -> if not moving to STATE_CMD_PARAM_WAIT
!((lt24_state == STATE_CMD_PARAM_WAIT))) | // -> if not in STATE_CMD_PARAM_WAIT
((lt24_state == STATE_CMD_PARAM_WAIT) & (cmd_generic_trig_i | ~cmd_generic_has_param_i)); // Init when leaving the STATE_CMD_PARAM_WAIT state
 
always @(posedge mclk or posedge puc_rst)
if (puc_rst) lt24_timer <= 4'h0;
else if (lt24_timer_init) lt24_timer <= 4'h0;
else if (lt24_timer_run) lt24_timer <= lt24_timer+4'h1;
 
 
//--------------------------------
// Pixel counter
//--------------------------------
reg [`SPIX_MSB:0] lt24_pixel_cnt;
 
wire lt24_pixel_cnt_run = (lt24_state==STATE_RAMWR_INIT_DATA_HI) |
(lt24_state==STATE_RAMWR_REFR_DATA_HI);
 
wire lt24_pixel_cnt_done = (lt24_pixel_cnt==1) | (lt24_pixel_cnt==0);
 
wire lt24_pixel_cnt_init = (lt24_state==STATE_RAMWR_INIT_CMD_HI) |
(lt24_state==STATE_RAMWR_REFR_CMD_HI) |
(lt24_pixel_cnt_done & lt24_pixel_cnt_run);
 
always @(posedge mclk or posedge puc_rst)
if (puc_rst) lt24_pixel_cnt <= {`SPIX_MSB+1{1'h0}};
else if (lt24_timer_init)
begin
if (lt24_pixel_cnt_init) lt24_pixel_cnt <= cfg_lt24_display_size_i;
else if (lt24_pixel_cnt_run) lt24_pixel_cnt <= lt24_pixel_cnt-{{`SPIX_MSB{1'h0}},1'b1};
end
 
 
//--------------------------------
// States Transitions
//--------------------------------
always @(lt24_state or cmd_dfill_trig_i or cmd_generic_trig_i or refresh_trigger or cfg_lt24_refresh_sync_en_i or status_gts_match or refresh_data_request_o or cmd_generic_has_param_i or lt24_timer_done or lt24_pixel_cnt_done)
case(lt24_state)
STATE_IDLE : lt24_state_nxt = cmd_dfill_trig_i ? STATE_RAMWR_INIT_CMD_LO :
refresh_trigger ?
(cfg_lt24_refresh_sync_en_i ? STATE_SCANLINE_CMD_LO : STATE_RAMWR_REFR_CMD_LO) :
cmd_generic_trig_i ? STATE_CMD_LO : STATE_IDLE ;
 
// GENERIC COMMANDS
STATE_CMD_LO : lt24_state_nxt = ~lt24_timer_done ? STATE_CMD_LO : STATE_CMD_HI ;
STATE_CMD_HI : lt24_state_nxt = ~lt24_timer_done ? STATE_CMD_HI :
cmd_generic_has_param_i ? STATE_CMD_PARAM_LO : STATE_IDLE ;
 
STATE_CMD_PARAM_LO : lt24_state_nxt = ~lt24_timer_done ? STATE_CMD_PARAM_LO : STATE_CMD_PARAM_HI ;
STATE_CMD_PARAM_HI : lt24_state_nxt = ~lt24_timer_done ? STATE_CMD_PARAM_HI :
cmd_generic_has_param_i ? STATE_CMD_PARAM_WAIT : STATE_IDLE ;
 
STATE_CMD_PARAM_WAIT : lt24_state_nxt = cmd_generic_trig_i ? STATE_CMD_PARAM_LO :
cmd_generic_has_param_i ? STATE_CMD_PARAM_WAIT : STATE_IDLE ;
 
// MEMORY INITIALIZATION
STATE_RAMWR_INIT_CMD_LO : lt24_state_nxt = ~lt24_timer_done ? STATE_RAMWR_INIT_CMD_LO : STATE_RAMWR_INIT_CMD_HI ;
STATE_RAMWR_INIT_CMD_HI : lt24_state_nxt = ~lt24_timer_done ? STATE_RAMWR_INIT_CMD_HI : STATE_RAMWR_INIT_DATA_LO ;
 
STATE_RAMWR_INIT_DATA_LO : lt24_state_nxt = ~lt24_timer_done ? STATE_RAMWR_INIT_DATA_LO : STATE_RAMWR_INIT_DATA_HI ;
STATE_RAMWR_INIT_DATA_HI : lt24_state_nxt = lt24_timer_done &
lt24_pixel_cnt_done ? STATE_IDLE :
~lt24_timer_done ? STATE_RAMWR_INIT_DATA_HI : STATE_RAMWR_INIT_DATA_LO ;
 
// WAIT FOR RIGHT SCANLINE BEFORE REFRESH
STATE_SCANLINE_CMD_LO : lt24_state_nxt = ~lt24_timer_done ? STATE_SCANLINE_CMD_LO : STATE_SCANLINE_CMD_HI ;
STATE_SCANLINE_CMD_HI : lt24_state_nxt = ~lt24_timer_done ? STATE_SCANLINE_CMD_HI : STATE_SCANLINE_DUMMY_LO ;
 
STATE_SCANLINE_DUMMY_LO : lt24_state_nxt = ~lt24_timer_done ? STATE_SCANLINE_DUMMY_LO : STATE_SCANLINE_DUMMY_HI ;
STATE_SCANLINE_DUMMY_HI : lt24_state_nxt = ~lt24_timer_done ? STATE_SCANLINE_DUMMY_HI : STATE_SCANLINE_GTS1_LO ;
 
STATE_SCANLINE_GTS1_LO : lt24_state_nxt = ~lt24_timer_done ? STATE_SCANLINE_GTS1_LO : STATE_SCANLINE_GTS1_HI ;
STATE_SCANLINE_GTS1_HI : lt24_state_nxt = ~lt24_timer_done ? STATE_SCANLINE_GTS1_HI : STATE_SCANLINE_GTS2_LO ;
 
STATE_SCANLINE_GTS2_LO : lt24_state_nxt = ~lt24_timer_done ? STATE_SCANLINE_GTS2_LO : STATE_SCANLINE_GTS2_HI ;
STATE_SCANLINE_GTS2_HI : lt24_state_nxt = ~lt24_timer_done ? STATE_SCANLINE_GTS2_HI :
(status_gts_match |
~cfg_lt24_refresh_sync_en_i) ? STATE_RAMWR_REFR_CMD_LO : STATE_SCANLINE_CMD_LO ;
 
// FRAME REFRESH
STATE_RAMWR_REFR_CMD_LO : lt24_state_nxt = ~lt24_timer_done ? STATE_RAMWR_REFR_CMD_LO : STATE_RAMWR_REFR_CMD_HI ;
STATE_RAMWR_REFR_CMD_HI : lt24_state_nxt = ~lt24_timer_done ? STATE_RAMWR_REFR_CMD_HI :
~refresh_data_request_o ? STATE_RAMWR_REFR_DATA_LO : STATE_RAMWR_REFR_WAIT ;
 
STATE_RAMWR_REFR_WAIT : lt24_state_nxt = ~refresh_data_request_o ? STATE_RAMWR_REFR_DATA_LO : STATE_RAMWR_REFR_WAIT ;
 
STATE_RAMWR_REFR_DATA_LO : lt24_state_nxt = ~lt24_timer_done ? STATE_RAMWR_REFR_DATA_LO : STATE_RAMWR_REFR_DATA_HI ;
STATE_RAMWR_REFR_DATA_HI : lt24_state_nxt = lt24_timer_done &
lt24_pixel_cnt_done ? STATE_IDLE :
~lt24_timer_done ? STATE_RAMWR_REFR_DATA_HI :
~refresh_data_request_o ? STATE_RAMWR_REFR_DATA_LO : STATE_RAMWR_REFR_WAIT ;
 
// pragma coverage off
default : lt24_state_nxt = STATE_IDLE;
// pragma coverage on
endcase
 
// State machine
always @(posedge mclk or posedge puc_rst)
if (puc_rst) lt24_state <= STATE_IDLE;
else lt24_state <= lt24_state_nxt;
 
 
// Output status
assign status_o[0] = (lt24_state != STATE_IDLE); // LT24 FSM BUSY
 
assign status_o[1] = (lt24_state == STATE_CMD_PARAM_WAIT); // LT24 Waits for command parameter
 
assign status_o[2] = (lt24_state == STATE_RAMWR_REFR_CMD_LO) | (lt24_state == STATE_RAMWR_REFR_CMD_HI) | // LT24 REFRESH BUSY
(lt24_state == STATE_RAMWR_REFR_DATA_LO) | (lt24_state == STATE_RAMWR_REFR_DATA_HI) |
(lt24_state == STATE_RAMWR_REFR_WAIT);
 
assign status_o[3] = (lt24_state == STATE_SCANLINE_CMD_LO) | (lt24_state == STATE_SCANLINE_CMD_HI) | // LT24 WAIT FOR SCANLINE
(lt24_state == STATE_SCANLINE_DUMMY_LO) | (lt24_state == STATE_SCANLINE_DUMMY_HI) |
(lt24_state == STATE_SCANLINE_GTS1_LO) | (lt24_state == STATE_SCANLINE_GTS1_HI) |
(lt24_state == STATE_SCANLINE_GTS2_LO) | (lt24_state == STATE_SCANLINE_GTS2_HI);
 
assign status_o[4] = (lt24_state == STATE_RAMWR_INIT_CMD_LO) | (lt24_state == STATE_RAMWR_INIT_CMD_HI) | // LT24 INIT BUSY
(lt24_state == STATE_RAMWR_INIT_DATA_LO) | (lt24_state == STATE_RAMWR_INIT_DATA_HI);
 
assign refresh_active_o = status_o[2];
 
 
// Refresh data request
wire refresh_data_request_set = ((lt24_state == STATE_RAMWR_REFR_CMD_LO) & (lt24_state_nxt == STATE_RAMWR_REFR_CMD_HI)) |
((lt24_state == STATE_RAMWR_REFR_DATA_LO) & (lt24_state_nxt == STATE_RAMWR_REFR_DATA_HI)) |
(lt24_state == STATE_RAMWR_REFR_WAIT);
wire refresh_data_request_clr = refresh_data_ready_i;
reg refresh_data_request_reg;
always @(posedge mclk or posedge puc_rst)
if (puc_rst) refresh_data_request_reg <= 1'b0;
else refresh_data_request_reg <= refresh_data_request_clr ? 1'b0 :
refresh_data_request_set ? 1'b1 : refresh_data_request_reg;
 
assign refresh_data_request_o = refresh_data_request_reg & ~refresh_data_ready_i;
 
assign event_fsm_start_o = (lt24_state_nxt != STATE_IDLE) & (lt24_state == STATE_IDLE);
assign event_fsm_done_o = (lt24_state != STATE_IDLE) & (lt24_state_nxt == STATE_IDLE);
 
 
//============================================================================
// 6) LT24 CONTROLLER OUTPUT ASSIGNMENT
//============================================================================
 
// LT24 Chip select (active low)
reg lt24_cs_n_o;
always @(posedge mclk or posedge puc_rst)
if (puc_rst) lt24_cs_n_o <= 1'b1;
else lt24_cs_n_o <= (lt24_state_nxt==STATE_IDLE);
 
// Command (0) or Data (1)
reg lt24_rs_o;
always @(posedge mclk or posedge puc_rst)
if (puc_rst) lt24_rs_o <= 1'b1;
else lt24_rs_o <= ~((lt24_state_nxt==STATE_CMD_LO) | (lt24_state_nxt==STATE_CMD_HI) |
(lt24_state_nxt==STATE_SCANLINE_CMD_LO) | (lt24_state_nxt==STATE_SCANLINE_CMD_HI) |
(lt24_state_nxt==STATE_RAMWR_INIT_CMD_LO) | (lt24_state_nxt==STATE_RAMWR_INIT_CMD_HI) |
(lt24_state_nxt==STATE_RAMWR_REFR_CMD_LO) | (lt24_state_nxt==STATE_RAMWR_REFR_CMD_HI));
 
// LT24 Write strobe (Active low)
reg lt24_wr_n_o;
 
wire lt24_wr_n_clr = (lt24_state_nxt==STATE_CMD_LO) | (lt24_state_nxt==STATE_CMD_PARAM_LO) | (lt24_state_nxt==STATE_SCANLINE_CMD_LO) |
(lt24_state_nxt==STATE_RAMWR_INIT_CMD_LO) | (lt24_state_nxt==STATE_RAMWR_INIT_DATA_LO) |
(lt24_state_nxt==STATE_RAMWR_REFR_CMD_LO) | (lt24_state_nxt==STATE_RAMWR_REFR_DATA_LO);
 
always @(posedge mclk or posedge puc_rst)
if (puc_rst) lt24_wr_n_o <= 1'b1;
else if (lt24_wr_n_clr) lt24_wr_n_o <= 1'b0;
else lt24_wr_n_o <= 1'b1;
 
// LT24 Read strobe (active low)
reg lt24_rd_n_o;
 
wire lt24_rd_n_clr = (lt24_state_nxt==STATE_SCANLINE_DUMMY_LO) |
(lt24_state_nxt==STATE_SCANLINE_GTS1_LO) | (lt24_state_nxt==STATE_SCANLINE_GTS2_LO);
 
always @(posedge mclk or posedge puc_rst)
if (puc_rst) lt24_rd_n_o <= 1'b1;
else if (lt24_rd_n_clr) lt24_rd_n_o <= 1'b0;
else lt24_rd_n_o <= 1'b1;
 
 
// LT24 Data
reg [15:0] lt24_d_nxt;
always @(lt24_state_nxt or cmd_generic_cmd_val_i or cmd_generic_param_val_i or lt24_d_o or cmd_dfill_i or refresh_data_i)
case(lt24_state_nxt)
STATE_IDLE : lt24_d_nxt <= 16'h0000;
 
STATE_CMD_LO,
STATE_CMD_HI : lt24_d_nxt <= {8'h00, cmd_generic_cmd_val_i};
STATE_CMD_PARAM_LO,
STATE_CMD_PARAM_HI : lt24_d_nxt <= cmd_generic_param_val_i;
STATE_CMD_PARAM_WAIT : lt24_d_nxt <= lt24_d_o;
 
STATE_RAMWR_INIT_CMD_LO,
STATE_RAMWR_INIT_CMD_HI : lt24_d_nxt <= 16'h002C;
STATE_RAMWR_INIT_DATA_LO,
STATE_RAMWR_INIT_DATA_HI : lt24_d_nxt <= cmd_dfill_i;
 
STATE_SCANLINE_CMD_LO,
STATE_SCANLINE_CMD_HI : lt24_d_nxt <= 16'h0045;
 
STATE_RAMWR_REFR_CMD_LO,
STATE_RAMWR_REFR_CMD_HI : lt24_d_nxt <= 16'h002C;
STATE_RAMWR_REFR_DATA_LO : lt24_d_nxt <= refresh_data_i;
STATE_RAMWR_REFR_DATA_HI : lt24_d_nxt <= lt24_d_o;
STATE_RAMWR_REFR_WAIT : lt24_d_nxt <= lt24_d_o;
 
// pragma coverage off
default : lt24_d_nxt <= 16'h0000;
// pragma coverage on
endcase
 
reg [15:0] lt24_d_o;
always @(posedge mclk or posedge puc_rst)
if (puc_rst) lt24_d_o <= 16'h0000;
else lt24_d_o <= lt24_d_nxt;
 
// Output enable
reg lt24_d_en_o;
always @(posedge mclk or posedge puc_rst)
if (puc_rst) lt24_d_en_o <= 1'h0; // Don't drive output during reset
else lt24_d_en_o <= ~((lt24_state_nxt == STATE_SCANLINE_DUMMY_LO) |
(lt24_state_nxt == STATE_SCANLINE_DUMMY_HI) |
(lt24_state_nxt == STATE_SCANLINE_GTS1_LO ) |
(lt24_state_nxt == STATE_SCANLINE_GTS1_HI ) |
(lt24_state_nxt == STATE_SCANLINE_GTS2_LO ) |
(lt24_state_nxt == STATE_SCANLINE_GTS2_HI ));
 
//============================================================================
// 7) LT24 GTS VALUE (i.e. CURRENT SCAN LINE)
//============================================================================
 
reg [1:0] status_gts_msb;
wire status_gts_msb_wr = ((lt24_state == STATE_SCANLINE_GTS1_LO) & (lt24_state_nxt == STATE_SCANLINE_GTS1_HI));
always @(posedge mclk or posedge puc_rst)
if (puc_rst) status_gts_msb <= 2'h0;
else if (status_gts_msb_wr) status_gts_msb <= lt24_d_i[1:0];
 
reg [7:0] status_gts_lsb;
wire status_gts_lsb_wr = ((lt24_state == STATE_SCANLINE_GTS2_LO) & (lt24_state_nxt == STATE_SCANLINE_GTS2_HI));
always @(posedge mclk or posedge puc_rst)
if (puc_rst) status_gts_lsb <= 8'h00;
else if (status_gts_lsb_wr) status_gts_lsb <= lt24_d_i[7:0];
 
wire [9:0] status_gts = {status_gts_msb, status_gts_lsb};
 
assign status_gts_match = (status_gts == cfg_lt24_refresh_sync_val_i);
 
//============================================================================
// 8) REFRESH TIMER & TRIGGER
//============================================================================
 
// Refresh Timer
reg [23:0] refresh_timer;
wire refresh_timer_disable = (cfg_lt24_refresh_i==12'h000) | ~cmd_refresh_i;
wire refresh_timer_done = (refresh_timer[23:12]==cfg_lt24_refresh_i);
 
always @(posedge mclk or posedge puc_rst)
if (puc_rst) refresh_timer <= 24'h000000;
else if (refresh_timer_disable) refresh_timer <= 24'h000000;
else if (refresh_timer_done) refresh_timer <= 24'h000000;
else refresh_timer <= refresh_timer + 24'h1;
 
// Refresh Trigger
wire refresh_trigger_set = (lt24_state==STATE_IDLE) & cmd_refresh_i & (refresh_timer==24'h000000);
wire refresh_trigger_clr = (lt24_state==STATE_RAMWR_REFR_CMD_LO);
 
always @(posedge mclk or posedge puc_rst)
if (puc_rst) refresh_trigger <= 1'b0;
else if (refresh_trigger_set) refresh_trigger <= 1'b1;
else if (refresh_trigger_clr) refresh_trigger <= 1'b0;
 
endmodule // ogfx_if_lt24
 
`ifdef OGFX_NO_INCLUDE
`else
`include "openGFX430_undefines.v"
`endif
/core/rtl/verilog/ogfx_backend_frame_fifo.v
0,0 → 1,398
//----------------------------------------------------------------------------
// Copyright (C) 2015 Authors
//
// This source file may be used and distributed without restriction provided
// that this copyright statement is not removed from the file and that any
// derivative work contains the original copyright notice and the associated
// disclaimer.
//
// This source file is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This source is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
// License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this source; if not, write to the Free Software Foundation,
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
//----------------------------------------------------------------------------
//
// *File Name: ogfx_backend_frame_fifo.v
//
// *Module Description:
// Mini-cache memory for frame memory access.
//
// *Author(s):
// - Olivier Girard, olgirard@gmail.com
//
//----------------------------------------------------------------------------
// $Rev$
// $LastChangedBy$
// $LastChangedDate$
//----------------------------------------------------------------------------
`ifdef OGFX_NO_INCLUDE
`else
`include "openGFX430_defines.v"
`endif
 
module ogfx_backend_frame_fifo (
 
// OUTPUTs
frame_data_o, // Frame data
frame_data_ready_o, // Frame data ready
 
vid_ram_addr_o, // Video-RAM address
vid_ram_cen_o, // Video-RAM enable (active low)
 
// INPUTs
mclk, // Main system clock
puc_rst, // Main system reset
 
display_width_i, // Display width
display_height_i, // Display height
display_size_i, // Display size (number of pixels)
display_y_swap_i, // Display configuration: swap Y axis (horizontal symmetry)
display_x_swap_i, // Display configuration: swap X axis (vertical symmetry)
display_cl_swap_i, // Display configuration: swap column/lines
 
frame_data_request_i, // Request for next frame data
 
gfx_mode_i, // Video mode (1xx:16bpp / 011:8bpp / 010:4bpp / 001:2bpp / 000:1bpp)
 
vid_ram_dout_i, // Video-RAM data output
vid_ram_dout_rdy_nxt_i, // Video-RAM data output ready during next cycle
 
refresh_active_i, // Display refresh on going
refresh_frame_base_addr_i // Refresh frame base address
);
 
// OUTPUTs
//=========
output [15:0] frame_data_o; // Frame data
output frame_data_ready_o; // Frame data ready
 
output[`VRAM_MSB:0] vid_ram_addr_o; // Video-RAM address
output vid_ram_cen_o; // Video-RAM enable (active low)
 
// INPUTs
//=========
input mclk; // Main system clock
input puc_rst; // Main system reset
 
input [`LPIX_MSB:0] display_width_i; // Display width
input [`LPIX_MSB:0] display_height_i; // Display height
input [`SPIX_MSB:0] display_size_i; // Display size (number of pixels)
input display_y_swap_i; // Display configuration: swap Y axis (horizontal symmetry)
input display_x_swap_i; // Display configuration: swap X axis (vertical symmetry)
input display_cl_swap_i; // Display configuration: swap column/lines
 
input frame_data_request_i; // Request for next frame data
 
input [2:0] gfx_mode_i; // Video mode (1xx:16bpp / 011:8bpp / 010:4bpp / 001:2bpp / 000:1bpp)
 
input [15:0] vid_ram_dout_i; // Video-RAM data output
input vid_ram_dout_rdy_nxt_i; // Video-RAM data output ready during next cycle
 
input refresh_active_i; // Display refresh on going
input [`APIX_MSB:0] refresh_frame_base_addr_i; // Refresh frame base address
 
 
//=============================================================================
// 1) WIRE, REGISTERS AND PARAMETER DECLARATION
//=============================================================================
 
// Some parameter(s)
parameter FIFO_EMPTY = 2'h0,
FIFO_FULL = 2'h3;
 
// Video modes decoding
wire gfx_mode_1_bpp = (gfx_mode_i == 3'b000);
wire gfx_mode_2_bpp = (gfx_mode_i == 3'b001);
wire gfx_mode_4_bpp = (gfx_mode_i == 3'b010);
wire gfx_mode_8_bpp = (gfx_mode_i == 3'b011);
wire gfx_mode_16_bpp = ~(gfx_mode_8_bpp | gfx_mode_4_bpp |
gfx_mode_2_bpp | gfx_mode_1_bpp);
 
// Others
reg [1:0] fifo_counter;
wire [1:0] fifo_counter_nxt;
wire fifo_data_ready;
wire read_from_fifo;
reg vid_ram_data_mux_ready;
reg vid_ram_dout_ready;
wire [15:0] vid_ram_dout_processed;
 
 
//============================================================================
// 1) FRAME ADDRESS GENERATION
//============================================================================
 
//--------------------------------
// FIFO data request
//--------------------------------
// The FIFO requests for new data whenever it is not full (or not about to get full)
 
reg fifo_data_request;
wire fifo_data_request_nxt = refresh_active_i &
(fifo_counter_nxt != FIFO_FULL) & // FIFO is full
~((fifo_counter_nxt == (FIFO_FULL-1)) & fifo_data_ready); // FIFO is about to be full
 
always @(posedge mclk or posedge puc_rst)
if (puc_rst) fifo_data_request <= 1'h0;
else fifo_data_request <= fifo_data_request_nxt;
 
//--------------------------------
// Video RAM Address generation
//--------------------------------
reg [`APIX_MSB:0] vid_ram_pixel_addr;
reg [`APIX_MSB:0] vid_ram_line_addr;
reg [`LPIX_MSB:0] vid_ram_column_count;
 
// Detect when the fifo is done reading the current pixel data
wire vid_ram_pixel_done = fifo_data_request & fifo_data_ready;
 
// Detect when the current line refresh is done
wire [`LPIX_MSB:0] line_length = display_cl_swap_i ? display_height_i : display_width_i;
wire vid_ram_line_done = vid_ram_pixel_done & (vid_ram_column_count==(line_length-{{`LPIX_MSB{1'b0}}, 1'b1}));
 
// Zero extension for LINT cleanup
wire [`VRAM_MSB*3:0] display_size_norm = {{`VRAM_MSB*3-`SPIX_MSB{1'b0}}, display_size_i};
wire [`VRAM_MSB*3:0] display_width_norm = {{`VRAM_MSB*3-`LPIX_MSB{1'b0}}, display_width_i};
 
// Based on the display configuration (i.e. X-Swap / Y-Swap / CL-Swap)
// the screen is not going to be refreshed in the same way.
// The screen refresh is the performed according to the following
// pseudo-code procedure:
//
// for (l_idx=0; l_idx<HEIGHT; l_idx++)
// for (c_idx=0; c_idx<WIDTH; c_idx++)
// addr = FIRST + 0 + WIDTH*l_idx + c_idx // Normal
// addr = FIRST + WIDTH-1 + WIDTH*l_idx - c_idx // X-Swap
// addr = LAST - WIDTH+1 - WIDTH*l_idx + c_idx // Y-Swap
// addr = LAST - 0 - WIDTH*l_idx - c_idx // X/Y-Swap
//
 
wire [`APIX_MSB:0] next_base_addr = ~refresh_active_i ? refresh_frame_base_addr_i :
vid_ram_line_done ? vid_ram_line_addr :
vid_ram_pixel_addr ;
 
wire [`APIX_MSB:0] next_addr = next_base_addr
+ (display_size_norm[`APIX_MSB:0] & {`APIX_MSB+1{refresh_active_i ? 1'b0 : display_y_swap_i}})
+ (display_width_norm[`APIX_MSB:0] & {`APIX_MSB+1{refresh_active_i ? (~display_y_swap_i & (display_cl_swap_i ^ vid_ram_line_done)) : display_x_swap_i}})
- (display_width_norm[`APIX_MSB:0] & {`APIX_MSB+1{refresh_active_i ? ( display_y_swap_i & (display_cl_swap_i ^ vid_ram_line_done)) : display_y_swap_i}})
+ ({{`APIX_MSB{1'b0}}, 1'b1} & {`APIX_MSB+1{refresh_active_i ? (~display_x_swap_i & ~(display_cl_swap_i ^ vid_ram_line_done)) : 1'b0 }})
- ({{`APIX_MSB{1'b0}}, 1'b1} & {`APIX_MSB+1{refresh_active_i ? ( display_x_swap_i & ~(display_cl_swap_i ^ vid_ram_line_done)) : display_x_swap_i}});
 
wire update_line_addr = ~refresh_active_i | vid_ram_line_done;
wire update_pixel_addr = update_line_addr | vid_ram_pixel_done;
 
// Start RAM address of currentely refreshed line
always @(posedge mclk or posedge puc_rst)
if (puc_rst) vid_ram_line_addr <= {`APIX_MSB+1{1'b0}};
else if (update_line_addr) vid_ram_line_addr <= next_addr;
 
// Current RAM address of the currentely refreshed pixel
wire [`APIX_MSB:0] vid_ram_pixel_addr_nxt = update_pixel_addr ? next_addr : vid_ram_pixel_addr;
 
always @(posedge mclk or posedge puc_rst)
if (puc_rst) vid_ram_pixel_addr <= {`APIX_MSB+1{1'b0}};
else vid_ram_pixel_addr <= vid_ram_pixel_addr_nxt;
 
// Count the pixel number in the current line
// (used to detec the end of a line)
always @(posedge mclk or posedge puc_rst)
if (puc_rst) vid_ram_column_count <= {`LPIX_MSB+1{1'b0}};
else if (~refresh_active_i) vid_ram_column_count <= {`LPIX_MSB+1{1'b0}};
else if (vid_ram_line_done) vid_ram_column_count <= {`LPIX_MSB+1{1'b0}};
else if (vid_ram_pixel_done) vid_ram_column_count <= vid_ram_column_count + {{`LPIX_MSB{1'b0}}, 1'b1};
 
// Depending on the color mode, format the address for doing the RAM accesses.
assign vid_ram_addr_o = ({`VRAM_MSB+1{gfx_mode_1_bpp }} & vid_ram_pixel_addr[`VRAM_MSB+4:4]) |
({`VRAM_MSB+1{gfx_mode_2_bpp }} & vid_ram_pixel_addr[`VRAM_MSB+3:3]) |
({`VRAM_MSB+1{gfx_mode_4_bpp }} & vid_ram_pixel_addr[`VRAM_MSB+2:2]) |
({`VRAM_MSB+1{gfx_mode_8_bpp }} & vid_ram_pixel_addr[`VRAM_MSB+1:1]) |
({`VRAM_MSB+1{gfx_mode_16_bpp}} & vid_ram_pixel_addr[`VRAM_MSB+0:0]) ;
 
// Compute the next RAM address to detect when a new address is generated
wire [16:0] vid_ram_addr_nxt = ({`VRAM_MSB+1{gfx_mode_1_bpp }} & vid_ram_pixel_addr_nxt[`VRAM_MSB+4:4]) |
({`VRAM_MSB+1{gfx_mode_2_bpp }} & vid_ram_pixel_addr_nxt[`VRAM_MSB+3:3]) |
({`VRAM_MSB+1{gfx_mode_4_bpp }} & vid_ram_pixel_addr_nxt[`VRAM_MSB+2:2]) |
({`VRAM_MSB+1{gfx_mode_8_bpp }} & vid_ram_pixel_addr_nxt[`VRAM_MSB+1:1]) |
({`VRAM_MSB+1{gfx_mode_16_bpp}} & vid_ram_pixel_addr_nxt[`VRAM_MSB+0:0]) ;
 
// Detect when a new word needs to be fetched from the memory
// (i.e. detect when the RAM address is updated)
reg vid_ram_addr_update;
wire vid_ram_addr_update_nxt = (vid_ram_addr_o != vid_ram_addr_nxt);
always @(posedge mclk or posedge puc_rst)
if (puc_rst) vid_ram_addr_update <= 1'h0;
else if (~refresh_active_i) vid_ram_addr_update <= 1'h1;
else if (vid_ram_pixel_done) vid_ram_addr_update <= vid_ram_addr_update_nxt;
 
 
// Disable RAM access if there is no need to fetch a new word
assign vid_ram_cen_o = vid_ram_addr_update ? ~fifo_data_request : 1'b1;
 
// If the next FIFO data doesn't come from the RAM, then it is ready as
// soon as it is requested
assign fifo_data_ready = vid_ram_addr_update ? vid_ram_dout_rdy_nxt_i : fifo_data_request;
 
 
//============================================================================
// 2) FRAME DATA-PRE-PROCESSING (PRIOR BEING PUSHED INTO FIFO)
//============================================================================
 
//--------------------------------
// Data buffer
//--------------------------------
// For the LUT modes, it is not necessary to access the RAM for
// every pixel. In that case, the FIFO is filled with the values
// coming from the buffer.
// (i.e. we only take data directly from the RAM when it is just read)
reg [15:0] vid_ram_dout_buf;
always @(posedge mclk or posedge puc_rst)
if (puc_rst) vid_ram_dout_buf <= 16'h0000;
else if (vid_ram_dout_ready) vid_ram_dout_buf <= vid_ram_dout_i;
 
wire [15:0] vid_ram_dout_mux = vid_ram_dout_ready ? vid_ram_dout_i : vid_ram_dout_buf;
 
//--------------------------------
// Data formating
//--------------------------------
// Depending on the mode, the address LSBs are used to select which bits
// of the current data word need to be put in the FIFO
wire [3:0] vid_ram_data_sel_nxt = ({4{gfx_mode_1_bpp}} & {vid_ram_pixel_addr[3:0] }) |
({4{gfx_mode_2_bpp}} & {vid_ram_pixel_addr[2:0], 1'b0 }) |
({4{gfx_mode_4_bpp}} & {vid_ram_pixel_addr[1:0], 2'b00 }) |
({4{gfx_mode_8_bpp}} & {vid_ram_pixel_addr[0], 3'b000 }) ;
 
reg [3:0] vid_ram_data_sel;
always @(posedge mclk or posedge puc_rst)
if (puc_rst) vid_ram_data_sel <= 4'h0;
else if (vid_ram_pixel_done) vid_ram_data_sel <= vid_ram_data_sel_nxt;
 
 
wire [15:0] vid_ram_dout_shifted = (vid_ram_dout_mux >> vid_ram_data_sel);
 
// Format data output for LUT processing
// (8 bit LSBs are used to address the LUT memory, MSBs are ignored)
assign vid_ram_dout_processed = ({16{gfx_mode_1_bpp }} & {8'h00, 7'b0000000, vid_ram_dout_shifted[0] }) |
({16{gfx_mode_2_bpp }} & {8'h00, 6'b000000 , vid_ram_dout_shifted[1:0]}) |
({16{gfx_mode_4_bpp }} & {8'h00, 4'b0000 , vid_ram_dout_shifted[3:0]}) |
({16{gfx_mode_8_bpp }} & {8'h00, vid_ram_dout_shifted[7:0]}) |
({16{gfx_mode_16_bpp}} & { vid_ram_dout_shifted[15:0] }) ;
 
//--------------------------------
// Data Ready
//--------------------------------
// Data is available on the bus one cycle after the rdy_nxt signals
always @(posedge mclk or posedge puc_rst)
if (puc_rst) vid_ram_data_mux_ready <= 1'b0;
else vid_ram_data_mux_ready <= fifo_data_ready;
 
always @(posedge mclk or posedge puc_rst)
if (puc_rst) vid_ram_dout_ready <= 1'b0;
else vid_ram_dout_ready <= vid_ram_dout_rdy_nxt_i;
 
 
//============================================================================
// 3) FIFO COUNTER
//============================================================================
 
// Declaration
// Control signals
wire fifo_push = vid_ram_data_mux_ready & (fifo_counter != FIFO_FULL);
wire fifo_pop = read_from_fifo & (fifo_counter != FIFO_EMPTY);
 
// Fifo counter
assign fifo_counter_nxt = ~refresh_active_i ? FIFO_EMPTY : // Initialize
(fifo_push & fifo_pop) ? fifo_counter : // Keep value (pop & push at the same time)
fifo_push ? fifo_counter + 2'h1 : // Push
fifo_pop ? fifo_counter - 2'h1 : // Pop
fifo_counter; // Hold
 
always @(posedge mclk or posedge puc_rst)
if (puc_rst) fifo_counter <= FIFO_EMPTY;
else fifo_counter <= fifo_counter_nxt;
 
 
//============================================================================
// 4) FIFO MEMORY & RD/WR POINTERS
//============================================================================
 
// Write pointer
reg [1:0] wr_ptr;
always @(posedge mclk or posedge puc_rst)
if (puc_rst) wr_ptr <= 2'h0;
else if (~refresh_active_i) wr_ptr <= 2'h0;
else if (fifo_push)
begin
if (wr_ptr==(FIFO_FULL-1)) wr_ptr <= 2'h0;
else wr_ptr <= wr_ptr + 2'h1;
end
 
// Memory
reg [15:0] fifo_mem [0:2];
always @(posedge mclk or posedge puc_rst)
if (puc_rst)
begin
fifo_mem[0] <= 16'h0000;
fifo_mem[1] <= 16'h0000;
fifo_mem[2] <= 16'h0000;
end
else if (fifo_push)
begin
fifo_mem[wr_ptr] <= vid_ram_dout_processed;
end
 
// Read pointer
reg [1:0] rd_ptr;
always @(posedge mclk or posedge puc_rst)
if (puc_rst) rd_ptr <= 2'h0;
else if (~refresh_active_i) rd_ptr <= 2'h0;
else if (fifo_pop)
begin
if (rd_ptr==(FIFO_FULL-1)) rd_ptr <= 2'h0;
else rd_ptr <= rd_ptr + 2'h1;
end
 
 
//============================================================================
// 5) FRAME DATA FROM FIFO
//============================================================================
 
// RAW Data is valid
reg frame_data_init;
wire frame_data_init_nxt = ~refresh_active_i ? 1'h0 :
fifo_pop ? 1'b1 : frame_data_init;
 
always @(posedge mclk or posedge puc_rst)
if (puc_rst) frame_data_init <= 1'h0;
else frame_data_init <= frame_data_init_nxt;
 
// RAW Data from the frame buffer
reg [15:0] frame_data_o;
always @(posedge mclk or posedge puc_rst)
if (puc_rst) frame_data_o <= 16'h0000;
else if (fifo_pop) frame_data_o <= fifo_mem[rd_ptr];
 
// Data is ready
assign frame_data_ready_o = frame_data_init_nxt & (fifo_counter != FIFO_EMPTY);
 
// Read from FIFO command
assign read_from_fifo = ~refresh_active_i |
~frame_data_init |
((fifo_counter != FIFO_EMPTY) & frame_data_request_i);
 
 
endmodule // ogfx_backend_frame_fifo
 
`ifdef OGFX_NO_INCLUDE
`else
`include "openGFX430_undefines.v"
`endif
/core/rtl/verilog/ogfx_gpu_dma_addr.v
0,0 → 1,152
//----------------------------------------------------------------------------
// Copyright (C) 2015 Authors
//
// This source file may be used and distributed without restriction provided
// that this copyright statement is not removed from the file and that any
// derivative work contains the original copyright notice and the associated
// disclaimer.
//
// This source file is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This source is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
// License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this source; if not, write to the Free Software Foundation,
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
//----------------------------------------------------------------------------
//
// *File Name: ogfx_gpu_dma_addr.v
//
// *Module Description:
// Compute next Video-Ram address
//
// *Author(s):
// - Olivier Girard, olgirard@gmail.com
//
//----------------------------------------------------------------------------
// $Rev$
// $LastChangedBy$
// $LastChangedDate$
//----------------------------------------------------------------------------
`ifdef OGFX_NO_INCLUDE
`else
`include "openGFX430_defines.v"
`endif
 
module ogfx_gpu_dma_addr (
 
// OUTPUTs
vid_ram_addr_nxt_o, // Next Video-RAM address
 
// INPUTs
mclk, // Main system clock
puc_rst, // Main system reset
display_width_i, // Display width
gfx_mode_1_bpp_i, // Graphic mode 1 bpp resolution
gfx_mode_2_bpp_i, // Graphic mode 2 bpp resolution
gfx_mode_4_bpp_i, // Graphic mode 4 bpp resolution
gfx_mode_8_bpp_i, // Graphic mode 8 bpp resolution
gfx_mode_16_bpp_i, // Graphic mode 16 bpp resolution
vid_ram_addr_i, // Video-RAM address
vid_ram_addr_init_i, // Video-RAM address initialization
vid_ram_addr_step_i, // Video-RAM address step
vid_ram_width_i, // Video-RAM width
vid_ram_win_x_swap_i, // Video-RAM X-Swap configuration
vid_ram_win_y_swap_i, // Video-RAM Y-Swap configuration
vid_ram_win_cl_swap_i // Video-RAM CL-Swap configuration
);
 
// OUTPUTs
//=========
output [`APIX_MSB:0] vid_ram_addr_nxt_o; // Next Video-RAM address
 
// INPUTs
//=========
input mclk; // Main system clock
input puc_rst; // Main system reset
input [`LPIX_MSB:0] display_width_i; // Display width
input gfx_mode_1_bpp_i; // Graphic mode 1 bpp resolution
input gfx_mode_2_bpp_i; // Graphic mode 2 bpp resolution
input gfx_mode_4_bpp_i; // Graphic mode 4 bpp resolution
input gfx_mode_8_bpp_i; // Graphic mode 8 bpp resolution
input gfx_mode_16_bpp_i; // Graphic mode 16 bpp resolution
input [`APIX_MSB:0] vid_ram_addr_i; // Video-RAM address
input vid_ram_addr_init_i; // Video-RAM address initialization
input vid_ram_addr_step_i; // Video-RAM address step
input [`LPIX_MSB:0] vid_ram_width_i; // Video-RAM width
input vid_ram_win_x_swap_i; // Video-RAM X-Swap configuration
input vid_ram_win_y_swap_i; // Video-RAM Y-Swap configuration
input vid_ram_win_cl_swap_i; // Video-RAM CL-Swap configuration
 
 
//=============================================================================
// 1) COMPUTE NEXT MEMORY ACCESS
//=============================================================================
reg [`APIX_MSB:0] vid_ram_line_addr;
reg [`LPIX_MSB:0] vid_ram_column_count;
 
// Detect when the current line refresh is done
wire vid_ram_line_done = vid_ram_addr_step_i & (vid_ram_column_count==(vid_ram_width_i-{{`LPIX_MSB{1'b0}}, 1'b1}));
 
// Mux between initialization value and display width
wire [`LPIX_MSB:0] vid_ram_length_mux = vid_ram_addr_init_i ? vid_ram_width_i : display_width_i ;
 
// Align depending on graphic mode
wire [`LPIX_MSB+4:0] vid_ram_length_align = {`LPIX_MSB+5{gfx_mode_1_bpp_i }} & {4'b0000, vid_ram_length_mux[`LPIX_MSB:0] } |
{`LPIX_MSB+5{gfx_mode_2_bpp_i }} & {3'b000, vid_ram_length_mux[`LPIX_MSB:0], 1'b0 } |
{`LPIX_MSB+5{gfx_mode_4_bpp_i }} & {2'b00, vid_ram_length_mux[`LPIX_MSB:0], 2'b00 } |
{`LPIX_MSB+5{gfx_mode_8_bpp_i }} & {1'b0, vid_ram_length_mux[`LPIX_MSB:0], 3'b000 } |
{`LPIX_MSB+5{gfx_mode_16_bpp_i}} & { vid_ram_length_mux[`LPIX_MSB:0], 4'b0000} ;
 
wire [`APIX_MSB:0] plus_one_val = {`APIX_MSB+1{gfx_mode_1_bpp_i }} & {4'b0000, {{`VRAM_MSB{1'b0}}, 1'b1} } |
{`APIX_MSB+1{gfx_mode_2_bpp_i }} & {3'b000, {{`VRAM_MSB{1'b0}}, 1'b1}, 1'b0 } |
{`APIX_MSB+1{gfx_mode_4_bpp_i }} & {2'b00, {{`VRAM_MSB{1'b0}}, 1'b1}, 2'b00 } |
{`APIX_MSB+1{gfx_mode_8_bpp_i }} & {1'b0, {{`VRAM_MSB{1'b0}}, 1'b1}, 3'b000 } |
{`APIX_MSB+1{gfx_mode_16_bpp_i}} & { {{`VRAM_MSB{1'b0}}, 1'b1}, 4'b0000} ;
 
// Zero extension for LINT cleanup
wire [`APIX_MSB*3:0] vid_ram_length_norm = {{`APIX_MSB*3-`LPIX_MSB-4{1'b0}}, vid_ram_length_align};
 
// Select base address for next calculation
wire [`APIX_MSB:0] next_base_addr = (vid_ram_addr_init_i | ~vid_ram_line_done) ? vid_ram_addr_i :
vid_ram_line_addr ;
// Compute next address
wire [`APIX_MSB:0] next_addr = next_base_addr
+ (vid_ram_length_norm[`APIX_MSB:0] & {`APIX_MSB+1{~vid_ram_addr_init_i ? (~vid_ram_win_y_swap_i & (vid_ram_win_cl_swap_i ^ vid_ram_line_done)) : 1'b0}})
- (vid_ram_length_norm[`APIX_MSB:0] & {`APIX_MSB+1{~vid_ram_addr_init_i ? ( vid_ram_win_y_swap_i & (vid_ram_win_cl_swap_i ^ vid_ram_line_done)) : 1'b0}})
+ (plus_one_val & {`APIX_MSB+1{~vid_ram_addr_init_i ? (~vid_ram_win_x_swap_i & ~(vid_ram_win_cl_swap_i ^ vid_ram_line_done)) : 1'b0}})
- (plus_one_val & {`APIX_MSB+1{~vid_ram_addr_init_i ? ( vid_ram_win_x_swap_i & ~(vid_ram_win_cl_swap_i ^ vid_ram_line_done)) : 1'b0}});
 
wire update_line_addr = vid_ram_addr_init_i | vid_ram_line_done;
wire update_pixel_addr = update_line_addr | vid_ram_addr_step_i;
 
// Start RAM address of currentely refreshed line
always @(posedge mclk or posedge puc_rst)
if (puc_rst) vid_ram_line_addr <= {`APIX_MSB+1{1'b0}};
else if (update_line_addr) vid_ram_line_addr <= next_addr;
 
// Current RAM address of the currentely refreshed pixel
assign vid_ram_addr_nxt_o = update_pixel_addr ? next_addr : vid_ram_addr_i;
 
// Count the pixel number in the current line
// (used to detec the end of a line)
always @(posedge mclk or posedge puc_rst)
if (puc_rst) vid_ram_column_count <= {`LPIX_MSB+1{1'b0}};
else if (vid_ram_addr_init_i) vid_ram_column_count <= {`LPIX_MSB+1{1'b0}};
else if (vid_ram_line_done) vid_ram_column_count <= {`LPIX_MSB+1{1'b0}};
else if (vid_ram_addr_step_i) vid_ram_column_count <= vid_ram_column_count + {{`LPIX_MSB{1'b0}}, 1'b1};
 
 
endmodule // ogfx_calc_vram_addr
 
`ifdef OGFX_NO_INCLUDE
`else
`include "openGFX430_undefines.v"
`endif
/core/rtl/verilog/openGFX430_defines.v
0,0 → 1,213
//----------------------------------------------------------------------------
// Copyright (C) 2009 , Olivier Girard
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the authors nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
// THE POSSIBILITY OF SUCH DAMAGE
//
//----------------------------------------------------------------------------
//
// *File Name: openGFX430_defines.v
//
// *Module Description:
// oMSP Graphic Controller Configuration file
//
// *Author(s):
// - Olivier Girard, olgirard@gmail.com
//
//----------------------------------------------------------------------------
// $Rev: 103 $
// $LastChangedBy: olivier.girard $
// $LastChangedDate: 2011-03-05 15:44:48 +0100 (Sat, 05 Mar 2011) $
//----------------------------------------------------------------------------
//`define OGFX_NO_INCLUDE
`ifdef OGFX_NO_INCLUDE
`else
`include "openGFX430_undefines.v"
`endif
 
//============================================================================
// GRAPHIC CONTROLLER USER CONFIGURATION
//============================================================================
 
//-----------------------------------------------------
// Video display maximum pixel height/width
//-----------------------------------------------------
//`define MAX_DISPLAY_PIXEL_LENGTH_4096
//`define MAX_DISPLAY_PIXEL_LENGTH_2048
//`define MAX_DISPLAY_PIXEL_LENGTH_1024
`define MAX_DISPLAY_PIXEL_LENGTH_512
//`define MAX_DISPLAY_PIXEL_LENGTH_256
//`define MAX_DISPLAY_PIXEL_LENGTH_128
//`define MAX_DISPLAY_PIXEL_LENGTH_64
//`define MAX_DISPLAY_PIXEL_LENGTH_32
 
//-----------------------------------------------------
// Video memory address width
//-----------------------------------------------------
`define VRAM_AWIDTH 17
 
//-----------------------------------------------------
// Define if the Video memory is bigger than 4k Words
// (should be defined if VRAM_AWIDTH is bigger than 12)
//-----------------------------------------------------
`define VRAM_BIGGER_4_KW
 
//-----------------------------------------------------
// Include/Exclude Frame buffer pointers from the
// register map
// (Frame pointer 0 is always included)
//-----------------------------------------------------
`define WITH_FRAME1_POINTER
//`define WITH_FRAME2_POINTER
//`define WITH_FRAME3_POINTER
 
//-----------------------------------------------------
// LUT Configuration
//-----------------------------------------------------
`define WITH_PROGRAMMABLE_LUT
`define WITH_EXTRA_LUT_BANK
 
 
 
//==========================================================================//
//==========================================================================//
//==========================================================================//
//==========================================================================//
//===== SYSTEM CONSTANTS --- !!!!!!!! DO NOT EDIT !!!!!!!! =====//
//==========================================================================//
//==========================================================================//
//==========================================================================//
//==========================================================================//
 
`ifdef MAX_DISPLAY_PIXEL_LENGTH_4096
`define LPIX_MSB 11
`define LPIX_SIZE 4096
`define WITH_DISPLAY_SIZE_HI
`endif
`ifdef MAX_DISPLAY_PIXEL_LENGTH_2048
`define LPIX_MSB 10
`define LPIX_SIZE 2048
`define WITH_DISPLAY_SIZE_HI
`endif
`ifdef MAX_DISPLAY_PIXEL_LENGTH_1024
`define LPIX_MSB 9
`define LPIX_SIZE 1024
`define WITH_DISPLAY_SIZE_HI
`endif
`ifdef MAX_DISPLAY_PIXEL_LENGTH_512
`define LPIX_MSB 8
`define LPIX_SIZE 512
`define WITH_DISPLAY_SIZE_HI
`endif
`ifdef MAX_DISPLAY_PIXEL_LENGTH_256
`define LPIX_MSB 7
`define LPIX_SIZE 256
`endif
`ifdef MAX_DISPLAY_PIXEL_LENGTH_128
`define LPIX_MSB 6
`define LPIX_SIZE 128
`endif
`ifdef MAX_DISPLAY_PIXEL_LENGTH_64
`define LPIX_MSB 5
`define LPIX_SIZE 64
`endif
`ifdef MAX_DISPLAY_PIXEL_LENGTH_32
`define LPIX_MSB 4
`define LPIX_SIZE 32
`endif
`define SPIX_MSB (((`LPIX_MSB+1)*2)-1)
`ifdef WITH_DISPLAY_SIZE_HI
`define SPIX_HI_MSB (`SPIX_MSB-16)
`define SPIX_LO_MSB 15
`else
`define SPIX_LO_MSB `SPIX_MSB
`endif
 
`define VRAM_MSB (`VRAM_AWIDTH-1)
 
`define APIX_WIDTH (`VRAM_AWIDTH+4)
`define APIX_MSB (`APIX_WIDTH-1)
`ifdef VRAM_BIGGER_4_KW
`define APIX_HI_MSB (`APIX_MSB-16)
`define APIX_LO_MSB 15
`else
`define APIX_LO_MSB `APIX_MSB
`endif
 
`ifdef WITH_EXTRA_LUT_BANK
`define LRAM_AWIDTH 9
`else
`define LRAM_AWIDTH 8
`endif
`define LRAM_MSB (`LRAM_AWIDTH-1)
 
 
// Opcodes for GPU commands
`define OP_EXEC_FILL 2'b00
`define OP_EXEC_COPY 2'b01
`define OP_EXEC_COPY_TRANS 2'b10
`define OP_REC_WIDTH 4'b1100
`define OP_REC_HEIGHT 4'b1101
`define OP_SRC_PX_ADDR {4'b1111, 2'b10, 10'b0000000000}
`define OP_DST_PX_ADDR {4'b1111, 2'b10, 10'b0000000001}
`define OP_OF0_ADDR {4'b1111, 2'b10, 10'b0000010000}
`define OP_OF1_ADDR {4'b1111, 2'b10, 10'b0000010001}
`define OP_OF2_ADDR {4'b1111, 2'b10, 10'b0000010010}
`define OP_OF3_ADDR {4'b1111, 2'b10, 10'b0000010011}
`define OP_SET_FILL {4'b1111, 2'b01, 10'b0000100000}
`define OP_SET_TRANSPARENT {4'b1111, 2'b01, 10'b0000100001}
 
// Bit possitions of the GPU Command
`define SRC_OFFSET 13:12
`define SRC_X_SWAP 11
`define SRC_Y_SWAP 10
`define SRC_CL_SWAP 9
`define PX_OP 8:5
`define DST_OFFSET 4:3
`define DST_X_SWAP 2
`define DST_Y_SWAP 1
`define DST_CL_SWAP 0
 
 
//----------------------------------
// Configuration checkers
//----------------------------------
`ifdef WITH_FRAME2_POINTER
`ifdef WITH_FRAME1_POINTER
`else
GFX CONTROLLER CONFIGURATION ERROR: ENABLED FRAME2 POINTER WITHOUT FRAME1 POINTER
`endif
`endif
`ifdef WITH_FRAME3_POINTER
`ifdef WITH_FRAME2_POINTER
`else
GFX CONTROLLER CONFIGURATION ERROR: ENABLED FRAME2 POINTER WITHOUT FRAME1 POINTER
`endif
`endif
`ifdef WITH_PROGRAMMABLE_LUT
`else
`ifdef WITH_EXTRA_LUT_BANK
GFX CONTROLLER CONFIGURATION ERROR: NOT ALLOWED TO ENABLE EXTRA LUT BANK IF PROGRAMMABLE LUT SUPPORT IS DISABLED
`endif
`endif
/core/rtl/verilog/openGFX430_undefines.v
0,0 → 1,62
//----------------------------------------------------------------------------
// Copyright (C) 2009 , Olivier Girard
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the authors nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
// THE POSSIBILITY OF SUCH DAMAGE
//
//----------------------------------------------------------------------------
//
// *File Name: openGFX430_undefines.v
//
// *Module Description:
// oMSP Graphic Controller Verilog `undef file
//
// *Author(s):
// - Olivier Girard, olgirard@gmail.com
//
//----------------------------------------------------------------------------
// $Rev: 23 $
// $LastChangedBy: olivier.girard $
// $LastChangedDate: 2009-08-30 18:39:26 +0200 (Sun, 30 Aug 2009) $
//----------------------------------------------------------------------------
 
//----------------------------------------------------------------------------
// GRAPHIC CONTROLLER USER CONFIGURATION
//----------------------------------------------------------------------------
 
 
 
//==========================================================================//
//==========================================================================//
//==========================================================================//
//==========================================================================//
//===== SYSTEM CONSTANTS --- !!!!!!!! DO NOT EDIT !!!!!!!! =====//
//==========================================================================//
//==========================================================================//
//==========================================================================//
//==========================================================================//
 
//`ifdef TASSELx
//`undef TASSELx
//`endif
/core/rtl/verilog/openGFX430.v
0,0 → 1,482
//----------------------------------------------------------------------------
// Copyright (C) 2016 Authors
//
// This source file may be used and distributed without restriction provided
// that this copyright statement is not removed from the file and that any
// derivative work contains the original copyright notice and the associated
// disclaimer.
//
// This source file is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This source is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
// License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this source; if not, write to the Free Software Foundation,
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
//----------------------------------------------------------------------------
//
// *File Name: openGFX430.v
//
// *Module Description:
// This is a basic video controller for the openMSP430.
//
// It is currently supporting the LT24 LCD Board but
// can be extended to anything.
//
// *Author(s):
// - Olivier Girard, olgirard@gmail.com
//
//----------------------------------------------------------------------------
// $Rev$
// $LastChangedBy$
// $LastChangedDate$
//----------------------------------------------------------------------------
`ifdef OGFX_NO_INCLUDE
`else
`include "openGFX430_defines.v"
`endif
 
module openGFX430 (
 
// OUTPUTs
irq_gfx_o, // Graphic Controller interrupt
 
lt24_cs_n_o, // LT24 Chip select (Active low)
lt24_rd_n_o, // LT24 Read strobe (Active low)
lt24_wr_n_o, // LT24 Write strobe (Active low)
lt24_rs_o, // LT24 Command/Param selection (Cmd=0/Param=1)
lt24_d_o, // LT24 Data output
lt24_d_en_o, // LT24 Data output enable
lt24_reset_n_o, // LT24 Reset (Active Low)
lt24_on_o, // LT24 on/off
 
per_dout_o, // Peripheral data output
 
`ifdef WITH_PROGRAMMABLE_LUT
lut_ram_addr_o, // LUT-RAM address
lut_ram_wen_o, // LUT-RAM write enable (active low)
lut_ram_cen_o, // LUT-RAM enable (active low)
lut_ram_din_o, // LUT-RAM data input
`endif
 
vid_ram_addr_o, // Video-RAM address
vid_ram_wen_o, // Video-RAM write enable (active low)
vid_ram_cen_o, // Video-RAM enable (active low)
vid_ram_din_o, // Video-RAM data input
 
// INPUTs
dbg_freeze_i, // Freeze address auto-incr on read
mclk, // Main system clock
per_addr_i, // Peripheral address
per_din_i, // Peripheral data input
per_en_i, // Peripheral enable (high active)
per_we_i, // Peripheral write enable (high active)
puc_rst, // Main system reset
 
lt24_d_i, // LT24 Data input
 
`ifdef WITH_PROGRAMMABLE_LUT
lut_ram_dout_i, // LUT-RAM data output
`endif
vid_ram_dout_i // Video-RAM data output
);
 
// OUTPUTs
//=========
output irq_gfx_o; // Graphic Controller interrupt
 
output lt24_cs_n_o; // LT24 Chip select (Active low)
output lt24_rd_n_o; // LT24 Read strobe (Active low)
output lt24_wr_n_o; // LT24 Write strobe (Active low)
output lt24_rs_o; // LT24 Command/Param selection (Cmd=0/Param=1)
output [15:0] lt24_d_o; // LT24 Data output
output lt24_d_en_o; // LT24 Data output enable
output lt24_reset_n_o; // LT24 Reset (Active Low)
output lt24_on_o; // LT24 on/off
 
output [15:0] per_dout_o; // Peripheral data output
 
`ifdef WITH_PROGRAMMABLE_LUT
output [`LRAM_MSB:0] lut_ram_addr_o; // LUT-RAM address
output lut_ram_wen_o; // LUT-RAM write enable (active low)
output lut_ram_cen_o; // LUT-RAM enable (active low)
output [15:0] lut_ram_din_o; // LUT-RAM data input
`endif
 
output [`VRAM_MSB:0] vid_ram_addr_o; // Video-RAM address
output vid_ram_wen_o; // Video-RAM write enable (active low)
output vid_ram_cen_o; // Video-RAM enable (active low)
output [15:0] vid_ram_din_o; // Video-RAM data input
 
// INPUTs
//=========
input dbg_freeze_i; // Freeze address auto-incr on read
input mclk; // Main system clock
input [13:0] per_addr_i; // Peripheral address
input [15:0] per_din_i; // Peripheral data input
input per_en_i; // Peripheral enable (high active)
input [1:0] per_we_i; // Peripheral write enable (high active)
input puc_rst; // Main system reset
 
input [15:0] lt24_d_i; // LT24 Data input
 
`ifdef WITH_PROGRAMMABLE_LUT
input [15:0] lut_ram_dout_i; // LUT-RAM data output
`endif
input [15:0] vid_ram_dout_i; // Video-RAM data output
 
 
//=============================================================================
// 1) WIRE & PARAMETER DECLARATION
//=============================================================================
 
wire [2:0] lt24_cfg_clk;
wire [11:0] lt24_cfg_refr;
wire lt24_cfg_refr_sync_en;
wire [9:0] lt24_cfg_refr_sync_val;
wire lt24_cmd_refr;
wire [7:0] lt24_cmd_val;
wire lt24_cmd_has_param;
wire [15:0] lt24_cmd_param;
wire lt24_cmd_param_rdy;
wire [15:0] lt24_cmd_dfill;
wire lt24_cmd_dfill_wr;
 
wire [`LPIX_MSB:0] display_width;
wire [`LPIX_MSB:0] display_height;
wire [`SPIX_MSB:0] display_size;
wire display_y_swap;
wire display_x_swap;
wire display_cl_swap;
wire [2:0] gfx_mode;
 
wire [4:0] lt24_status;
wire lt24_done_evt;
wire lt24_start_evt;
 
`ifdef WITH_PROGRAMMABLE_LUT
wire [`LRAM_MSB:0] lut_ram_sw_addr;
wire [15:0] lut_ram_sw_din;
wire lut_ram_sw_wen;
wire lut_ram_sw_cen;
wire [15:0] lut_ram_sw_dout;
wire [`LRAM_MSB:0] lut_ram_refr_addr;
wire lut_ram_refr_cen;
wire [15:0] lut_ram_refr_dout;
wire lut_ram_refr_dout_rdy_nxt;
`endif
wire [`VRAM_MSB:0] vid_ram_sw_addr;
wire [15:0] vid_ram_sw_din;
wire vid_ram_sw_wen;
wire vid_ram_sw_cen;
wire [15:0] vid_ram_sw_dout;
wire [`VRAM_MSB:0] vid_ram_gpu_addr;
wire [15:0] vid_ram_gpu_din;
wire vid_ram_gpu_wen;
wire vid_ram_gpu_cen;
wire [15:0] vid_ram_gpu_dout;
wire vid_ram_gpu_dout_rdy_nxt;
wire [`VRAM_MSB:0] vid_ram_refr_addr;
wire vid_ram_refr_cen;
wire [15:0] vid_ram_refr_dout;
wire vid_ram_refr_dout_rdy_nxt;
 
wire refresh_active;
wire [15:0] refresh_data;
wire refresh_data_ready;
wire refresh_data_request;
wire [`APIX_MSB:0] refresh_frame_addr;
wire [1:0] refresh_lut_select;
 
wire gpu_cmd_done_evt;
wire gpu_cmd_error_evt;
wire gpu_get_data;
wire [15:0] gpu_data;
wire gpu_data_avail;
wire gpu_enable;
 
 
//============================================================================
// 2) REGISTERS
//============================================================================
 
ogfx_reg ogfx_reg_inst (
 
// OUTPUTs
.irq_gfx_o ( irq_gfx_o ), // Graphic Controller interrupt
 
.gpu_data_o ( gpu_data ), // GPU data
.gpu_data_avail_o ( gpu_data_avail ), // GPU data available
.gpu_enable_o ( gpu_enable ), // GPU enable
 
.lt24_reset_n_o ( lt24_reset_n_o ), // LT24 Reset (Active Low)
.lt24_on_o ( lt24_on_o ), // LT24 on/off
.lt24_cfg_clk_o ( lt24_cfg_clk ), // LT24 Interface clock configuration
.lt24_cfg_refr_o ( lt24_cfg_refr ), // LT24 Interface refresh configuration
.lt24_cfg_refr_sync_en_o ( lt24_cfg_refr_sync_en ), // LT24 Interface refresh sync enable configuration
.lt24_cfg_refr_sync_val_o ( lt24_cfg_refr_sync_val ), // LT24 Interface refresh sync value configuration
.lt24_cmd_refr_o ( lt24_cmd_refr ), // LT24 Interface refresh command
.lt24_cmd_val_o ( lt24_cmd_val ), // LT24 Generic command value
.lt24_cmd_has_param_o ( lt24_cmd_has_param ), // LT24 Generic command has parameters
.lt24_cmd_param_o ( lt24_cmd_param ), // LT24 Generic command parameter value
.lt24_cmd_param_rdy_o ( lt24_cmd_param_rdy ), // LT24 Generic command trigger
.lt24_cmd_dfill_o ( lt24_cmd_dfill ), // LT24 Data fill value
.lt24_cmd_dfill_wr_o ( lt24_cmd_dfill_wr ), // LT24 Data fill trigger
 
.display_width_o ( display_width ), // Display width
.display_height_o ( display_height ), // Display height
.display_size_o ( display_size ), // Display size (number of pixels)
.display_y_swap_o ( display_y_swap ), // Display configuration: swap Y axis (horizontal symmetry)
.display_x_swap_o ( display_x_swap ), // Display configuration: swap X axis (vertical symmetry)
.display_cl_swap_o ( display_cl_swap ), // Display configuration: swap column/lines
 
.gfx_mode_o ( gfx_mode ), // Video mode (1xx:16bpp / 011:8bpp / 010:4bpp / 001:2bpp / 000:1bpp)
 
.per_dout_o ( per_dout_o ), // Peripheral data output
 
.refresh_frame_addr_o ( refresh_frame_addr ), // Refresh frame base address
.refresh_lut_select_o ( refresh_lut_select ), // Refresh LUT bank selection
 
`ifdef WITH_PROGRAMMABLE_LUT
.lut_ram_addr_o ( lut_ram_sw_addr ), // LUT-RAM address
.lut_ram_din_o ( lut_ram_sw_din ), // LUT-RAM data
.lut_ram_wen_o ( lut_ram_sw_wen ), // LUT-RAM write strobe (active low)
.lut_ram_cen_o ( lut_ram_sw_cen ), // LUT-RAM chip enable (active low)
`endif
 
.vid_ram_addr_o ( vid_ram_sw_addr ), // Video-RAM address
.vid_ram_din_o ( vid_ram_sw_din ), // Video-RAM data
.vid_ram_wen_o ( vid_ram_sw_wen ), // Video-RAM write strobe (active low)
.vid_ram_cen_o ( vid_ram_sw_cen ), // Video-RAM chip enable (active low)
 
// INPUTs
.dbg_freeze_i ( dbg_freeze_i ), // Freeze address auto-incr on read
.gpu_cmd_done_evt_i ( gpu_cmd_done_evt ), // GPU command done event
.gpu_cmd_error_evt_i ( gpu_cmd_error_evt ), // GPU command error event
.gpu_get_data_i ( gpu_get_data ), // GPU get next data
.lt24_status_i ( lt24_status ), // LT24 FSM Status
.lt24_start_evt_i ( lt24_start_evt ), // LT24 FSM start event
.lt24_done_evt_i ( lt24_done_evt ), // LT24 FSM done event
.mclk ( mclk ), // Main system clock
.per_addr_i ( per_addr_i ), // Peripheral address
.per_din_i ( per_din_i ), // Peripheral data input
.per_en_i ( per_en_i ), // Peripheral enable (high active)
.per_we_i ( per_we_i ), // Peripheral write enable (high active)
.puc_rst ( puc_rst ), // Main system reset
 
`ifdef WITH_PROGRAMMABLE_LUT
.lut_ram_dout_i ( lut_ram_sw_dout ), // LUT-RAM data input
`endif
.vid_ram_dout_i ( vid_ram_sw_dout ) // Video-RAM data input
);
 
 
//============================================================================
// 3) GPU
//============================================================================
 
ogfx_gpu ogfx_gpu_inst (
 
// OUTPUTs
.gpu_cmd_done_evt_o ( gpu_cmd_done_evt ), // GPU command done event
.gpu_cmd_error_evt_o ( gpu_cmd_error_evt ), // GPU command error event
.gpu_get_data_o ( gpu_get_data ), // GPU get next data
 
.vid_ram_addr_o ( vid_ram_gpu_addr ), // Video-RAM address
.vid_ram_din_o ( vid_ram_gpu_din ), // Video-RAM data
.vid_ram_wen_o ( vid_ram_gpu_wen ), // Video-RAM write strobe (active low)
.vid_ram_cen_o ( vid_ram_gpu_cen ), // Video-RAM chip enable (active low)
 
// INPUTs
.mclk ( mclk ), // Main system clock
.puc_rst ( puc_rst ), // Main system reset
 
.display_width_i ( display_width ), // Display width
 
.gfx_mode_i ( gfx_mode ), // Video mode (1xx:16bpp / 011:8bpp / 010:4bpp / 001:2bpp / 000:1bpp)
 
.gpu_data_i ( gpu_data ), // GPU data
.gpu_data_avail_i ( gpu_data_avail ), // GPU data available
.gpu_enable_i ( gpu_enable ), // GPU enable
 
.vid_ram_dout_i ( vid_ram_gpu_dout ), // Video-RAM data input
.vid_ram_dout_rdy_nxt_i ( vid_ram_gpu_dout_rdy_nxt ) // Video-RAM data output ready during next cycle
);
 
 
//============================================================================
// 4) LT24 INTERFACE
//============================================================================
 
ogfx_if_lt24 ogfx_if_lt24_inst (
 
// OUTPUTs
.event_fsm_done_o ( lt24_done_evt ), // LT24 FSM done event
.event_fsm_start_o ( lt24_start_evt ), // LT24 FSM start event
 
.lt24_cs_n_o ( lt24_cs_n_o ), // LT24 Chip select (Active low)
.lt24_d_o ( lt24_d_o ), // LT24 Data output
.lt24_d_en_o ( lt24_d_en_o ), // LT24 Data output enable
.lt24_rd_n_o ( lt24_rd_n_o ), // LT24 Read strobe (Active low)
.lt24_rs_o ( lt24_rs_o ), // LT24 Command/Param selection (Cmd=0/Param=1)
.lt24_wr_n_o ( lt24_wr_n_o ), // LT24 Write strobe (Active low)
 
.refresh_active_o ( refresh_active ), // Display refresh on going
.refresh_data_request_o ( refresh_data_request ), // Display refresh new data request
 
.status_o ( lt24_status ), // LT24 FSM Status
 
// INPUTs
.mclk ( mclk ), // Main system clock
.puc_rst ( puc_rst ), // Main system reset
 
.cfg_lt24_clk_div_i ( lt24_cfg_clk ), // Clock Divider configuration for LT24 interface
.cfg_lt24_display_size_i ( display_size ), // Display size (number of pixels)
.cfg_lt24_refresh_i ( lt24_cfg_refr ), // Refresh rate configuration for LT24 interface
.cfg_lt24_refresh_sync_en_i ( lt24_cfg_refr_sync_en ), // Refresh sync enable configuration for LT24 interface
.cfg_lt24_refresh_sync_val_i ( lt24_cfg_refr_sync_val ), // Refresh sync value configuration for LT24 interface
 
.cmd_dfill_i ( lt24_cmd_dfill ), // Display data fill
.cmd_dfill_trig_i ( lt24_cmd_dfill_wr ), // Trigger a full display data fill
 
.cmd_generic_cmd_val_i ( lt24_cmd_val ), // Generic command value
.cmd_generic_has_param_i ( lt24_cmd_has_param ), // Generic command to be sent has parameter(s)
.cmd_generic_param_val_i ( lt24_cmd_param ), // Generic command parameter value
.cmd_generic_trig_i ( lt24_cmd_param_rdy ), // Trigger generic command transmit (or new parameter available)
 
.cmd_refresh_i ( lt24_cmd_refr ), // Display refresh command
 
.lt24_d_i ( lt24_d_i ), // LT24 Data input
 
.refresh_data_i ( refresh_data ), // Display refresh data
.refresh_data_ready_i ( refresh_data_ready ) // Display refresh new data is ready
);
 
//============================================================================
// 5) VIDEO BACKEND
//============================================================================
 
// Video Backend
ogfx_backend ogfx_backend_inst (
 
// OUTPUTs
.refresh_data_o ( refresh_data ), // Display refresh data
.refresh_data_ready_o ( refresh_data_ready ), // Display refresh new data is ready
 
.vid_ram_addr_o ( vid_ram_refr_addr ), // Video-RAM address
.vid_ram_cen_o ( vid_ram_refr_cen ), // Video-RAM enable (active low)
 
`ifdef WITH_PROGRAMMABLE_LUT
.lut_ram_addr_o ( lut_ram_refr_addr ), // LUT-RAM address
.lut_ram_cen_o ( lut_ram_refr_cen ), // LUT-RAM enable (active low)
`endif
 
// INPUTs
.mclk ( mclk ), // Main system clock
.puc_rst ( puc_rst ), // Main system reset
 
.display_width_i ( display_width ), // Display width
.display_height_i ( display_height ), // Display height
.display_size_i ( display_size ), // Display size (number of pixels)
.display_y_swap_i ( display_y_swap ), // Display configuration: swap Y axis (horizontal symmetry)
.display_x_swap_i ( display_x_swap ), // Display configuration: swap X axis (vertical symmetry)
.display_cl_swap_i ( display_cl_swap ), // Display configuration: swap column/lines
 
.gfx_mode_i ( gfx_mode ), // Video mode (1xx:16bpp / 011:8bpp / 010:4bpp / 001:2bpp / 000:1bpp)
 
`ifdef WITH_PROGRAMMABLE_LUT
.lut_ram_dout_i ( lut_ram_refr_dout ), // LUT-RAM data output
.lut_ram_dout_rdy_nxt_i ( lut_ram_refr_dout_rdy_nxt ), // LUT-RAM data output ready during next cycle
`endif
 
.vid_ram_dout_i ( vid_ram_refr_dout ), // Video-RAM data output
.vid_ram_dout_rdy_nxt_i ( vid_ram_refr_dout_rdy_nxt ), // Video-RAM data output ready during next cycle
 
.refresh_active_i ( refresh_active ), // Display refresh on going
.refresh_data_request_i ( refresh_data_request ), // Display refresh new data request
.refresh_frame_base_addr_i ( refresh_frame_addr ), // Refresh frame base address
.refresh_lut_select_i ( refresh_lut_select ) // Refresh LUT bank selection
);
 
//============================================================================
// 6) ARBITER FOR VIDEO AND LUT MEMORIES
//============================================================================
 
ogfx_ram_arbiter ogfx_ram_arbiter_inst (
 
.mclk ( mclk ), // Main system clock
.puc_rst ( puc_rst ), // Main system reset
 
//------------------------------------------------------------
 
// SW interface, fixed highest priority
.lut_ram_sw_addr_i ( lut_ram_sw_addr ), // LUT-RAM Software address
.lut_ram_sw_din_i ( lut_ram_sw_din ), // LUT-RAM Software data
.lut_ram_sw_wen_i ( lut_ram_sw_wen ), // LUT-RAM Software write strobe (active low)
.lut_ram_sw_cen_i ( lut_ram_sw_cen ), // LUT-RAM Software chip enable (active low)
.lut_ram_sw_dout_o ( lut_ram_sw_dout ), // LUT-RAM Software data input
 
// Refresh-backend, fixed lowest priority
.lut_ram_refr_addr_i ( lut_ram_refr_addr ), // LUT-RAM Refresh address
.lut_ram_refr_din_i ( 16'h0000 ), // LUT-RAM Refresh data
.lut_ram_refr_wen_i ( 1'h1 ), // LUT-RAM Refresh write strobe (active low)
.lut_ram_refr_cen_i ( lut_ram_refr_cen ), // LUT-RAM Refresh enable (active low)
.lut_ram_refr_dout_o ( lut_ram_refr_dout ), // LUT-RAM Refresh data output
.lut_ram_refr_dout_rdy_nxt_o ( lut_ram_refr_dout_rdy_nxt ), // LUT-RAM Refresh data output ready during next cycle
 
// LUT Memory interface
.lut_ram_addr_o ( lut_ram_addr_o ), // LUT-RAM address
.lut_ram_din_o ( lut_ram_din_o ), // LUT-RAM data
.lut_ram_wen_o ( lut_ram_wen_o ), // LUT-RAM write strobe (active low)
.lut_ram_cen_o ( lut_ram_cen_o ), // LUT-RAM chip enable (active low)
.lut_ram_dout_i ( lut_ram_dout_i ), // LUT-RAM data input
 
//------------------------------------------------------------
 
// SW interface, fixed highest priority
.vid_ram_sw_addr_i ( vid_ram_sw_addr ), // Video-RAM Software address
.vid_ram_sw_din_i ( vid_ram_sw_din ), // Video-RAM Software data
.vid_ram_sw_wen_i ( vid_ram_sw_wen ), // Video-RAM Software write strobe (active low)
.vid_ram_sw_cen_i ( vid_ram_sw_cen ), // Video-RAM Software chip enable (active low)
.vid_ram_sw_dout_o ( vid_ram_sw_dout ), // Video-RAM Software data input
 
// GPU interface (round-robin with refresh-backend)
.vid_ram_gpu_addr_i ( vid_ram_gpu_addr ), // Video-RAM GPU address
.vid_ram_gpu_din_i ( vid_ram_gpu_din ), // Video-RAM GPU data
.vid_ram_gpu_wen_i ( vid_ram_gpu_wen ), // Video-RAM GPU write strobe (active low)
.vid_ram_gpu_cen_i ( vid_ram_gpu_cen ), // Video-RAM GPU chip enable (active low)
.vid_ram_gpu_dout_o ( vid_ram_gpu_dout ), // Video-RAM GPU data input
.vid_ram_gpu_dout_rdy_nxt_o ( vid_ram_gpu_dout_rdy_nxt ), // Video-RAM GPU data output ready during next cycle
 
// Refresh-backend (round-robin with GPU interface)
.vid_ram_refr_addr_i ( vid_ram_refr_addr ), // Video-RAM Refresh address
.vid_ram_refr_din_i ( 16'h0000 ), // Video-RAM Refresh data
.vid_ram_refr_wen_i ( 1'h1 ), // Video-RAM Refresh write strobe (active low)
.vid_ram_refr_cen_i ( vid_ram_refr_cen ), // Video-RAM Refresh enable (active low)
.vid_ram_refr_dout_o ( vid_ram_refr_dout ), // Video-RAM Refresh data output
.vid_ram_refr_dout_rdy_nxt_o ( vid_ram_refr_dout_rdy_nxt ), // Video-RAM Refresh data output ready during next cycle
 
// Video Memory interface
.vid_ram_addr_o ( vid_ram_addr_o ), // Video-RAM address
.vid_ram_din_o ( vid_ram_din_o ), // Video-RAM data
.vid_ram_wen_o ( vid_ram_wen_o ), // Video-RAM write strobe (active low)
.vid_ram_cen_o ( vid_ram_cen_o ), // Video-RAM chip enable (active low)
.vid_ram_dout_i ( vid_ram_dout_i ) // Video-RAM data input
 
//------------------------------------------------------------
);
 
 
endmodule // openGFX430
 
`ifdef OGFX_NO_INCLUDE
`else
`include "openGFX430_undefines.v"
`endif
/core/rtl/verilog/ogfx_gpu_dma.v
0,0 → 1,558
//----------------------------------------------------------------------------
// Copyright (C) 2015 Authors
//
// This source file may be used and distributed without restriction provided
// that this copyright statement is not removed from the file and that any
// derivative work contains the original copyright notice and the associated
// disclaimer.
//
// This source file is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This source is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
// License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this source; if not, write to the Free Software Foundation,
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
//----------------------------------------------------------------------------
//
// *File Name: ogfx_gpu_dma.v
//
// *Module Description:
// Graphic-Processing unit 2D-DMA.
//
// *Author(s):
// - Olivier Girard, olgirard@gmail.com
//
//----------------------------------------------------------------------------
// $Rev$
// $LastChangedBy$
// $LastChangedDate$
//----------------------------------------------------------------------------
`ifdef OGFX_NO_INCLUDE
`else
`include "openGFX430_defines.v"
`endif
 
module ogfx_gpu_dma (
 
// OUTPUTs
gpu_exec_done_o, // GPU execution done
 
vid_ram_addr_o, // Video-RAM address
vid_ram_din_o, // Video-RAM data
vid_ram_wen_o, // Video-RAM write strobe (active low)
vid_ram_cen_o, // Video-RAM chip enable (active low)
 
// INPUTs
mclk, // Main system clock
puc_rst, // Main system reset
 
cfg_dst_px_addr_i, // Destination pixel address configuration
cfg_dst_cl_swp_i, // Destination Column/Line-Swap configuration
cfg_dst_x_swp_i, // Destination X-Swap configuration
cfg_dst_y_swp_i, // Destination Y-Swap configuration
cfg_fill_color_i, // Fill color (for rectangle fill operation)
cfg_pix_op_sel_i, // Pixel operation to be performed during the copy
cfg_rec_width_i, // Rectangle width configuration
cfg_rec_height_i, // Rectangle height configuration
cfg_src_px_addr_i, // Source pixel address configuration
cfg_src_cl_swp_i, // Source Column/Line-Swap configuration
cfg_src_x_swp_i, // Source X-Swap configuration
cfg_src_y_swp_i, // Source Y-Swap configuration
cfg_transparent_color_i, // Transparent color (for rectangle transparent copy operation)
 
display_width_i, // Display width
 
gfx_mode_i, // Video mode (1xx:16bpp / 011:8bpp / 010:4bpp / 001:2bpp / 000:1bpp)
 
gpu_enable_i, // GPU enable
 
exec_fill_i, // Rectangle fill on going
exec_copy_i, // Rectangle copy on going
exec_copy_trans_i, // Rectangle transparent copy on going
trig_exec_i, // Trigger rectangle execution
 
vid_ram_dout_i, // Video-RAM data input
vid_ram_dout_rdy_nxt_i // Video-RAM data output ready during next cycle
);
 
// OUTPUTs
//=========
output gpu_exec_done_o; // GPU execution done
 
output [`VRAM_MSB:0] vid_ram_addr_o; // Video-RAM address
output [15:0] vid_ram_din_o; // Video-RAM data
output vid_ram_wen_o; // Video-RAM write strobe (active low)
output vid_ram_cen_o; // Video-RAM chip enable (active low)
 
// INPUTs
//=========
input mclk; // Main system clock
input puc_rst; // Main system reset
 
input [`APIX_MSB:0] cfg_dst_px_addr_i; // Destination pixel address configuration
input cfg_dst_cl_swp_i; // Destination Column/Line-Swap configuration
input cfg_dst_x_swp_i; // Destination X-Swap configuration
input cfg_dst_y_swp_i; // Destination Y-Swap configuration
input [15:0] cfg_fill_color_i; // Fill color (for rectangle fill operation)
input [3:0] cfg_pix_op_sel_i; // Pixel operation to be performed during the copy
input [`LPIX_MSB:0] cfg_rec_width_i; // Rectangle width configuration
input [`LPIX_MSB:0] cfg_rec_height_i; // Rectangle height configuration
input [`APIX_MSB:0] cfg_src_px_addr_i; // Source pixel address configuration
input cfg_src_cl_swp_i; // Source Column/Line-Swap configuration
input cfg_src_x_swp_i; // Source X-Swap configuration
input cfg_src_y_swp_i; // Source Y-Swap configuration
input [15:0] cfg_transparent_color_i; // Transparent color (for rectangle transparent copy operation)
 
input [`LPIX_MSB:0] display_width_i; // Display width
 
input [2:0] gfx_mode_i; // Video mode (1xx:16bpp / 011:8bpp / 010:4bpp / 001:2bpp / 000:1bpp)
 
input gpu_enable_i; // GPU enable
 
input exec_fill_i; // Rectangle fill on going
input exec_copy_i; // Rectangle copy on going
input exec_copy_trans_i; // Rectangle transparent copy on going
input trig_exec_i; // Trigger rectangle execution
 
input [15:0] vid_ram_dout_i; // Video-RAM data input
input vid_ram_dout_rdy_nxt_i; // Video-RAM data output ready during next cycle
 
 
//=============================================================================
// 1) WIRE, REGISTERS AND PARAMETER DECLARATION
//=============================================================================
 
// Video modes decoding
wire gfx_mode_1_bpp = (gfx_mode_i == 3'b000);
wire gfx_mode_2_bpp = (gfx_mode_i == 3'b001);
wire gfx_mode_4_bpp = (gfx_mode_i == 3'b010);
wire gfx_mode_8_bpp = (gfx_mode_i == 3'b011);
wire gfx_mode_16_bpp = ~(gfx_mode_8_bpp | gfx_mode_4_bpp | gfx_mode_2_bpp | gfx_mode_1_bpp);
 
 
// Pixel operation decoding
wire pix_op_00 = (cfg_pix_op_sel_i == 4'b0000); // S
wire pix_op_01 = (cfg_pix_op_sel_i == 4'b0001); // not S
wire pix_op_02 = (cfg_pix_op_sel_i == 4'b0010); // not D
 
wire pix_op_03 = (cfg_pix_op_sel_i == 4'b0011); // S and D
wire pix_op_04 = (cfg_pix_op_sel_i == 4'b0100); // S or D
wire pix_op_05 = (cfg_pix_op_sel_i == 4'b0101); // S xor D
 
wire pix_op_06 = (cfg_pix_op_sel_i == 4'b0110); // not (S and D)
wire pix_op_07 = (cfg_pix_op_sel_i == 4'b0111); // not (S or D)
wire pix_op_08 = (cfg_pix_op_sel_i == 4'b1000); // not (S xor D)
 
wire pix_op_09 = (cfg_pix_op_sel_i == 4'b1001); // (not S) and D
wire pix_op_10 = (cfg_pix_op_sel_i == 4'b1010); // S and (not D)
wire pix_op_11 = (cfg_pix_op_sel_i == 4'b1011); // (not S) or D
wire pix_op_12 = (cfg_pix_op_sel_i == 4'b1100); // S or (not D)
 
wire pix_op_13 = (cfg_pix_op_sel_i == 4'b1101); // Fill 0 if S not transparent
wire pix_op_14 = (cfg_pix_op_sel_i == 4'b1110); // Fill 1 if S not transparent
wire pix_op_15 = (cfg_pix_op_sel_i == 4'b1111); // Fill 'fill_color' if S not transparent
 
wire dma_done;
wire pixel_is_transparent;
 
// 16 bits one-hot decoder
function [15:0] one_hot16;
input [3:0] binary;
begin
one_hot16 = 16'h0000;
one_hot16[binary] = 1'b1;
end
endfunction
 
 
//=============================================================================
// 2) DMA STATE MACHINE
//=============================================================================
 
// State definition
parameter IDLE = 3'h0;
parameter INIT = 3'h1;
parameter SKIP = 3'h2;
parameter SRC_READ = 3'h3;
parameter DST_READ = 3'h4;
parameter DST_WRITE = 3'h5;
 
// State machine
reg [2:0] dma_state;
reg [2:0] dma_state_nxt;
 
// State arcs
wire needs_src_read = (exec_copy_i & ~pix_op_02) | exec_copy_trans_i;
wire needs_dst_read = (exec_fill_i | exec_copy_trans_i | exec_copy_i) & (~(pix_op_00 | pix_op_01 | pix_op_13 | pix_op_14 | pix_op_15) | ~gfx_mode_16_bpp);
wire needs_dst_write = (exec_fill_i | exec_copy_trans_i | exec_copy_i) & ~pixel_is_transparent;
 
wire data_ready_nxt = (dma_state==SRC_READ) |
(((dma_state==DST_READ) |
(dma_state==DST_WRITE)) & ~pixel_is_transparent) ? vid_ram_dout_rdy_nxt_i : 1'b1;
 
// State transition
always @(dma_state or trig_exec_i or needs_src_read or needs_dst_read or data_ready_nxt or dma_done or needs_dst_write)
case (dma_state)
IDLE : dma_state_nxt = ~trig_exec_i ? IDLE : INIT ;
 
INIT : dma_state_nxt = needs_src_read ? SRC_READ :
needs_dst_read ? DST_READ :
needs_dst_write ? DST_WRITE : SKIP ;
 
SKIP : dma_state_nxt = dma_done ? IDLE : SKIP ;
 
SRC_READ : dma_state_nxt = ~data_ready_nxt ? SRC_READ :
needs_dst_read ? DST_READ : DST_WRITE ;
 
DST_READ : dma_state_nxt = ~data_ready_nxt ? DST_READ :
needs_dst_write ? DST_WRITE :
dma_done ? IDLE : SRC_READ ;
 
DST_WRITE : dma_state_nxt = ~data_ready_nxt ? DST_WRITE :
dma_done ? IDLE :
needs_src_read ? SRC_READ :
needs_dst_read ? DST_READ : DST_WRITE ;
// pragma coverage off
default : dma_state_nxt = IDLE;
// pragma coverage on
endcase
 
// State machine
always @(posedge mclk or posedge puc_rst)
if (puc_rst) dma_state <= IDLE;
else if (~gpu_enable_i) dma_state <= IDLE;
else dma_state <= dma_state_nxt;
 
 
// Utility signals
wire dma_init = (dma_state==INIT);
wire dma_pixel_done = (dma_state==SKIP) | ((dma_state==DST_READ) & pixel_is_transparent) |
((dma_state==DST_WRITE) & data_ready_nxt ) ;
assign gpu_exec_done_o = (dma_state==IDLE) & ~trig_exec_i;
 
 
//=============================================================================
// 3) COUNT TRANSFERS
//=============================================================================
reg [`LPIX_MSB:0] height_cnt;
wire height_cnt_done;
reg [`LPIX_MSB:0] width_cnt;
wire width_cnt_done;
 
// Height Counter
wire height_cnt_init = dma_init;
wire height_cnt_dec = dma_pixel_done & width_cnt_done & ~height_cnt_done;
 
always @(posedge mclk or posedge puc_rst)
if (puc_rst) height_cnt <= {{`LPIX_MSB{1'h0}},1'b1};
else if (height_cnt_init) height_cnt <= cfg_rec_height_i;
else if (height_cnt_dec) height_cnt <= height_cnt-{{`LPIX_MSB{1'h0}},1'b1};
 
assign height_cnt_done = (height_cnt=={{`LPIX_MSB{1'h0}}, 1'b1});
 
// Width Counter
wire width_cnt_init = dma_init | height_cnt_dec;
wire width_cnt_dec = dma_pixel_done & ~width_cnt_done;
 
always @(posedge mclk or posedge puc_rst)
if (puc_rst) width_cnt <= {{`LPIX_MSB{1'h0}},1'b1};
else if (width_cnt_init) width_cnt <= cfg_rec_width_i;
else if (width_cnt_dec) width_cnt <= width_cnt-{{`LPIX_MSB{1'h0}},1'b1};
 
assign width_cnt_done = (width_cnt=={{`LPIX_MSB{1'h0}}, 1'b1});
 
// DMA Transfer is done when both counters are done
assign dma_done = height_cnt_done & width_cnt_done;
 
 
//=============================================================================
// 4) SOURCE ADDRESS GENERATION
//=============================================================================
 
reg [`APIX_MSB:0] vram_src_addr;
wire [`APIX_MSB:0] vram_src_addr_calc;
 
wire vram_src_addr_inc = dma_pixel_done & needs_src_read;
wire [`APIX_MSB:0] vram_src_addr_nxt = trig_exec_i ? cfg_src_px_addr_i : vram_src_addr_calc;
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) vram_src_addr <= {`APIX_MSB+1{1'b0}};
else if (trig_exec_i | vram_src_addr_inc) vram_src_addr <= vram_src_addr_nxt;
 
 
// Compute the next address
ogfx_gpu_dma_addr ogfx_gpu_dma_src_addr_inst (
 
// OUTPUTs
.vid_ram_addr_nxt_o ( vram_src_addr_calc ), // Next Video-RAM address
 
// INPUTs
.mclk ( mclk ), // Main system clock
.puc_rst ( puc_rst ), // Main system reset
.display_width_i ( display_width_i ), // Display width
.gfx_mode_1_bpp_i ( gfx_mode_1_bpp ), // Graphic mode 1 bpp resolution
.gfx_mode_2_bpp_i ( gfx_mode_2_bpp ), // Graphic mode 2 bpp resolution
.gfx_mode_4_bpp_i ( gfx_mode_4_bpp ), // Graphic mode 4 bpp resolution
.gfx_mode_8_bpp_i ( gfx_mode_8_bpp ), // Graphic mode 8 bpp resolution
.gfx_mode_16_bpp_i ( gfx_mode_16_bpp ), // Graphic mode 16 bpp resolution
.vid_ram_addr_i ( vram_src_addr ), // Video-RAM address
.vid_ram_addr_init_i ( dma_init ), // Video-RAM address initialization
.vid_ram_addr_step_i ( vram_src_addr_inc ), // Video-RAM address step
.vid_ram_width_i ( cfg_rec_width_i ), // Video-RAM width
.vid_ram_win_x_swap_i ( cfg_src_x_swp_i ), // Video-RAM X-Swap configuration
.vid_ram_win_y_swap_i ( cfg_src_y_swp_i ), // Video-RAM Y-Swap configuration
.vid_ram_win_cl_swap_i ( cfg_src_cl_swp_i ) // Video-RAM CL-Swap configuration
);
 
//=============================================================================
// 5) SOURCE DATA MASK
//=============================================================================
 
reg [15:0] vram_src_mask;
wire [15:0] vram_src_mask_shift = one_hot16(vram_src_addr_nxt[3:0]);
wire [15:0] vram_src_mask_vram_nxt = ({16{gfx_mode_1_bpp }} & vram_src_mask_shift ) |
({16{gfx_mode_2_bpp }} & {{2{vram_src_mask_shift[14]}},
{2{vram_src_mask_shift[12]}},
{2{vram_src_mask_shift[10]}},
{2{vram_src_mask_shift[8] }},
{2{vram_src_mask_shift[6] }},
{2{vram_src_mask_shift[4] }},
{2{vram_src_mask_shift[2] }},
{2{vram_src_mask_shift[0] }}}) |
({16{gfx_mode_4_bpp }} & {{4{vram_src_mask_shift[12]}},
{4{vram_src_mask_shift[8] }},
{4{vram_src_mask_shift[4] }},
{4{vram_src_mask_shift[0] }}}) |
({16{gfx_mode_8_bpp }} & {{8{vram_src_mask_shift[8] }},
{8{vram_src_mask_shift[0] }}}) |
({16{gfx_mode_16_bpp}} & {16{1'b1}} ) ;
 
wire [15:0] vram_src_mask_fill_nxt = ({16{gfx_mode_1_bpp }} & 16'h0001) |
({16{gfx_mode_2_bpp }} & 16'h0003) |
({16{gfx_mode_4_bpp }} & 16'h000f) |
({16{gfx_mode_8_bpp }} & 16'h00ff) |
({16{gfx_mode_16_bpp}} & 16'hffff) ;
 
wire [15:0] vram_src_mask_nxt = exec_fill_i ? vram_src_mask_fill_nxt :
vram_src_mask_vram_nxt ;
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) vram_src_mask <= 16'h0000;
else if (trig_exec_i | vram_src_addr_inc) vram_src_mask <= vram_src_mask_nxt;
 
 
//=============================================================================
// 6) DESTINATION ADDRESS GENERATION
//=============================================================================
 
reg [`APIX_MSB:0] vram_dst_addr;
wire [`APIX_MSB:0] vram_dst_addr_calc;
 
wire vram_dst_addr_inc = dma_pixel_done;
wire [`APIX_MSB:0] vram_dst_addr_nxt = trig_exec_i ? cfg_dst_px_addr_i : vram_dst_addr_calc;
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) vram_dst_addr <= {`APIX_MSB+1{1'b0}};
else if (trig_exec_i | vram_dst_addr_inc) vram_dst_addr <= vram_dst_addr_nxt;
 
 
// Compute the next address
ogfx_gpu_dma_addr ogfx_gpu_dma_dst_addr_inst (
 
// OUTPUTs
.vid_ram_addr_nxt_o ( vram_dst_addr_calc ), // Next Video-RAM address
 
// INPUTs
.mclk ( mclk ), // Main system clock
.puc_rst ( puc_rst ), // Main system reset
.display_width_i ( display_width_i ), // Display width
.gfx_mode_1_bpp_i ( gfx_mode_1_bpp ), // Graphic mode 1 bpp resolution
.gfx_mode_2_bpp_i ( gfx_mode_2_bpp ), // Graphic mode 2 bpp resolution
.gfx_mode_4_bpp_i ( gfx_mode_4_bpp ), // Graphic mode 4 bpp resolution
.gfx_mode_8_bpp_i ( gfx_mode_8_bpp ), // Graphic mode 8 bpp resolution
.gfx_mode_16_bpp_i ( gfx_mode_16_bpp ), // Graphic mode 16 bpp resolution
.vid_ram_addr_i ( vram_dst_addr ), // Video-RAM address
.vid_ram_addr_init_i ( dma_init ), // Video-RAM address initialization
.vid_ram_addr_step_i ( vram_dst_addr_inc ), // Video-RAM address step
.vid_ram_width_i ( cfg_rec_width_i ), // Video-RAM width
.vid_ram_win_x_swap_i ( cfg_dst_x_swp_i ), // Video-RAM X-Swap configuration
.vid_ram_win_y_swap_i ( cfg_dst_y_swp_i ), // Video-RAM Y-Swap configuration
.vid_ram_win_cl_swap_i ( cfg_dst_cl_swp_i ) // Video-RAM CL-Swap configuration
);
 
//=============================================================================
// 7) DESTINATION DATA MASK
//=============================================================================
 
reg [15:0] vram_dst_mask;
wire [15:0] vram_dst_mask_shift = one_hot16(vram_dst_addr_nxt[3:0]);
wire [15:0] vram_dst_mask_nxt = ({16{gfx_mode_1_bpp }} & vram_dst_mask_shift ) |
({16{gfx_mode_2_bpp }} & {{2{vram_dst_mask_shift[14]}},
{2{vram_dst_mask_shift[12]}},
{2{vram_dst_mask_shift[10]}},
{2{vram_dst_mask_shift[8] }},
{2{vram_dst_mask_shift[6] }},
{2{vram_dst_mask_shift[4] }},
{2{vram_dst_mask_shift[2] }},
{2{vram_dst_mask_shift[0] }}}) |
({16{gfx_mode_4_bpp }} & {{4{vram_dst_mask_shift[12]}},
{4{vram_dst_mask_shift[8] }},
{4{vram_dst_mask_shift[4] }},
{4{vram_dst_mask_shift[0] }}}) |
({16{gfx_mode_8_bpp }} & {{8{vram_dst_mask_shift[8] }},
{8{vram_dst_mask_shift[0] }}}) |
({16{gfx_mode_16_bpp}} & {16{1'b1}} ) ;
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) vram_dst_mask <= 16'h0000;
else if (trig_exec_i | vram_dst_addr_inc) vram_dst_mask <= vram_dst_mask_nxt;
 
 
//=============================================================================
// 8) VIDEO-MEMORY INTERFACE
//=============================================================================
 
//--------------------------
// Source data
//--------------------------
 
// Align source data to destination for lower resolution
wire [15:0] src_data_mask = ((exec_fill_i ? cfg_fill_color_i : vid_ram_dout_i) & vram_src_mask);
wire src_data_mask_1_bpp = (|src_data_mask);
wire [1:0] src_data_mask_2_bpp = {(|{src_data_mask[15], src_data_mask[13], src_data_mask[11], src_data_mask[9], src_data_mask[7], src_data_mask[5], src_data_mask[3], src_data_mask[1]}),
(|{src_data_mask[14], src_data_mask[12], src_data_mask[10], src_data_mask[8], src_data_mask[6], src_data_mask[4], src_data_mask[2], src_data_mask[0]})};
wire [3:0] src_data_mask_4_bpp = {(|{src_data_mask[15], src_data_mask[11], src_data_mask[7] , src_data_mask[3]}),
(|{src_data_mask[14], src_data_mask[10], src_data_mask[6] , src_data_mask[2]}),
(|{src_data_mask[13], src_data_mask[9] , src_data_mask[5] , src_data_mask[1]}),
(|{src_data_mask[12], src_data_mask[8] , src_data_mask[4] , src_data_mask[0]})};
wire [7:0] src_data_mask_8_bpp = {(|{src_data_mask[15], src_data_mask[7]}),
(|{src_data_mask[14], src_data_mask[6]}),
(|{src_data_mask[13], src_data_mask[5]}),
(|{src_data_mask[12], src_data_mask[4]}),
(|{src_data_mask[11], src_data_mask[3]}),
(|{src_data_mask[10], src_data_mask[2]}),
(|{src_data_mask[9] , src_data_mask[1]}),
(|{src_data_mask[8] , src_data_mask[0]})};
wire [15:0] src_data_mask_16_bpp = src_data_mask;
 
wire [15:0] src_data_align = ({16{gfx_mode_1_bpp }} & {16{src_data_mask_1_bpp}}) |
({16{gfx_mode_2_bpp }} & {8{src_data_mask_2_bpp}}) |
({16{gfx_mode_4_bpp }} & {4{src_data_mask_4_bpp}}) |
({16{gfx_mode_8_bpp }} & {2{src_data_mask_8_bpp}}) |
({16{gfx_mode_16_bpp}} & src_data_mask_16_bpp ) ;
 
// Detect read accesses
reg src_data_ready;
wire src_data_ready_nxt = ((dma_state==SRC_READ) & data_ready_nxt) | (exec_fill_i & dma_init);
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) src_data_ready <= 1'b0;
else src_data_ready <= src_data_ready_nxt;
 
// Read data buffer
reg [15:0] src_data_buf;
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) src_data_buf <= 16'h0000;
else if (src_data_ready) src_data_buf <= src_data_align;
 
// Source data
wire [15:0] src_data = src_data_ready ? src_data_align : src_data_buf;
 
//--------------------------
// Destination data
//--------------------------
 
// Detect read access
reg dst_data_ready;
wire dst_data_ready_nxt = ((dma_state==DST_READ) & data_ready_nxt);
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) dst_data_ready <= 1'b0;
else dst_data_ready <= dst_data_ready_nxt;
 
// Read data buffer
reg [15:0] dst_data_buf;
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) dst_data_buf <= 16'h0000;
else if (dst_data_ready) dst_data_buf <= vid_ram_dout_i;
 
// Source data
wire [15:0] dst_data = dst_data_ready ? vid_ram_dout_i : dst_data_buf;
 
//--------------------------
// Detect transparency
//--------------------------
wire [15:0] transparent_color_align = ({16{gfx_mode_1_bpp }} & {16{cfg_transparent_color_i[0] }}) |
({16{gfx_mode_2_bpp }} & {8{cfg_transparent_color_i[1:0]}}) |
({16{gfx_mode_4_bpp }} & {4{cfg_transparent_color_i[3:0]}}) |
({16{gfx_mode_8_bpp }} & {2{cfg_transparent_color_i[7:0]}}) |
({16{gfx_mode_16_bpp}} & cfg_transparent_color_i ) ;
 
wire pixel_is_transparent_nxt = ((exec_copy_trans_i & src_data_ready ) |
(exec_copy_i & src_data_ready & (pix_op_13 | pix_op_14 | pix_op_15)) |
(exec_fill_i & (pix_op_13 | pix_op_14 | pix_op_15)) ) & (src_data_align==transparent_color_align);
reg pixel_is_transparent_reg;
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) pixel_is_transparent_reg <= 1'b0;
else if (dma_pixel_done | (dma_state==IDLE)) pixel_is_transparent_reg <= 1'b0;
else if (pixel_is_transparent_nxt) pixel_is_transparent_reg <= 1'b1;
 
assign pixel_is_transparent = (pixel_is_transparent_nxt | pixel_is_transparent_reg);
 
//--------------------------
// Pixel operation
//--------------------------
wire [15:0] fill_color_align = ({16{gfx_mode_1_bpp }} & {16{cfg_fill_color_i[0] }}) |
({16{gfx_mode_2_bpp }} & {8{cfg_fill_color_i[1:0]}}) |
({16{gfx_mode_4_bpp }} & {4{cfg_fill_color_i[3:0]}}) |
({16{gfx_mode_8_bpp }} & {2{cfg_fill_color_i[7:0]}}) |
({16{gfx_mode_16_bpp}} & cfg_fill_color_i ) ;
 
wire [15:0] pixel_data = ({16{pix_op_00}} & ( src_data )) | // S
({16{pix_op_01}} & (~src_data )) | // not S
({16{pix_op_02}} & ( ~dst_data)) | // not D
 
({16{pix_op_03}} & ( src_data & dst_data)) | // S and D
({16{pix_op_04}} & ( src_data | dst_data)) | // S or D
({16{pix_op_05}} & ( src_data ^ dst_data)) | // S xor D
 
({16{pix_op_06}} & ~( src_data & dst_data)) | // not (S and D)
({16{pix_op_07}} & ~( src_data | dst_data)) | // not (S or D)
({16{pix_op_08}} & ~( src_data ^ dst_data)) | // not (S xor D)
 
({16{pix_op_09}} & (~src_data & dst_data)) | // (not S) and D
({16{pix_op_10}} & ( src_data & ~dst_data)) | // S and (not D)
({16{pix_op_11}} & (~src_data | dst_data)) | // (not S) or D
({16{pix_op_12}} & ( src_data | ~dst_data)) | // S or (not D)
 
({16{pix_op_13}} & ( 16'h0000 )) | // Fill 0 if S not transparent
({16{pix_op_14}} & ( 16'hffff )) | // Fill 1 if S not transparent
({16{pix_op_15}} & ( fill_color_align )) ; // Fill 'fill_color' if S not transparent
 
 
 
// RAM interface
assign vid_ram_din_o = (pixel_data & vram_dst_mask) | (dst_data & ~vram_dst_mask);
 
assign vid_ram_addr_o = (dma_state==SRC_READ) ? vram_src_addr[`APIX_MSB:4] :
vram_dst_addr[`APIX_MSB:4] ;
 
assign vid_ram_wen_o = ~( (dma_state==DST_WRITE) & ~pixel_is_transparent) ;
 
assign vid_ram_cen_o = ~( (dma_state==SRC_READ) |
((dma_state==DST_READ) & ~pixel_is_transparent) |
((dma_state==DST_WRITE) & ~pixel_is_transparent));
 
 
endmodule // ogfx_gpu_dma
 
`ifdef OGFX_NO_INCLUDE
`else
`include "openGFX430_undefines.v"
`endif
/core/rtl/verilog/ogfx_reg.v
0,0 → 1,1377
//----------------------------------------------------------------------------
// Copyright (C) 2015 Authors
//
// This source file may be used and distributed without restriction provided
// that this copyright statement is not removed from the file and that any
// derivative work contains the original copyright notice and the associated
// disclaimer.
//
// This source file is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This source is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
// License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this source; if not, write to the Free Software Foundation,
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
//----------------------------------------------------------------------------
//
// *File Name: ogfx_reg.v
//
// *Module Description:
// Registers for oMSP programming.
//
// *Author(s):
// - Olivier Girard, olgirard@gmail.com
//
//----------------------------------------------------------------------------
// $Rev$
// $LastChangedBy$
// $LastChangedDate$
//----------------------------------------------------------------------------
`ifdef OGFX_NO_INCLUDE
`else
`include "openGFX430_defines.v"
`endif
 
module ogfx_reg (
 
// OUTPUTs
irq_gfx_o, // Graphic Controller interrupt
 
gpu_data_o, // GPU data
gpu_data_avail_o, // GPU data available
gpu_enable_o, // GPU enable
 
lt24_reset_n_o, // LT24 Reset (Active Low)
lt24_on_o, // LT24 on/off
lt24_cfg_clk_o, // LT24 Interface clock configuration
lt24_cfg_refr_o, // LT24 Interface refresh configuration
lt24_cfg_refr_sync_en_o, // LT24 Interface refresh sync enable configuration
lt24_cfg_refr_sync_val_o, // LT24 Interface refresh sync value configuration
lt24_cmd_refr_o, // LT24 Interface refresh command
lt24_cmd_val_o, // LT24 Generic command value
lt24_cmd_has_param_o, // LT24 Generic command has parameters
lt24_cmd_param_o, // LT24 Generic command parameter value
lt24_cmd_param_rdy_o, // LT24 Generic command trigger
lt24_cmd_dfill_o, // LT24 Data fill value
lt24_cmd_dfill_wr_o, // LT24 Data fill trigger
 
display_width_o, // Display width
display_height_o, // Display height
display_size_o, // Display size (number of pixels)
display_y_swap_o, // Display configuration: swap Y axis (horizontal symmetry)
display_x_swap_o, // Display configuration: swap X axis (vertical symmetry)
display_cl_swap_o, // Display configuration: swap column/lines
gfx_mode_o, // Video mode (1xx:16bpp / 011:8bpp / 010:4bpp / 001:2bpp / 000:1bpp)
 
per_dout_o, // Peripheral data output
 
refresh_frame_addr_o, // Refresh frame base address
refresh_lut_select_o, // Refresh LUT bank selection
 
`ifdef WITH_PROGRAMMABLE_LUT
lut_ram_addr_o, // LUT-RAM address
lut_ram_din_o, // LUT-RAM data
lut_ram_wen_o, // LUT-RAM write strobe (active low)
lut_ram_cen_o, // LUT-RAM chip enable (active low)
`endif
 
vid_ram_addr_o, // Video-RAM address
vid_ram_din_o, // Video-RAM data
vid_ram_wen_o, // Video-RAM write strobe (active low)
vid_ram_cen_o, // Video-RAM chip enable (active low)
 
// INPUTs
dbg_freeze_i, // Freeze address auto-incr on read
gpu_cmd_done_evt_i, // GPU command done event
gpu_cmd_error_evt_i, // GPU command error event
gpu_get_data_i, // GPU get next data
lt24_status_i, // LT24 FSM Status
lt24_start_evt_i, // LT24 FSM is starting
lt24_done_evt_i, // LT24 FSM is done
mclk, // Main system clock
per_addr_i, // Peripheral address
per_din_i, // Peripheral data input
per_en_i, // Peripheral enable (high active)
per_we_i, // Peripheral write enable (high active)
puc_rst, // Main system reset
`ifdef WITH_PROGRAMMABLE_LUT
lut_ram_dout_i, // LUT-RAM data input
`endif
vid_ram_dout_i // Video-RAM data input
);
 
// OUTPUTs
//=========
output irq_gfx_o; // Graphic Controller interrupt
 
output [15:0] gpu_data_o; // GPU data
output gpu_data_avail_o; // GPU data available
output gpu_enable_o; // GPU enable
 
output lt24_reset_n_o; // LT24 Reset (Active Low)
output lt24_on_o; // LT24 on/off
output [2:0] lt24_cfg_clk_o; // LT24 Interface clock configuration
output [11:0] lt24_cfg_refr_o; // LT24 Interface refresh configuration
output lt24_cfg_refr_sync_en_o; // LT24 Interface refresh sync configuration
output [9:0] lt24_cfg_refr_sync_val_o; // LT24 Interface refresh sync value configuration
output lt24_cmd_refr_o; // LT24 Interface refresh command
output [7:0] lt24_cmd_val_o; // LT24 Generic command value
output lt24_cmd_has_param_o; // LT24 Generic command has parameters
output [15:0] lt24_cmd_param_o; // LT24 Generic command parameter value
output lt24_cmd_param_rdy_o; // LT24 Generic command trigger
output [15:0] lt24_cmd_dfill_o; // LT24 Data fill value
output lt24_cmd_dfill_wr_o; // LT24 Data fill trigger
 
output [`LPIX_MSB:0] display_width_o; // Display width
output [`LPIX_MSB:0] display_height_o; // Display height
output [`SPIX_MSB:0] display_size_o; // Display size (number of pixels)
output display_y_swap_o; // Display configuration: swap Y axis (horizontal symmetry)
output display_x_swap_o; // Display configuration: swap X axis (vertical symmetry)
output display_cl_swap_o; // Display configuration: swap column/lines
output [2:0] gfx_mode_o; // Video mode (1xx:16bpp / 011:8bpp / 010:4bpp / 001:2bpp / 000:1bpp)
 
output [15:0] per_dout_o; // Peripheral data output
 
output [`APIX_MSB:0] refresh_frame_addr_o; // Refresh frame base address
output [1:0] refresh_lut_select_o; // Refresh LUT bank selection
 
`ifdef WITH_PROGRAMMABLE_LUT
output [`LRAM_MSB:0] lut_ram_addr_o; // LUT-RAM address
output [15:0] lut_ram_din_o; // LUT-RAM data
output lut_ram_wen_o; // LUT-RAM write strobe (active low)
output lut_ram_cen_o; // LUT-RAM chip enable (active low)
`endif
 
output [`VRAM_MSB:0] vid_ram_addr_o; // Video-RAM address
output [15:0] vid_ram_din_o; // Video-RAM data
output vid_ram_wen_o; // Video-RAM write strobe (active low)
output vid_ram_cen_o; // Video-RAM chip enable (active low)
 
// INPUTs
//=========
input dbg_freeze_i; // Freeze address auto-incr on read
input gpu_cmd_done_evt_i; // GPU command done event
input gpu_cmd_error_evt_i; // GPU command error event
input gpu_get_data_i; // GPU get next data
input [4:0] lt24_status_i; // LT24 FSM Status
input lt24_start_evt_i; // LT24 FSM is starting
input lt24_done_evt_i; // LT24 FSM is done
input mclk; // Main system clock
input [13:0] per_addr_i; // Peripheral address
input [15:0] per_din_i; // Peripheral data input
input per_en_i; // Peripheral enable (high active)
input [1:0] per_we_i; // Peripheral write enable (high active)
input puc_rst; // Main system reset
`ifdef WITH_PROGRAMMABLE_LUT
input [15:0] lut_ram_dout_i; // LUT-RAM data input
`endif
input [15:0] vid_ram_dout_i; // Video-RAM data input
 
 
//=============================================================================
// 1) PARAMETER DECLARATION
//=============================================================================
 
// Register base address (must be aligned to decoder bit width)
parameter [14:0] BASE_ADDR = 15'h0200;
 
// Decoder bit width (defines how many bits are considered for address decoding)
parameter DEC_WD = 7;
 
// Register addresses offset
parameter [DEC_WD-1:0] GFX_CTRL = 'h00, // General control/status/irq
GFX_STATUS = 'h08,
GFX_IRQ = 'h0A,
 
DISPLAY_WIDTH = 'h10, // Display configuration
DISPLAY_HEIGHT = 'h12,
DISPLAY_SIZE_HI = 'h14,
DISPLAY_SIZE_LO = 'h16,
DISPLAY_CFG = 'h18,
 
LT24_CFG = 'h20, // LT24 configuration and Generic command sending
LT24_REFRESH = 'h22,
LT24_REFRESH_SYNC = 'h24,
LT24_CMD = 'h26,
LT24_CMD_PARAM = 'h28,
LT24_CMD_DFILL = 'h2A,
LT24_STATUS = 'h2C,
 
LUT_RAM_ADDR = 'h30, // LUT Memory Access Gate
LUT_RAM_DATA = 'h32,
 
FRAME_SELECT = 'h3E, // Frame pointers and selection
FRAME0_PTR_HI = 'h40,
FRAME0_PTR_LO = 'h42,
FRAME1_PTR_HI = 'h44,
FRAME1_PTR_LO = 'h46,
FRAME2_PTR_HI = 'h48,
FRAME2_PTR_LO = 'h4A,
FRAME3_PTR_HI = 'h4C,
FRAME3_PTR_LO = 'h4E,
 
VID_RAM0_CFG = 'h50, // First Video Memory Access Gate
VID_RAM0_WIDTH = 'h52,
VID_RAM0_ADDR_HI = 'h54,
VID_RAM0_ADDR_LO = 'h56,
VID_RAM0_DATA = 'h58,
 
VID_RAM1_CFG = 'h60, // Second Video Memory Access Gate
VID_RAM1_WIDTH = 'h62,
VID_RAM1_ADDR_HI = 'h64,
VID_RAM1_ADDR_LO = 'h66,
VID_RAM1_DATA = 'h68,
 
GPU_CMD = 'h70, // Graphic Processing Unit
GPU_STAT = 'h72;
 
 
// Register one-hot decoder utilities
parameter DEC_SZ = (1 << DEC_WD);
parameter [DEC_SZ-1:0] BASE_REG = {{DEC_SZ-1{1'b0}}, 1'b1};
 
// Register one-hot decoder
parameter [DEC_SZ-1:0] GFX_CTRL_D = (BASE_REG << GFX_CTRL ),
GFX_STATUS_D = (BASE_REG << GFX_STATUS ),
GFX_IRQ_D = (BASE_REG << GFX_IRQ ),
 
DISPLAY_WIDTH_D = (BASE_REG << DISPLAY_WIDTH ),
DISPLAY_HEIGHT_D = (BASE_REG << DISPLAY_HEIGHT ),
DISPLAY_SIZE_HI_D = (BASE_REG << DISPLAY_SIZE_HI ),
DISPLAY_SIZE_LO_D = (BASE_REG << DISPLAY_SIZE_LO ),
DISPLAY_CFG_D = (BASE_REG << DISPLAY_CFG ),
 
LT24_CFG_D = (BASE_REG << LT24_CFG ),
LT24_REFRESH_D = (BASE_REG << LT24_REFRESH ),
LT24_REFRESH_SYNC_D = (BASE_REG << LT24_REFRESH_SYNC ),
LT24_CMD_D = (BASE_REG << LT24_CMD ),
LT24_CMD_PARAM_D = (BASE_REG << LT24_CMD_PARAM ),
LT24_CMD_DFILL_D = (BASE_REG << LT24_CMD_DFILL ),
LT24_STATUS_D = (BASE_REG << LT24_STATUS ),
 
LUT_RAM_ADDR_D = (BASE_REG << LUT_RAM_ADDR ),
LUT_RAM_DATA_D = (BASE_REG << LUT_RAM_DATA ),
 
FRAME_SELECT_D = (BASE_REG << FRAME_SELECT ),
FRAME0_PTR_HI_D = (BASE_REG << FRAME0_PTR_HI ),
FRAME0_PTR_LO_D = (BASE_REG << FRAME0_PTR_LO ),
FRAME1_PTR_HI_D = (BASE_REG << FRAME1_PTR_HI ),
FRAME1_PTR_LO_D = (BASE_REG << FRAME1_PTR_LO ),
FRAME2_PTR_HI_D = (BASE_REG << FRAME2_PTR_HI ),
FRAME2_PTR_LO_D = (BASE_REG << FRAME2_PTR_LO ),
FRAME3_PTR_HI_D = (BASE_REG << FRAME3_PTR_HI ),
FRAME3_PTR_LO_D = (BASE_REG << FRAME3_PTR_LO ),
 
VID_RAM0_CFG_D = (BASE_REG << VID_RAM0_CFG ),
VID_RAM0_WIDTH_D = (BASE_REG << VID_RAM0_WIDTH ),
VID_RAM0_ADDR_HI_D = (BASE_REG << VID_RAM0_ADDR_HI ),
VID_RAM0_ADDR_LO_D = (BASE_REG << VID_RAM0_ADDR_LO ),
VID_RAM0_DATA_D = (BASE_REG << VID_RAM0_DATA ),
 
VID_RAM1_CFG_D = (BASE_REG << VID_RAM1_CFG ),
VID_RAM1_WIDTH_D = (BASE_REG << VID_RAM1_WIDTH ),
VID_RAM1_ADDR_HI_D = (BASE_REG << VID_RAM1_ADDR_HI ),
VID_RAM1_ADDR_LO_D = (BASE_REG << VID_RAM1_ADDR_LO ),
VID_RAM1_DATA_D = (BASE_REG << VID_RAM1_DATA ),
 
GPU_CMD_D = (BASE_REG << GPU_CMD ),
GPU_STAT_D = (BASE_REG << GPU_STAT );
 
 
//============================================================================
// 2) REGISTER DECODER
//============================================================================
 
// Local register selection
wire reg_sel = per_en_i & (per_addr_i[13:DEC_WD-1]==BASE_ADDR[14:DEC_WD]);
 
// Register local address
wire [DEC_WD-1:0] reg_addr = {per_addr_i[DEC_WD-2:0], 1'b0};
 
// Register address decode
wire [DEC_SZ-1:0] reg_dec = (GFX_CTRL_D & {DEC_SZ{(reg_addr == GFX_CTRL )}}) |
(GFX_STATUS_D & {DEC_SZ{(reg_addr == GFX_STATUS )}}) |
(GFX_IRQ_D & {DEC_SZ{(reg_addr == GFX_IRQ )}}) |
 
(DISPLAY_WIDTH_D & {DEC_SZ{(reg_addr == DISPLAY_WIDTH )}}) |
(DISPLAY_HEIGHT_D & {DEC_SZ{(reg_addr == DISPLAY_HEIGHT )}}) |
(DISPLAY_SIZE_HI_D & {DEC_SZ{(reg_addr == DISPLAY_SIZE_HI )}}) |
(DISPLAY_SIZE_LO_D & {DEC_SZ{(reg_addr == DISPLAY_SIZE_LO )}}) |
(DISPLAY_CFG_D & {DEC_SZ{(reg_addr == DISPLAY_CFG )}}) |
 
(LT24_CFG_D & {DEC_SZ{(reg_addr == LT24_CFG )}}) |
(LT24_REFRESH_D & {DEC_SZ{(reg_addr == LT24_REFRESH )}}) |
(LT24_REFRESH_SYNC_D & {DEC_SZ{(reg_addr == LT24_REFRESH_SYNC )}}) |
(LT24_CMD_D & {DEC_SZ{(reg_addr == LT24_CMD )}}) |
(LT24_CMD_PARAM_D & {DEC_SZ{(reg_addr == LT24_CMD_PARAM )}}) |
(LT24_CMD_DFILL_D & {DEC_SZ{(reg_addr == LT24_CMD_DFILL )}}) |
(LT24_STATUS_D & {DEC_SZ{(reg_addr == LT24_STATUS )}}) |
 
(LUT_RAM_ADDR_D & {DEC_SZ{(reg_addr == LUT_RAM_ADDR )}}) |
(LUT_RAM_DATA_D & {DEC_SZ{(reg_addr == LUT_RAM_DATA )}}) |
 
(FRAME_SELECT_D & {DEC_SZ{(reg_addr == FRAME_SELECT )}}) |
(FRAME0_PTR_HI_D & {DEC_SZ{(reg_addr == FRAME0_PTR_HI )}}) |
(FRAME0_PTR_LO_D & {DEC_SZ{(reg_addr == FRAME0_PTR_LO )}}) |
(FRAME1_PTR_HI_D & {DEC_SZ{(reg_addr == FRAME1_PTR_HI )}}) |
(FRAME1_PTR_LO_D & {DEC_SZ{(reg_addr == FRAME1_PTR_LO )}}) |
(FRAME2_PTR_HI_D & {DEC_SZ{(reg_addr == FRAME2_PTR_HI )}}) |
(FRAME2_PTR_LO_D & {DEC_SZ{(reg_addr == FRAME2_PTR_LO )}}) |
(FRAME3_PTR_HI_D & {DEC_SZ{(reg_addr == FRAME3_PTR_HI )}}) |
(FRAME3_PTR_LO_D & {DEC_SZ{(reg_addr == FRAME3_PTR_LO )}}) |
 
(VID_RAM0_CFG_D & {DEC_SZ{(reg_addr == VID_RAM0_CFG )}}) |
(VID_RAM0_WIDTH_D & {DEC_SZ{(reg_addr == VID_RAM0_WIDTH )}}) |
(VID_RAM0_ADDR_HI_D & {DEC_SZ{(reg_addr == VID_RAM0_ADDR_HI )}}) |
(VID_RAM0_ADDR_LO_D & {DEC_SZ{(reg_addr == VID_RAM0_ADDR_LO )}}) |
(VID_RAM0_DATA_D & {DEC_SZ{(reg_addr == VID_RAM0_DATA )}}) |
 
(VID_RAM1_CFG_D & {DEC_SZ{(reg_addr == VID_RAM1_CFG )}}) |
(VID_RAM1_WIDTH_D & {DEC_SZ{(reg_addr == VID_RAM1_WIDTH )}}) |
(VID_RAM1_ADDR_HI_D & {DEC_SZ{(reg_addr == VID_RAM1_ADDR_HI )}}) |
(VID_RAM1_ADDR_LO_D & {DEC_SZ{(reg_addr == VID_RAM1_ADDR_LO )}}) |
(VID_RAM1_DATA_D & {DEC_SZ{(reg_addr == VID_RAM1_DATA )}}) |
 
(GPU_CMD_D & {DEC_SZ{(reg_addr == GPU_CMD )}}) |
(GPU_STAT_D & {DEC_SZ{(reg_addr == GPU_STAT )}});
 
// Read/Write probes
wire reg_write = |per_we_i & reg_sel;
wire reg_read = ~|per_we_i & reg_sel;
 
// Read/Write vectors
wire [DEC_SZ-1:0] reg_wr = reg_dec & {DEC_SZ{reg_write}};
wire [DEC_SZ-1:0] reg_rd = reg_dec & {DEC_SZ{reg_read}};
 
// Other wire declarations
wire [`APIX_MSB:0] frame0_ptr;
`ifdef WITH_FRAME1_POINTER
wire [`APIX_MSB:0] frame1_ptr;
`endif
`ifdef WITH_FRAME2_POINTER
wire [`APIX_MSB:0] frame2_ptr;
`endif
`ifdef WITH_FRAME3_POINTER
wire [`APIX_MSB:0] frame3_ptr;
`endif
wire [`APIX_MSB:0] vid_ram0_base_addr;
wire [`APIX_MSB:0] vid_ram1_base_addr;
`ifdef WITH_EXTRA_LUT_BANK
reg lut_bank_select;
`endif
reg vid_ram0_addr_lo_wr_dly;
reg vid_ram1_addr_lo_wr_dly;
wire gpu_fifo_done_evt;
wire gpu_fifo_ovfl_evt;
 
 
//============================================================================
// 3) REGISTERS
//============================================================================
 
//------------------------------------------------
// GFX_CTRL Register
//------------------------------------------------
reg [15:0] gfx_ctrl;
 
wire gfx_ctrl_wr = reg_wr[GFX_CTRL];
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) gfx_ctrl <= 16'h0000;
else if (gfx_ctrl_wr) gfx_ctrl <= per_din_i;
 
// Bitfield assignments
wire gfx_irq_refr_done_en = gfx_ctrl[0];
wire gfx_irq_refr_start_en = gfx_ctrl[1];
wire gfx_irq_gpu_fifo_done_en = gfx_ctrl[4];
wire gfx_irq_gpu_fifo_ovfl_en = gfx_ctrl[5];
wire gfx_irq_gpu_cmd_done_en = gfx_ctrl[6];
wire gfx_irq_gpu_cmd_error_en = gfx_ctrl[7];
assign gfx_mode_o = gfx_ctrl[10:8]; // 1xx: 16 bits-per-pixel
// 011: 8 bits-per-pixel
// 010: 4 bits-per-pixel
// 001: 2 bits-per-pixel
// 000: 1 bits-per-pixel
wire gpu_enable_o = gfx_ctrl[12];
 
// Video modes decoding
wire gfx_mode_1_bpp = (gfx_mode_o == 3'b000);
wire gfx_mode_2_bpp = (gfx_mode_o == 3'b001);
wire gfx_mode_4_bpp = (gfx_mode_o == 3'b010);
wire gfx_mode_8_bpp = (gfx_mode_o == 3'b011);
wire gfx_mode_16_bpp = ~(gfx_mode_8_bpp | gfx_mode_4_bpp | gfx_mode_2_bpp | gfx_mode_1_bpp);
 
//------------------------------------------------
// GFX_STATUS Register
//------------------------------------------------
wire [15:0] gfx_status;
 
assign gfx_status[0] = lt24_status_i[2]; // Screen Refresh is busy
assign gfx_status[15:1] = 15'h0000;
 
//------------------------------------------------
// GFX_IRQ Register
//------------------------------------------------
wire [15:0] gfx_irq;
 
// Clear IRQ when 1 is written. Set IRQ when FSM is done
wire gfx_irq_refr_done_clr = per_din_i[0] & reg_wr[GFX_IRQ];
wire gfx_irq_refr_done_set = lt24_done_evt_i;
 
wire gfx_irq_refr_start_clr = per_din_i[1] & reg_wr[GFX_IRQ];
wire gfx_irq_refr_start_set = lt24_start_evt_i;
 
wire gfx_irq_gpu_fifo_done_clr = per_din_i[4] & reg_wr[GFX_IRQ];
wire gfx_irq_gpu_fifo_done_set = gpu_fifo_done_evt;
 
wire gfx_irq_gpu_fifo_ovfl_clr = per_din_i[5] & reg_wr[GFX_IRQ];
wire gfx_irq_gpu_fifo_ovfl_set = gpu_fifo_ovfl_evt;
 
wire gfx_irq_gpu_cmd_done_clr = per_din_i[6] & reg_wr[GFX_IRQ];
wire gfx_irq_gpu_cmd_done_set = gpu_cmd_done_evt_i;
 
wire gfx_irq_gpu_cmd_error_clr = per_din_i[7] & reg_wr[GFX_IRQ];
wire gfx_irq_gpu_cmd_error_set = gpu_cmd_error_evt_i;
 
reg gfx_irq_refr_done;
reg gfx_irq_refr_start;
reg gfx_irq_gpu_fifo_done;
reg gfx_irq_gpu_fifo_ovfl;
reg gfx_irq_gpu_cmd_done;
reg gfx_irq_gpu_cmd_error;
always @ (posedge mclk or posedge puc_rst)
if (puc_rst)
begin
gfx_irq_refr_done <= 1'b0;
gfx_irq_refr_start <= 1'b0;
gfx_irq_gpu_fifo_done <= 1'b0;
gfx_irq_gpu_fifo_ovfl <= 1'b0;
gfx_irq_gpu_cmd_done <= 1'b0;
gfx_irq_gpu_cmd_error <= 1'b0;
end
else
begin
gfx_irq_refr_done <= (gfx_irq_refr_done_set | (~gfx_irq_refr_done_clr & gfx_irq_refr_done )); // IRQ set has priority over clear
gfx_irq_refr_start <= (gfx_irq_refr_start_set | (~gfx_irq_refr_start_clr & gfx_irq_refr_start )); // IRQ set has priority over clear
gfx_irq_gpu_fifo_done <= (gfx_irq_gpu_fifo_done_set | (~gfx_irq_gpu_fifo_done_clr & gfx_irq_gpu_fifo_done)); // IRQ set has priority over clear
gfx_irq_gpu_fifo_ovfl <= (gfx_irq_gpu_fifo_ovfl_set | (~gfx_irq_gpu_fifo_ovfl_clr & gfx_irq_gpu_fifo_ovfl)); // IRQ set has priority over clear
gfx_irq_gpu_cmd_done <= (gfx_irq_gpu_cmd_done_set | (~gfx_irq_gpu_cmd_done_clr & gfx_irq_gpu_cmd_done )); // IRQ set has priority over clear
gfx_irq_gpu_cmd_error <= (gfx_irq_gpu_cmd_error_set | (~gfx_irq_gpu_cmd_error_clr & gfx_irq_gpu_cmd_error)); // IRQ set has priority over clear
end
 
assign gfx_irq = {8'h00,
gfx_irq_gpu_cmd_error, gfx_irq_gpu_cmd_done, gfx_irq_gpu_fifo_ovfl, gfx_irq_gpu_fifo_done,
2'h0, gfx_irq_refr_start, gfx_irq_refr_done};
 
assign irq_gfx_o = (gfx_irq_refr_done & gfx_irq_refr_done_en) |
(gfx_irq_refr_start & gfx_irq_refr_start_en) |
(gfx_irq_gpu_cmd_error & gfx_irq_gpu_cmd_error_en) |
(gfx_irq_gpu_cmd_done & gfx_irq_gpu_cmd_done_en) |
(gfx_irq_gpu_fifo_ovfl & gfx_irq_gpu_fifo_ovfl_en) |
(gfx_irq_gpu_fifo_done & gfx_irq_gpu_fifo_done_en); // Graphic Controller interrupt
 
//------------------------------------------------
// DISPLAY_WIDTH Register
//------------------------------------------------
reg [`LPIX_MSB:0] display_width_o;
 
wire display_width_wr = reg_wr[DISPLAY_WIDTH];
wire [`LPIX_MSB:0] display_w_h_nxt = (|per_din_i[`LPIX_MSB:0]) ? per_din_i[`LPIX_MSB:0] :
{{`LPIX_MSB{1'b0}}, 1'b1};
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) display_width_o <= {{`LPIX_MSB{1'b0}}, 1'b1};
else if (display_width_wr) display_width_o <= display_w_h_nxt;
 
wire [16:0] display_width_tmp = {{16-`LPIX_MSB{1'b0}}, display_width_o};
wire [15:0] display_width_rd = display_width_tmp[15:0];
 
//------------------------------------------------
// DISPLAY_HEIGHT Register
//------------------------------------------------
reg [`LPIX_MSB:0] display_height_o;
 
wire display_height_wr = reg_wr[DISPLAY_HEIGHT];
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) display_height_o <= {{`LPIX_MSB{1'b0}}, 1'b1};
else if (display_height_wr) display_height_o <= display_w_h_nxt;
 
wire [16:0] display_height_tmp = {{16-`LPIX_MSB{1'b0}}, display_height_o};
wire [15:0] display_height_rd = display_height_tmp[15:0];
 
//------------------------------------------------
// DISPLAY_SIZE_HI Register
//------------------------------------------------
`ifdef WITH_DISPLAY_SIZE_HI
reg [`SPIX_HI_MSB:0] display_size_hi;
 
wire display_size_hi_wr = reg_wr[DISPLAY_SIZE_HI];
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) display_size_hi <= {`SPIX_HI_MSB+1{1'h0}};
else if (display_size_hi_wr) display_size_hi <= per_din_i[`SPIX_HI_MSB:0];
 
wire [16:0] display_size_hi_tmp = {{16-`SPIX_HI_MSB{1'h0}}, display_size_hi};
wire [15:0] display_size_hi_rd = display_size_hi_tmp[15:0];
`endif
 
//------------------------------------------------
// DISPLAY_SIZE_LO Register
//------------------------------------------------
reg [`SPIX_LO_MSB:0] display_size_lo;
 
wire display_size_lo_wr = reg_wr[DISPLAY_SIZE_LO];
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) display_size_lo <= {{`SPIX_LO_MSB{1'h0}}, 1'b1};
else if (display_size_lo_wr) display_size_lo <= per_din_i[`SPIX_LO_MSB:0];
 
wire [16:0] display_size_lo_tmp = {{16-`SPIX_LO_MSB{1'h0}}, display_size_lo};
wire [15:0] display_size_lo_rd = display_size_lo_tmp[15:0];
 
`ifdef WITH_DISPLAY_SIZE_HI
assign display_size_o = {display_size_hi, display_size_lo};
`else
assign display_size_o = display_size_lo;
`endif
 
//------------------------------------------------
// DISPLAY_CFG Register
//------------------------------------------------
reg display_x_swap_o;
reg display_y_swap_o;
reg display_cl_swap_o;
 
wire display_cfg_wr = reg_wr[DISPLAY_CFG];
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst)
begin
display_cl_swap_o <= 1'b0;
display_y_swap_o <= 1'b0;
display_x_swap_o <= 1'b0;
end
else if (display_cfg_wr)
begin
display_cl_swap_o <= per_din_i[0];
display_y_swap_o <= per_din_i[1];
display_x_swap_o <= per_din_i[2];
end
 
wire [15:0] display_cfg = {13'h0000,
display_x_swap_o,
display_y_swap_o,
display_cl_swap_o};
 
//------------------------------------------------
// LT24_CFG Register
//------------------------------------------------
reg [15:0] lt24_cfg;
 
wire lt24_cfg_wr = reg_wr[LT24_CFG];
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) lt24_cfg <= 16'h0000;
else if (lt24_cfg_wr) lt24_cfg <= per_din_i;
 
// Bitfield assignments
assign lt24_cfg_clk_o = lt24_cfg[6:4];
assign lt24_reset_n_o = ~lt24_cfg[1];
assign lt24_on_o = lt24_cfg[0];
 
//------------------------------------------------
// LT24_REFRESH Register
//------------------------------------------------
reg lt24_cmd_refr_o;
reg [11:0] lt24_cfg_refr_o;
 
wire lt24_refresh_wr = reg_wr[LT24_REFRESH];
wire lt24_cmd_refr_clr = lt24_done_evt_i & lt24_status_i[2] & (lt24_cfg_refr_o==8'h00); // Auto-clear in manual refresh mode when done
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) lt24_cmd_refr_o <= 1'h0;
else if (lt24_refresh_wr) lt24_cmd_refr_o <= per_din_i[0];
else if (lt24_cmd_refr_clr) lt24_cmd_refr_o <= 1'h0;
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) lt24_cfg_refr_o <= 12'h000;
else if (lt24_refresh_wr) lt24_cfg_refr_o <= per_din_i[15:4];
 
wire [15:0] lt24_refresh = {lt24_cfg_refr_o, 3'h0, lt24_cmd_refr_o};
 
//------------------------------------------------
// LT24_REFRESH Register
//------------------------------------------------
reg lt24_cfg_refr_sync_en_o;
reg [9:0] lt24_cfg_refr_sync_val_o;
 
wire lt24_refresh_sync_wr = reg_wr[LT24_REFRESH_SYNC];
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) lt24_cfg_refr_sync_en_o <= 1'h0;
else if (lt24_refresh_sync_wr) lt24_cfg_refr_sync_en_o <= per_din_i[15];
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) lt24_cfg_refr_sync_val_o <= 10'h000;
else if (lt24_refresh_sync_wr) lt24_cfg_refr_sync_val_o <= per_din_i[9:0];
 
wire [15:0] lt24_refresh_sync = {lt24_cfg_refr_sync_en_o, 5'h00, lt24_cfg_refr_sync_val_o};
 
 
//------------------------------------------------
// LT24_CMD Register
//------------------------------------------------
reg [15:0] lt24_cmd;
 
wire lt24_cmd_wr = reg_wr[LT24_CMD];
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) lt24_cmd <= 16'h0000;
else if (lt24_cmd_wr) lt24_cmd <= per_din_i;
 
assign lt24_cmd_val_o = lt24_cmd[7:0];
assign lt24_cmd_has_param_o = lt24_cmd[8];
 
//------------------------------------------------
// LT24_CMD_PARAM Register
//------------------------------------------------
reg [15:0] lt24_cmd_param_o;
 
wire lt24_cmd_param_wr = reg_wr[LT24_CMD_PARAM];
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) lt24_cmd_param_o <= 16'h0000;
else if (lt24_cmd_param_wr) lt24_cmd_param_o <= per_din_i;
 
reg lt24_cmd_param_rdy_o;
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) lt24_cmd_param_rdy_o <= 1'b0;
else lt24_cmd_param_rdy_o <= lt24_cmd_param_wr;
 
//------------------------------------------------
// LT24_CMD_DFILL Register
//------------------------------------------------
reg [15:0] lt24_cmd_dfill_o;
 
assign lt24_cmd_dfill_wr_o = reg_wr[LT24_CMD_DFILL];
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) lt24_cmd_dfill_o <= 16'h0000;
else if (lt24_cmd_dfill_wr_o) lt24_cmd_dfill_o <= per_din_i;
 
//------------------------------------------------
// LT24_STATUS Register
//------------------------------------------------
wire [15:0] lt24_status;
 
assign lt24_status[0] = lt24_status_i[0]; // FSM_BUSY
assign lt24_status[1] = lt24_status_i[1]; // WAIT_PARAM
assign lt24_status[2] = lt24_status_i[2]; // REFRESH_BUSY
assign lt24_status[3] = lt24_status_i[3]; // WAIT_FOR_SCANLINE
assign lt24_status[4] = lt24_status_i[4]; // DATA_FILL_BUSY
assign lt24_status[15:5] = 11'h000;
 
 
//------------------------------------------------
// LUT_RAM_ADDR Register
//------------------------------------------------
`ifdef WITH_PROGRAMMABLE_LUT
 
reg [7:0] lut_ram_addr;
wire [7:0] lut_ram_addr_inc;
wire lut_ram_addr_inc_wr;
 
wire lut_ram_addr_wr = reg_wr[LUT_RAM_ADDR];
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) lut_ram_addr <= 8'h00;
else if (lut_ram_addr_wr) lut_ram_addr <= per_din_i[7:0];
else if (lut_ram_addr_inc_wr) lut_ram_addr <= lut_ram_addr_inc;
 
assign lut_ram_addr_inc = lut_ram_addr + 8'h01;
wire [15:0] lut_ram_addr_rd = {8'h00, lut_ram_addr};
 
`ifdef WITH_EXTRA_LUT_BANK
assign lut_ram_addr_o = {lut_bank_select, lut_ram_addr};
`else
assign lut_ram_addr_o = lut_ram_addr;
`endif
 
`else
wire [15:0] lut_ram_addr_rd = 16'h0000;
`endif
 
//------------------------------------------------
// LUT_RAM_DATA Register
//------------------------------------------------
`ifdef WITH_PROGRAMMABLE_LUT
 
// Update the LUT_RAM_DATA register with regular register write access
wire lut_ram_data_wr = reg_wr[LUT_RAM_DATA];
wire lut_ram_data_rd = reg_rd[LUT_RAM_DATA];
reg lut_ram_dout_rdy;
 
// LUT-RAM data Register
reg [15:0] lut_ram_data;
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) lut_ram_data <= 16'h0000;
else if (lut_ram_data_wr) lut_ram_data <= per_din_i;
else if (lut_ram_dout_rdy) lut_ram_data <= lut_ram_dout_i;
 
// Increment the address after a write or read access to the LUT_RAM_DATA register
assign lut_ram_addr_inc_wr = lut_ram_data_wr | lut_ram_data_rd;
 
// Apply peripheral data bus % write strobe during VID_RAMx_DATA write access
assign lut_ram_din_o = per_din_i & {16{lut_ram_data_wr}};
assign lut_ram_wen_o = ~(|per_we_i & lut_ram_data_wr);
 
// Trigger a LUT-RAM read access immediately after:
// - a LUT-RAM_ADDR register write access
// - a LUT-RAM_DATA register read access
reg lut_ram_addr_wr_dly;
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) lut_ram_addr_wr_dly <= 1'b0;
else lut_ram_addr_wr_dly <= lut_ram_addr_wr;
 
reg lut_ram_data_rd_dly;
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) lut_ram_data_rd_dly <= 1'b0;
else lut_ram_data_rd_dly <= lut_ram_data_rd;
 
// Chip enable.
// Note: we perform a data read access:
// - one cycle after a VID_RAM_DATA register read access (so that the address has been incremented)
// - one cycle after a VID_RAM_ADDR register write
assign lut_ram_cen_o = ~(lut_ram_addr_wr_dly | lut_ram_data_rd_dly | // Read access
lut_ram_data_wr); // Write access
 
// Update the VRAM_DATA register one cycle after each memory access
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) lut_ram_dout_rdy <= 1'b0;
else lut_ram_dout_rdy <= ~lut_ram_cen_o;
 
`else
wire [15:0] lut_ram_data = 16'h0000;
`endif
 
//------------------------------------------------
// FRAME_SELECT Register
//------------------------------------------------
 
wire frame_select_wr = reg_wr[FRAME_SELECT];
 
`ifdef WITH_PROGRAMMABLE_LUT
reg refresh_sw_lut_enable;
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) refresh_sw_lut_enable <= 1'b0;
else if (frame_select_wr) refresh_sw_lut_enable <= per_din_i[2];
`else
wire refresh_sw_lut_enable = 1'b0;
`endif
 
`ifdef WITH_EXTRA_LUT_BANK
reg refresh_sw_lut_select;
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst)
begin
refresh_sw_lut_select <= 1'b0;
lut_bank_select <= 1'b0;
end
else if (frame_select_wr)
begin
refresh_sw_lut_select <= per_din_i[3];
lut_bank_select <= per_din_i[15];
end
`else
assign refresh_sw_lut_select = 1'b0;
wire lut_bank_select = 1'b0;
`endif
wire [1:0] refresh_lut_select_o = {refresh_sw_lut_select, refresh_sw_lut_enable};
 
`ifdef WITH_FRAME1_POINTER
`ifdef WITH_FRAME2_POINTER
reg [1:0] refresh_frame_select;
reg [1:0] vid_ram0_frame_select;
reg [1:0] vid_ram1_frame_select;
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst)
begin
refresh_frame_select <= 2'h0;
vid_ram0_frame_select <= 2'h0;
vid_ram1_frame_select <= 2'h0;
end
else if (frame_select_wr)
begin
refresh_frame_select <= per_din_i[1:0];
vid_ram0_frame_select <= per_din_i[5:4];
vid_ram1_frame_select <= per_din_i[7:6];
end
 
wire [15:0] frame_select = {lut_bank_select, 7'h00, vid_ram1_frame_select, vid_ram0_frame_select, refresh_lut_select_o, refresh_frame_select};
`else
reg refresh_frame_select;
reg vid_ram0_frame_select;
reg vid_ram1_frame_select;
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst)
begin
refresh_frame_select <= 1'h0;
vid_ram0_frame_select <= 1'h0;
vid_ram1_frame_select <= 1'h0;
end
else if (frame_select_wr)
begin
refresh_frame_select <= per_din_i[0];
vid_ram0_frame_select <= per_din_i[4];
vid_ram1_frame_select <= per_din_i[6];
end
 
wire [15:0] frame_select = {lut_bank_select, 7'h00, 1'h0, vid_ram1_frame_select, 1'h0, vid_ram0_frame_select, refresh_lut_select_o, 1'h0, refresh_frame_select};
`endif
`else
wire [15:0] frame_select = {lut_bank_select, 11'h000, refresh_lut_select_o, 2'h0};
`endif
 
// Frame pointer selections
`ifdef WITH_FRAME1_POINTER
assign refresh_frame_addr_o = (refresh_frame_select==0) ? frame0_ptr :
`ifdef WITH_FRAME2_POINTER
(refresh_frame_select==1) ? frame1_ptr :
`ifdef WITH_FRAME3_POINTER
(refresh_frame_select==2) ? frame2_ptr :
frame3_ptr ;
`else
frame2_ptr ;
`endif
`else
frame1_ptr ;
`endif
 
assign vid_ram0_base_addr = (vid_ram0_frame_select==0) ? frame0_ptr :
`ifdef WITH_FRAME2_POINTER
(vid_ram0_frame_select==1) ? frame1_ptr :
`ifdef WITH_FRAME3_POINTER
(vid_ram0_frame_select==2) ? frame2_ptr :
frame3_ptr ;
`else
frame2_ptr ;
`endif
`else
frame1_ptr ;
`endif
 
assign vid_ram1_base_addr = (vid_ram1_frame_select==0) ? frame0_ptr :
`ifdef WITH_FRAME2_POINTER
(vid_ram1_frame_select==1) ? frame1_ptr :
`ifdef WITH_FRAME3_POINTER
(vid_ram1_frame_select==2) ? frame2_ptr :
frame3_ptr ;
`else
frame2_ptr ;
`endif
`else
frame1_ptr ;
`endif
 
`else
assign refresh_frame_addr_o = frame0_ptr;
assign vid_ram0_base_addr = frame0_ptr;
assign vid_ram1_base_addr = frame0_ptr;
`endif
 
//------------------------------------------------
// FRAME0_PTR_HI Register
//------------------------------------------------
`ifdef VRAM_BIGGER_4_KW
reg [`APIX_HI_MSB:0] frame0_ptr_hi;
 
wire frame0_ptr_hi_wr = reg_wr[FRAME0_PTR_HI];
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) frame0_ptr_hi <= {`APIX_HI_MSB+1{1'b0}};
else if (frame0_ptr_hi_wr) frame0_ptr_hi <= per_din_i[`APIX_HI_MSB:0];
 
wire [16:0] frame0_ptr_hi_tmp = {{16-`APIX_HI_MSB{1'b0}}, frame0_ptr_hi};
wire [15:0] frame0_ptr_hi_rd = frame0_ptr_hi_tmp[15:0];
`endif
 
//------------------------------------------------
// FRAME0_PTR_LO Register
//------------------------------------------------
reg [`APIX_LO_MSB:0] frame0_ptr_lo;
 
wire frame0_ptr_lo_wr = reg_wr[FRAME0_PTR_LO];
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) frame0_ptr_lo <= {`APIX_LO_MSB+1{1'b0}};
else if (frame0_ptr_lo_wr) frame0_ptr_lo <= per_din_i[`APIX_LO_MSB:0];
 
`ifdef VRAM_BIGGER_4_KW
assign frame0_ptr = {frame0_ptr_hi[`APIX_HI_MSB:0], frame0_ptr_lo};
wire [15:0] frame0_ptr_lo_rd = frame0_ptr_lo;
`else
assign frame0_ptr = {frame0_ptr_lo[`APIX_LO_MSB:0]};
wire [16:0] frame0_ptr_lo_tmp = {{16-`APIX_LO_MSB{1'b0}}, frame0_ptr_lo};
wire [15:0] frame0_ptr_lo_rd = frame0_ptr_lo_tmp[15:0];
`endif
 
//------------------------------------------------
// FRAME1_PTR_HI Register
//------------------------------------------------
`ifdef WITH_FRAME1_POINTER
`ifdef VRAM_BIGGER_4_KW
reg [`APIX_HI_MSB:0] frame1_ptr_hi;
 
wire frame1_ptr_hi_wr = reg_wr[FRAME1_PTR_HI];
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) frame1_ptr_hi <= {`APIX_HI_MSB+1{1'b0}};
else if (frame1_ptr_hi_wr) frame1_ptr_hi <= per_din_i[`APIX_HI_MSB:0];
 
wire [16:0] frame1_ptr_hi_tmp = {{16-`APIX_HI_MSB{1'b0}}, frame1_ptr_hi};
wire [15:0] frame1_ptr_hi_rd = frame1_ptr_hi_tmp[15:0];
`endif
`endif
 
//------------------------------------------------
// FRAME1_PTR_LO Register
//------------------------------------------------
`ifdef WITH_FRAME1_POINTER
reg [`APIX_LO_MSB:0] frame1_ptr_lo;
 
wire frame1_ptr_lo_wr = reg_wr[FRAME1_PTR_LO];
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) frame1_ptr_lo <= {`APIX_LO_MSB+1{1'b0}};
else if (frame1_ptr_lo_wr) frame1_ptr_lo <= per_din_i[`APIX_LO_MSB:0];
 
`ifdef VRAM_BIGGER_4_KW
assign frame1_ptr = {frame1_ptr_hi[`APIX_HI_MSB:0], frame1_ptr_lo};
wire [15:0] frame1_ptr_lo_rd = frame1_ptr_lo;
`else
assign frame1_ptr = {frame1_ptr_lo[`APIX_LO_MSB:0]};
wire [16:0] frame1_ptr_lo_tmp = {{16-`APIX_LO_MSB{1'b0}}, frame1_ptr_lo};
wire [15:0] frame1_ptr_lo_rd = frame1_ptr_lo_tmp[15:0];
`endif
`endif
 
//------------------------------------------------
// FRAME2_PTR_HI Register
//------------------------------------------------
`ifdef WITH_FRAME2_POINTER
`ifdef VRAM_BIGGER_4_KW
reg [`APIX_HI_MSB:0] frame2_ptr_hi;
 
wire frame2_ptr_hi_wr = reg_wr[FRAME2_PTR_HI];
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) frame2_ptr_hi <= {`APIX_HI_MSB+1{1'b0}};
else if (frame2_ptr_hi_wr) frame2_ptr_hi <= per_din_i[`APIX_HI_MSB:0];
 
wire [16:0] frame2_ptr_hi_tmp = {{16-`APIX_HI_MSB{1'b0}}, frame2_ptr_hi};
wire [15:0] frame2_ptr_hi_rd = frame2_ptr_hi_tmp[15:0];
`endif
`endif
 
//------------------------------------------------
// FRAME2_PTR_LO Register
//------------------------------------------------
`ifdef WITH_FRAME2_POINTER
reg [`APIX_LO_MSB:0] frame2_ptr_lo;
 
wire frame2_ptr_lo_wr = reg_wr[FRAME2_PTR_LO];
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) frame2_ptr_lo <= {`APIX_LO_MSB+1{1'b0}};
else if (frame2_ptr_lo_wr) frame2_ptr_lo <= per_din_i[`APIX_LO_MSB:0];
 
`ifdef VRAM_BIGGER_4_KW
assign frame2_ptr = {frame2_ptr_hi[`APIX_HI_MSB:0], frame2_ptr_lo};
wire [15:0] frame2_ptr_lo_rd = frame2_ptr_lo;
`else
assign frame2_ptr = {frame2_ptr_lo[`APIX_LO_MSB:0]};
wire [16:0] frame2_ptr_lo_tmp = {{16-`APIX_LO_MSB{1'b0}}, frame2_ptr_lo};
wire [15:0] frame2_ptr_lo_rd = frame2_ptr_lo_tmp[15:0];
`endif
`endif
 
//------------------------------------------------
// FRAME3_PTR_HI Register
//------------------------------------------------
`ifdef WITH_FRAME3_POINTER
`ifdef VRAM_BIGGER_4_KW
reg [`APIX_HI_MSB:0] frame3_ptr_hi;
 
wire frame3_ptr_hi_wr = reg_wr[FRAME3_PTR_HI];
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) frame3_ptr_hi <= {`APIX_HI_MSB+1{1'b0}};
else if (frame3_ptr_hi_wr) frame3_ptr_hi <= per_din_i[`APIX_HI_MSB:0];
 
wire [16:0] frame3_ptr_hi_tmp = {{16-`APIX_HI_MSB{1'b0}},frame3_ptr_hi};
wire [15:0] frame3_ptr_hi_rd = frame3_ptr_hi_tmp[15:0];
`endif
`endif
 
//------------------------------------------------
// FRAME3_PTR_LO Register
//------------------------------------------------
`ifdef WITH_FRAME3_POINTER
reg [`APIX_LO_MSB:0] frame3_ptr_lo;
 
wire frame3_ptr_lo_wr = reg_wr[FRAME3_PTR_LO];
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) frame3_ptr_lo <= {`APIX_LO_MSB+1{1'b0}};
else if (frame3_ptr_lo_wr) frame3_ptr_lo <= per_din_i[`APIX_LO_MSB:0];
 
`ifdef VRAM_BIGGER_4_KW
assign frame3_ptr = {frame3_ptr_hi[`APIX_HI_MSB:0], frame3_ptr_lo};
wire [15:0] frame3_ptr_lo_rd = frame3_ptr_lo;
`else
assign frame3_ptr = {frame3_ptr_lo[`APIX_LO_MSB:0]};
wire [16:0] frame3_ptr_lo_tmp = {{16-`APIX_LO_MSB{1'b0}}, frame3_ptr_lo};
wire [15:0] frame3_ptr_lo_rd = frame3_ptr_lo_tmp[15:0];
`endif
`endif
 
//------------------------------------------------
// VID_RAM0 Interface
//------------------------------------------------
wire [15:0] vid_ram0_cfg;
wire [15:0] vid_ram0_width;
`ifdef VRAM_BIGGER_4_KW
wire [15:0] vid_ram0_addr_hi;
`endif
wire [15:0] vid_ram0_addr_lo;
wire [15:0] vid_ram0_data;
 
wire vid_ram0_we;
wire vid_ram0_ce;
wire [15:0] vid_ram0_din;
wire [`APIX_MSB:0] vid_ram0_addr_nxt;
wire vid_ram0_access;
 
ogfx_reg_vram_if ogfx_reg_vram0_if_inst (
 
// OUTPUTs
.vid_ram_cfg_o ( vid_ram0_cfg ), // VID_RAM0_CFG Register
.vid_ram_width_o ( vid_ram0_width ), // VID_RAM0_WIDTH Register
`ifdef VRAM_BIGGER_4_KW
.vid_ram_addr_hi_o ( vid_ram0_addr_hi ), // VID_RAM0_ADDR_HI Register
`endif
.vid_ram_addr_lo_o ( vid_ram0_addr_lo ), // VID_RAM0_ADDR_LO Register
.vid_ram_data_o ( vid_ram0_data ), // VID_RAM0_DATA Register
 
.vid_ram_we_o ( vid_ram0_we ), // Video-RAM Write strobe
.vid_ram_ce_o ( vid_ram0_ce ), // Video-RAM Chip enable
.vid_ram_din_o ( vid_ram0_din ), // Video-RAM Data input
.vid_ram_addr_nxt_o ( vid_ram0_addr_nxt ), // Video-RAM Next address
.vid_ram_access_o ( vid_ram0_access ), // Video-RAM Access
 
// INPUTs
.mclk ( mclk ), // Main system clock
.puc_rst ( puc_rst ), // Main system reset
 
.vid_ram_cfg_wr_i ( reg_wr[VID_RAM0_CFG] ), // VID_RAM0_CFG Write strobe
.vid_ram_width_wr_i ( reg_wr[VID_RAM0_WIDTH] ), // VID_RAM0_WIDTH Write strobe
`ifdef VRAM_BIGGER_4_KW
.vid_ram_addr_hi_wr_i ( reg_wr[VID_RAM0_ADDR_HI] ), // VID_RAM0_ADDR_HI Write strobe
`endif
.vid_ram_addr_lo_wr_i ( reg_wr[VID_RAM0_ADDR_LO] ), // VID_RAM0_ADDR_LO Write strobe
.vid_ram_data_wr_i ( reg_wr[VID_RAM0_DATA] ), // VID_RAM0_DATA Write strobe
.vid_ram_data_rd_i ( reg_rd[VID_RAM0_DATA] ), // VID_RAM0_DATA Read strobe
 
.dbg_freeze_i ( dbg_freeze_i ), // Freeze auto-increment on read when CPU stopped
.display_width_i ( display_width_o ), // Display width
.gfx_mode_1_bpp_i ( gfx_mode_1_bpp ), // Graphic mode 1 bpp resolution
.gfx_mode_2_bpp_i ( gfx_mode_2_bpp ), // Graphic mode 2 bpp resolution
.gfx_mode_4_bpp_i ( gfx_mode_4_bpp ), // Graphic mode 4 bpp resolution
.gfx_mode_8_bpp_i ( gfx_mode_8_bpp ), // Graphic mode 8 bpp resolution
.gfx_mode_16_bpp_i ( gfx_mode_16_bpp ), // Graphic mode 16 bpp resolution
 
.per_din_i ( per_din_i ), // Peripheral data input
.vid_ram_base_addr_i ( vid_ram0_base_addr ), // Video-RAM base address
.vid_ram_dout_i ( vid_ram_dout_i ) // Video-RAM data input
);
 
//------------------------------------------------
// VID_RAM1 Interface
//------------------------------------------------
wire [15:0] vid_ram1_cfg;
wire [15:0] vid_ram1_width;
`ifdef VRAM_BIGGER_4_KW
wire [15:0] vid_ram1_addr_hi;
`endif
wire [15:0] vid_ram1_addr_lo;
wire [15:0] vid_ram1_data;
 
wire vid_ram1_we;
wire vid_ram1_ce;
wire [15:0] vid_ram1_din;
wire [`APIX_MSB:0] vid_ram1_addr_nxt;
wire vid_ram1_access;
 
ogfx_reg_vram_if ogfx_reg_vram1_if_inst (
 
// OUTPUTs
.vid_ram_cfg_o ( vid_ram1_cfg ), // VID_RAM1_CFG Register
.vid_ram_width_o ( vid_ram1_width ), // VID_RAM1_WIDTH Register
`ifdef VRAM_BIGGER_4_KW
.vid_ram_addr_hi_o ( vid_ram1_addr_hi ), // VID_RAM1_ADDR_HI Register
`endif
.vid_ram_addr_lo_o ( vid_ram1_addr_lo ), // VID_RAM1_ADDR_LO Register
.vid_ram_data_o ( vid_ram1_data ), // VID_RAM1_DATA Register
 
.vid_ram_we_o ( vid_ram1_we ), // Video-RAM Write strobe
.vid_ram_ce_o ( vid_ram1_ce ), // Video-RAM Chip enable
.vid_ram_din_o ( vid_ram1_din ), // Video-RAM Data input
.vid_ram_addr_nxt_o ( vid_ram1_addr_nxt ), // Video-RAM Next address
.vid_ram_access_o ( vid_ram1_access ), // Video-RAM Access
 
// INPUTs
.mclk ( mclk ), // Main system clock
.puc_rst ( puc_rst ), // Main system reset
 
.vid_ram_cfg_wr_i ( reg_wr[VID_RAM1_CFG] ), // VID_RAM1_CFG Write strobe
.vid_ram_width_wr_i ( reg_wr[VID_RAM1_WIDTH] ), // VID_RAM1_WIDTH Write strobe
`ifdef VRAM_BIGGER_4_KW
.vid_ram_addr_hi_wr_i ( reg_wr[VID_RAM1_ADDR_HI] ), // VID_RAM1_ADDR_HI Write strobe
`endif
.vid_ram_addr_lo_wr_i ( reg_wr[VID_RAM1_ADDR_LO] ), // VID_RAM1_ADDR_LO Write strobe
.vid_ram_data_wr_i ( reg_wr[VID_RAM1_DATA] ), // VID_RAM1_DATA Write strobe
.vid_ram_data_rd_i ( reg_rd[VID_RAM1_DATA] ), // VID_RAM1_DATA Read strobe
 
.dbg_freeze_i ( dbg_freeze_i ), // Freeze auto-increment on read when CPU stopped
.display_width_i ( display_width_o ), // Display width
.gfx_mode_1_bpp_i ( gfx_mode_1_bpp ), // Graphic mode 1 bpp resolution
.gfx_mode_2_bpp_i ( gfx_mode_2_bpp ), // Graphic mode 2 bpp resolution
.gfx_mode_4_bpp_i ( gfx_mode_4_bpp ), // Graphic mode 4 bpp resolution
.gfx_mode_8_bpp_i ( gfx_mode_8_bpp ), // Graphic mode 8 bpp resolution
.gfx_mode_16_bpp_i ( gfx_mode_16_bpp ), // Graphic mode 16 bpp resolution
 
.per_din_i ( per_din_i ), // Peripheral data input
.vid_ram_base_addr_i ( vid_ram1_base_addr ), // Video-RAM base address
.vid_ram_dout_i ( vid_ram_dout_i ) // Video-RAM data input
);
 
//------------------------------------------------
// GPU Interface (GPU_CMD/GPU_STAT) Registers
//------------------------------------------------
 
wire [3:0] gpu_stat_fifo_cnt;
wire gpu_stat_fifo_empty;
wire gpu_stat_fifo_full;
 
ogfx_reg_fifo ogfx_reg_fifo_gpu_inst (
 
// OUTPUTs
.fifo_cnt_o ( gpu_stat_fifo_cnt ), // Fifo counter
.fifo_data_o ( gpu_data_o ), // Read data output
.fifo_done_evt_o ( gpu_fifo_done_evt ), // Fifo has been emptied
.fifo_empty_o ( gpu_stat_fifo_empty ), // Fifo is currentely empty
.fifo_full_o ( gpu_stat_fifo_full ), // Fifo is currentely full
.fifo_ovfl_evt_o ( gpu_fifo_ovfl_evt ), // Fifo overflow event
 
// INPUTs
.mclk ( mclk ), // Main system clock
.puc_rst ( puc_rst ), // Main system reset
 
.fifo_data_i ( per_din_i ), // Read data input
.fifo_enable_i ( gpu_enable_o ), // Enable fifo (flushed when disabled)
.fifo_pop_i ( gpu_get_data_i ), // Pop data from the fifo
.fifo_push_i ( reg_wr[GPU_CMD] ) // Push new data to the fifo
);
 
assign gpu_data_avail_o = ~gpu_stat_fifo_empty;
 
wire [15:0] gpu_stat = {10'h000, gpu_stat_fifo_full, gpu_stat_fifo_empty, gpu_stat_fifo_cnt};
 
 
//============================================================================
// 4) DATA OUTPUT GENERATION
//============================================================================
 
// Data output mux
wire [15:0] gfx_ctrl_read = gfx_ctrl & {16{reg_rd[GFX_CTRL ]}};
wire [15:0] gfx_status_read = gfx_status & {16{reg_rd[GFX_STATUS ]}};
wire [15:0] gfx_irq_read = gfx_irq & {16{reg_rd[GFX_IRQ ]}};
 
wire [15:0] display_width_read = display_width_rd & {16{reg_rd[DISPLAY_WIDTH ]}};
wire [15:0] display_height_read = display_height_rd & {16{reg_rd[DISPLAY_HEIGHT ]}};
`ifdef WITH_DISPLAY_SIZE_HI
wire [15:0] display_size_hi_read = display_size_hi_rd & {16{reg_rd[DISPLAY_SIZE_HI ]}};
`endif
wire [15:0] display_size_lo_read = display_size_lo_rd & {16{reg_rd[DISPLAY_SIZE_LO ]}};
wire [15:0] display_cfg_read = display_cfg & {16{reg_rd[DISPLAY_CFG ]}};
 
wire [15:0] lt24_cfg_read = lt24_cfg & {16{reg_rd[LT24_CFG ]}};
wire [15:0] lt24_refresh_read = lt24_refresh & {16{reg_rd[LT24_REFRESH ]}};
wire [15:0] lt24_refresh_sync_read = lt24_refresh_sync & {16{reg_rd[LT24_REFRESH_SYNC ]}};
wire [15:0] lt24_cmd_read = lt24_cmd & {16{reg_rd[LT24_CMD ]}};
wire [15:0] lt24_cmd_param_read = lt24_cmd_param_o & {16{reg_rd[LT24_CMD_PARAM ]}};
wire [15:0] lt24_cmd_dfill_read = lt24_cmd_dfill_o & {16{reg_rd[LT24_CMD_DFILL ]}};
wire [15:0] lt24_status_read = lt24_status & {16{reg_rd[LT24_STATUS ]}};
 
wire [15:0] lut_ram_addr_read = lut_ram_addr_rd & {16{reg_rd[LUT_RAM_ADDR ]}};
wire [15:0] lut_ram_data_read = lut_ram_data & {16{reg_rd[LUT_RAM_DATA ]}};
 
wire [15:0] frame_select_read = frame_select & {16{reg_rd[FRAME_SELECT ]}};
`ifdef VRAM_BIGGER_4_KW
wire [15:0] frame0_ptr_hi_read = frame0_ptr_hi_rd & {16{reg_rd[FRAME0_PTR_HI ]}};
`endif
wire [15:0] frame0_ptr_lo_read = frame0_ptr_lo_rd & {16{reg_rd[FRAME0_PTR_LO ]}};
`ifdef WITH_FRAME1_POINTER
`ifdef VRAM_BIGGER_4_KW
wire [15:0] frame1_ptr_hi_read = frame1_ptr_hi_rd & {16{reg_rd[FRAME1_PTR_HI ]}};
`endif
wire [15:0] frame1_ptr_lo_read = frame1_ptr_lo_rd & {16{reg_rd[FRAME1_PTR_LO ]}};
`endif
`ifdef WITH_FRAME2_POINTER
`ifdef VRAM_BIGGER_4_KW
wire [15:0] frame2_ptr_hi_read = frame2_ptr_hi_rd & {16{reg_rd[FRAME2_PTR_HI ]}};
`endif
wire [15:0] frame2_ptr_lo_read = frame2_ptr_lo_rd & {16{reg_rd[FRAME2_PTR_LO ]}};
`endif
`ifdef WITH_FRAME3_POINTER
`ifdef VRAM_BIGGER_4_KW
wire [15:0] frame3_ptr_hi_read = frame3_ptr_hi_rd & {16{reg_rd[FRAME3_PTR_HI ]}};
`endif
wire [15:0] frame3_ptr_lo_read = frame3_ptr_lo_rd & {16{reg_rd[FRAME3_PTR_LO ]}};
`endif
wire [15:0] vid_ram0_cfg_read = vid_ram0_cfg & {16{reg_rd[VID_RAM0_CFG ]}};
wire [15:0] vid_ram0_width_read = vid_ram0_width & {16{reg_rd[VID_RAM0_WIDTH ]}};
`ifdef VRAM_BIGGER_4_KW
wire [15:0] vid_ram0_addr_hi_read = vid_ram0_addr_hi & {16{reg_rd[VID_RAM0_ADDR_HI ]}};
`endif
wire [15:0] vid_ram0_addr_lo_read = vid_ram0_addr_lo & {16{reg_rd[VID_RAM0_ADDR_LO ]}};
wire [15:0] vid_ram0_data_read = vid_ram0_data & {16{reg_rd[VID_RAM0_DATA ]}};
 
wire [15:0] vid_ram1_cfg_read = vid_ram1_cfg & {16{reg_rd[VID_RAM1_CFG ]}};
wire [15:0] vid_ram1_width_read = vid_ram1_width & {16{reg_rd[VID_RAM1_WIDTH ]}};
`ifdef VRAM_BIGGER_4_KW
wire [15:0] vid_ram1_addr_hi_read = vid_ram1_addr_hi & {16{reg_rd[VID_RAM1_ADDR_HI ]}};
`endif
wire [15:0] vid_ram1_addr_lo_read = vid_ram1_addr_lo & {16{reg_rd[VID_RAM1_ADDR_LO ]}};
wire [15:0] vid_ram1_data_read = vid_ram1_data & {16{reg_rd[VID_RAM1_DATA ]}};
wire [15:0] gpu_cmd_read = 16'h0000 & {16{reg_rd[GPU_CMD ]}};
wire [15:0] gpu_stat_read = gpu_stat & {16{reg_rd[GPU_STAT ]}};
 
 
wire [15:0] per_dout_o = gfx_ctrl_read |
gfx_status_read |
gfx_irq_read |
 
display_width_read |
display_height_read |
`ifdef WITH_DISPLAY_SIZE_HI
display_size_hi_read |
`endif
display_size_lo_read |
display_cfg_read |
 
lt24_cfg_read |
lt24_refresh_read |
lt24_refresh_sync_read |
lt24_cmd_read |
lt24_cmd_param_read |
lt24_cmd_dfill_read |
lt24_status_read |
 
lut_ram_addr_read |
lut_ram_data_read |
 
frame_select_read |
`ifdef VRAM_BIGGER_4_KW
frame0_ptr_hi_read |
`endif
frame0_ptr_lo_read |
`ifdef WITH_FRAME1_POINTER
`ifdef VRAM_BIGGER_4_KW
frame1_ptr_hi_read |
`endif
frame1_ptr_lo_read |
`endif
`ifdef WITH_FRAME2_POINTER
`ifdef VRAM_BIGGER_4_KW
frame2_ptr_hi_read |
`endif
frame2_ptr_lo_read |
`endif
`ifdef WITH_FRAME3_POINTER
`ifdef VRAM_BIGGER_4_KW
frame3_ptr_hi_read |
`endif
frame3_ptr_lo_read |
`endif
vid_ram0_cfg_read |
vid_ram0_width_read |
`ifdef VRAM_BIGGER_4_KW
vid_ram0_addr_hi_read |
`endif
vid_ram0_addr_lo_read |
vid_ram0_data_read |
 
vid_ram1_cfg_read |
vid_ram1_width_read |
`ifdef VRAM_BIGGER_4_KW
vid_ram1_addr_hi_read |
`endif
vid_ram1_addr_lo_read |
vid_ram1_data_read |
gpu_cmd_read |
gpu_stat_read;
 
 
//============================================================================
// 5) VIDEO MEMORY INTERFACE
//============================================================================
 
// Write access strobe
assign vid_ram_wen_o = ~(vid_ram0_we | vid_ram1_we);
 
// Chip enable.
assign vid_ram_cen_o = ~(vid_ram0_ce | vid_ram1_ce);
 
// Data to be written
assign vid_ram_din_o = (vid_ram0_din | vid_ram1_din);
 
// Detect memory accesses for ADDR update
wire vid_ram_access = (vid_ram0_access | vid_ram1_access);
 
// Next Address
wire [`APIX_MSB:0] vid_ram_addr_nxt = (vid_ram0_addr_nxt | vid_ram1_addr_nxt);
 
// Align according to graphic mode
wire [`VRAM_MSB:0] vid_ram_addr_align = ({`VRAM_AWIDTH{gfx_mode_1_bpp }} & vid_ram_addr_nxt[`APIX_MSB-0:4]) |
({`VRAM_AWIDTH{gfx_mode_2_bpp }} & vid_ram_addr_nxt[`APIX_MSB-1:3]) |
({`VRAM_AWIDTH{gfx_mode_4_bpp }} & vid_ram_addr_nxt[`APIX_MSB-2:2]) |
({`VRAM_AWIDTH{gfx_mode_8_bpp }} & vid_ram_addr_nxt[`APIX_MSB-3:1]) |
({`VRAM_AWIDTH{gfx_mode_16_bpp}} & vid_ram_addr_nxt[`APIX_MSB-4:0]) ;
 
// Generate Video RAM address
reg [`VRAM_MSB:0] vid_ram_addr_o;
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) vid_ram_addr_o <= {`VRAM_AWIDTH{1'b0}};
else if (vid_ram_access) vid_ram_addr_o <= vid_ram_addr_align;
 
 
endmodule // ogfx_reg
 
`ifdef OGFX_NO_INCLUDE
`else
`include "openGFX430_undefines.v"
`endif
/core/rtl/verilog/ogfx_backend_lut_fifo.v
0,0 → 1,363
//----------------------------------------------------------------------------
// Copyright (C) 2015 Authors
//
// This source file may be used and distributed without restriction provided
// that this copyright statement is not removed from the file and that any
// derivative work contains the original copyright notice and the associated
// disclaimer.
//
// This source file is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This source is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
// License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this source; if not, write to the Free Software Foundation,
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
//----------------------------------------------------------------------------
//
// *File Name: ogfx_backend_lut_fifo.v
//
// *Module Description:
// Mini-cache memory for the LUT memory accesses.
//
// *Author(s):
// - Olivier Girard, olgirard@gmail.com
//
//----------------------------------------------------------------------------
// $Rev$
// $LastChangedBy$
// $LastChangedDate$
//----------------------------------------------------------------------------
`ifdef OGFX_NO_INCLUDE
`else
`include "openGFX430_defines.v"
`endif
 
module ogfx_backend_lut_fifo (
 
// OUTPUTs
frame_data_request_o, // Request for next frame data
 
refresh_data_o, // Display Refresh data
refresh_data_ready_o, // Display Refresh data ready
 
`ifdef WITH_PROGRAMMABLE_LUT
lut_ram_addr_o, // LUT-RAM address
lut_ram_cen_o, // LUT-RAM enable (active low)
`endif
 
// INPUTs
mclk, // Main system clock
puc_rst, // Main system reset
 
frame_data_i, // Frame data
frame_data_ready_i, // Frame data ready
 
gfx_mode_i, // Video mode (1xx:16bpp / 011:8bpp / 010:4bpp / 001:2bpp / 000:1bpp)
 
`ifdef WITH_PROGRAMMABLE_LUT
lut_ram_dout_i, // LUT-RAM data output
lut_ram_dout_rdy_nxt_i, // LUT-RAM data output ready during next cycle
`endif
 
refresh_active_i, // Display refresh on going
refresh_data_request_i, // Request for next refresh data
refresh_lut_select_i // Refresh LUT bank selection
);
 
// OUTPUTs
//=========
output frame_data_request_o; // Request for next frame data
 
output [15:0] refresh_data_o; // Display Refresh data
output refresh_data_ready_o; // Display Refresh data ready
 
`ifdef WITH_PROGRAMMABLE_LUT
output [`LRAM_MSB:0] lut_ram_addr_o; // LUT-RAM address
output lut_ram_cen_o; // LUT-RAM enable (active low)
`endif
 
// INPUTs
//=========
input mclk; // Main system clock
input puc_rst; // Main system reset
 
input [15:0] frame_data_i; // Frame data
input frame_data_ready_i; // Frame data ready
 
input [2:0] gfx_mode_i; // Video mode (1xx:16bpp / 011:8bpp / 010:4bpp / 001:2bpp / 000:1bpp)
 
`ifdef WITH_PROGRAMMABLE_LUT
input [15:0] lut_ram_dout_i; // LUT-RAM data output
input lut_ram_dout_rdy_nxt_i; // LUT-RAM data output ready during next cycle
`endif
 
input refresh_active_i; // Display refresh on going
input refresh_data_request_i; // Request for next refresh data
input [1:0] refresh_lut_select_i; // Refresh LUT bank selection
 
 
//=============================================================================
// 1) WIRE, REGISTERS AND PARAMETER DECLARATION
//=============================================================================
 
// State machine registers
reg [1:0] lut_state;
reg [1:0] lut_state_nxt;
 
// State definition
parameter STATE_IDLE = 0,
STATE_FRAME_DATA = 1,
STATE_LUT_DATA = 2,
STATE_HOLD = 3;
 
// Some parameter(s)
parameter FIFO_EMPTY = 3'h0,
FIFO_FULL = 3'h5;
 
// Video modes decoding
wire gfx_mode_1_bpp = (gfx_mode_i == 3'b000);
wire gfx_mode_2_bpp = (gfx_mode_i == 3'b001);
wire gfx_mode_4_bpp = (gfx_mode_i == 3'b010);
wire gfx_mode_8_bpp = (gfx_mode_i == 3'b011);
wire gfx_mode_16_bpp = ~(gfx_mode_8_bpp | gfx_mode_4_bpp |
gfx_mode_2_bpp | gfx_mode_1_bpp);
 
// Others
reg [2:0] fifo_counter;
wire [2:0] fifo_counter_nxt;
 
 
//============================================================================
// 2) HARD CODED LOOKUP TABLE
//============================================================================
 
wire [15:0] lut_hw_data_1_bpp = ({5'b00000, 6'b000000, 5'b00000} & {16{frame_data_i[0] ==1'b0 }}) | // 1 bpp: Black
({5'b11111, 6'b111111, 5'b11111} & {16{frame_data_i[0] ==1'b1 }}) ; // White
 
wire [15:0] lut_hw_data_2_bpp = ({5'b00000, 6'b000000, 5'b00000} & {16{frame_data_i[0] ==2'b00 }}) | // 2 bpp: Black
({5'b01000, 6'b010000, 5'b01000} & {16{frame_data_i[0] ==2'b01 }}) | // Dark Gray
({5'b11000, 6'b110000, 5'b11000} & {16{frame_data_i[0] ==2'b10 }}) | // Light Gray
({5'b11111, 6'b111111, 5'b11111} & {16{frame_data_i[0] ==2'b11 }}) ; // White
 
wire [15:0] lut_hw_data_4_bpp = ({5'b00000, 6'b000000, 5'b00000} & {16{frame_data_i[3:0]==4'b0000}}) | // 4 bpp: Black
({5'b00000, 6'b000000, 5'b10000} & {16{frame_data_i[3:0]==4'b0001}}) | // Dark Blue
({5'b10000, 6'b000000, 5'b00000} & {16{frame_data_i[3:0]==4'b0010}}) | // Dark Red
({5'b10000, 6'b000000, 5'b10000} & {16{frame_data_i[3:0]==4'b0011}}) | // Dark Magenta
({5'b00000, 6'b100000, 5'b00000} & {16{frame_data_i[3:0]==4'b0100}}) | // Dark Green
({5'b00000, 6'b100000, 5'b10000} & {16{frame_data_i[3:0]==4'b0101}}) | // Dark Cyan
({5'b10000, 6'b100000, 5'b00000} & {16{frame_data_i[3:0]==4'b0110}}) | // Dark Yellow
({5'b10000, 6'b100000, 5'b10000} & {16{frame_data_i[3:0]==4'b0111}}) | // Gray
({5'b00000, 6'b000000, 5'b00000} & {16{frame_data_i[3:0]==4'b1000}}) | // Black
({5'b00000, 6'b000000, 5'b11111} & {16{frame_data_i[3:0]==4'b1001}}) | // Blue
({5'b11111, 6'b000000, 5'b00000} & {16{frame_data_i[3:0]==4'b1010}}) | // Red
({5'b11111, 6'b000000, 5'b11111} & {16{frame_data_i[3:0]==4'b1011}}) | // Magenta
({5'b00000, 6'b111111, 5'b00000} & {16{frame_data_i[3:0]==4'b1100}}) | // Green
({5'b00000, 6'b111111, 5'b11111} & {16{frame_data_i[3:0]==4'b1101}}) | // Cyan
({5'b11111, 6'b111111, 5'b00000} & {16{frame_data_i[3:0]==4'b1110}}) | // Yellow
({5'b11111, 6'b111111, 5'b11111} & {16{frame_data_i[3:0]==4'b1111}}); // White
 
wire [15:0] lut_hw_data_8_bpp = {frame_data_i[7],frame_data_i[6],frame_data_i[5],frame_data_i[5],frame_data_i[5], // 8 bpp: R = D<7,6,5,5,5>
frame_data_i[4],frame_data_i[3],frame_data_i[2],frame_data_i[2],frame_data_i[2],frame_data_i[2], // G = D<4,3,2,2,2,2>
frame_data_i[1],frame_data_i[0],frame_data_i[0],frame_data_i[0],frame_data_i[0]}; // B = D<1,0,0,0,0>
 
wire [15:0] lut_hw_data = (lut_hw_data_1_bpp & {16{gfx_mode_1_bpp}}) |
(lut_hw_data_2_bpp & {16{gfx_mode_2_bpp}}) |
(lut_hw_data_4_bpp & {16{gfx_mode_4_bpp}}) |
(lut_hw_data_8_bpp & {16{gfx_mode_8_bpp}});
 
wire lut_hw_enabled = ~gfx_mode_16_bpp & ~refresh_lut_select_i[0];
wire lut_sw_enabled = ~gfx_mode_16_bpp & refresh_lut_select_i[0];
 
 
//============================================================================
// 3) STATE MACHINE
//============================================================================
 
//--------------------------------
// States Transitions
//--------------------------------
always @(lut_state or refresh_active_i or frame_data_ready_i or
`ifdef WITH_PROGRAMMABLE_LUT
lut_sw_enabled or lut_ram_dout_rdy_nxt_i or
`endif
fifo_counter_nxt)
case(lut_state)
 
STATE_IDLE : lut_state_nxt = ~refresh_active_i ? STATE_IDLE : STATE_FRAME_DATA ;
 
STATE_FRAME_DATA : lut_state_nxt = ~refresh_active_i ? STATE_IDLE :
~frame_data_ready_i ? STATE_FRAME_DATA :
`ifdef WITH_PROGRAMMABLE_LUT
lut_sw_enabled ? STATE_LUT_DATA :
`endif
STATE_HOLD ;
 
`ifdef WITH_PROGRAMMABLE_LUT
STATE_LUT_DATA : lut_state_nxt = ~refresh_active_i ? STATE_IDLE :
lut_ram_dout_rdy_nxt_i ? STATE_HOLD : STATE_LUT_DATA ;
`endif
 
STATE_HOLD : lut_state_nxt = ~refresh_active_i ? STATE_IDLE :
(fifo_counter_nxt!=FIFO_FULL) ? STATE_FRAME_DATA : STATE_HOLD ;
 
// pragma coverage off
default : lut_state_nxt = STATE_IDLE;
// pragma coverage on
endcase
 
//--------------------------------
// State machine
//--------------------------------
always @(posedge mclk or posedge puc_rst)
if (puc_rst) lut_state <= STATE_IDLE;
else lut_state <= lut_state_nxt;
 
 
// Request for the next frame data
assign frame_data_request_o = (lut_state == STATE_FRAME_DATA);
 
 
//============================================================================
// 4) LUT MEMORY INTERFACE
//============================================================================
 
//--------------------------------
// Enable
//--------------------------------
`ifdef WITH_PROGRAMMABLE_LUT
assign lut_ram_cen_o = ~(lut_state == STATE_LUT_DATA);
`endif
 
//--------------------------------
// Address
//--------------------------------
// Mask with chip enable to save power
 
`ifdef WITH_PROGRAMMABLE_LUT
`ifdef WITH_EXTRA_LUT_BANK
// Allow LUT bank switching only when the refresh is not on going
reg refresh_lut_bank_select_sync;
always @(posedge mclk or posedge puc_rst)
if (puc_rst) refresh_lut_bank_select_sync <= 1'b0;
else if (~refresh_active_i) refresh_lut_bank_select_sync <= refresh_lut_select_i[1];
 
assign lut_ram_addr_o = {refresh_lut_bank_select_sync, frame_data_i[7:0]} & {9{~lut_ram_cen_o}};
`else
assign lut_ram_addr_o = frame_data_i[7:0] & {8{~lut_ram_cen_o}};
`endif
`endif
 
//--------------------------------
// Data Ready
//--------------------------------
// When filling the FIFO, the data is available on the bus
// one cycle after the rdy_nxt signal
reg lut_ram_dout_ready;
always @(posedge mclk or posedge puc_rst)
if (puc_rst) lut_ram_dout_ready <= 1'b0;
`ifdef WITH_PROGRAMMABLE_LUT
else lut_ram_dout_ready <= lut_sw_enabled ? lut_ram_dout_rdy_nxt_i :
(frame_data_ready_i & (lut_state == STATE_FRAME_DATA));
`else
else lut_ram_dout_ready <= (frame_data_ready_i & (lut_state == STATE_FRAME_DATA));
`endif
 
 
//============================================================================
// 5) FIFO COUNTER
//============================================================================
 
// Control signals
wire fifo_push = lut_ram_dout_ready & (fifo_counter != FIFO_FULL);
wire fifo_pop = refresh_data_request_i & (fifo_counter != FIFO_EMPTY);
 
// Fifo counter
assign fifo_counter_nxt = ~refresh_active_i ? FIFO_EMPTY : // Initialize
(fifo_push & fifo_pop) ? fifo_counter : // Keep value (pop & push at the same time)
fifo_push ? fifo_counter + 3'h1 : // Push
fifo_pop ? fifo_counter - 3'h1 : // Pop
fifo_counter; // Hold
 
always @(posedge mclk or posedge puc_rst)
if (puc_rst) fifo_counter <= FIFO_EMPTY;
else fifo_counter <= fifo_counter_nxt;
 
 
//============================================================================
// 6) FIFO MEMORY & RD/WR POINTERS
//============================================================================
 
// Write pointer
reg [2:0] wr_ptr;
always @(posedge mclk or posedge puc_rst)
if (puc_rst) wr_ptr <= 3'h0;
else if (~refresh_active_i) wr_ptr <= 3'h0;
else if (fifo_push)
begin
if (wr_ptr==(FIFO_FULL-1)) wr_ptr <= 3'h0;
else wr_ptr <= wr_ptr + 3'h1;
end
 
// Memory
reg [15:0] fifo_mem [0:4];
always @(posedge mclk or posedge puc_rst)
if (puc_rst)
begin
fifo_mem[0] <= 16'h0000;
fifo_mem[1] <= 16'h0000;
fifo_mem[2] <= 16'h0000;
fifo_mem[3] <= 16'h0000;
fifo_mem[4] <= 16'h0000;
end
else if (fifo_push)
begin
fifo_mem[wr_ptr] <= lut_hw_enabled ? lut_hw_data :
`ifdef WITH_PROGRAMMABLE_LUT
lut_sw_enabled ? lut_ram_dout_i :
`endif
frame_data_i;
end
 
// Read pointer
reg [2:0] rd_ptr;
always @(posedge mclk or posedge puc_rst)
if (puc_rst) rd_ptr <= 3'h0;
else if (~refresh_active_i) rd_ptr <= 3'h0;
else if (fifo_pop)
begin
if (rd_ptr==(FIFO_FULL-1)) rd_ptr <= 3'h0;
else rd_ptr <= rd_ptr + 3'h1;
end
 
//============================================================================
// 7) REFRESH_DATA
//============================================================================
 
// Refresh Data is ready
reg refresh_data_ready_o;
always @(posedge mclk or posedge puc_rst)
if (puc_rst) refresh_data_ready_o <= 1'h0;
else if (~refresh_active_i) refresh_data_ready_o <= 1'h0;
else refresh_data_ready_o <= fifo_pop;
 
// Refresh Data
reg [15:0] refresh_data_o;
always @(posedge mclk or posedge puc_rst)
if (puc_rst) refresh_data_o <= 16'h0000;
else if (fifo_pop) refresh_data_o <= fifo_mem[rd_ptr];
 
 
endmodule // ogfx_backend_lut_fifo
 
`ifdef OGFX_NO_INCLUDE
`else
`include "openGFX430_undefines.v"
`endif
/core/rtl/verilog/ogfx_reg_vram_if.v
0,0 → 1,446
//----------------------------------------------------------------------------
// Copyright (C) 2015 Authors
//
// This source file may be used and distributed without restriction provided
// that this copyright statement is not removed from the file and that any
// derivative work contains the original copyright notice and the associated
// disclaimer.
//
// This source file is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This source is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
// License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this source; if not, write to the Free Software Foundation,
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
//----------------------------------------------------------------------------
//
// *File Name: ogfx_reg_vram_if.v
//
// *Module Description:
// Video-RAM Registers interface.
//
// *Author(s):
// - Olivier Girard, olgirard@gmail.com
//
//----------------------------------------------------------------------------
// $Rev$
// $LastChangedBy$
// $LastChangedDate$
//----------------------------------------------------------------------------
`ifdef OGFX_NO_INCLUDE
`else
`include "openGFX430_defines.v"
`endif
 
module ogfx_reg_vram_if (
 
// OUTPUTs
vid_ram_cfg_o, // VID_RAMx_CFG Register
vid_ram_width_o, // VID_RAMx_WIDTH Register
`ifdef VRAM_BIGGER_4_KW
vid_ram_addr_hi_o, // VID_RAMx_ADDR_HI Register
`endif
vid_ram_addr_lo_o, // VID_RAMx_ADDR_LO Register
vid_ram_data_o, // VID_RAMx_DATA Register
 
vid_ram_we_o, // Video-RAM Write strobe
vid_ram_ce_o, // Video-RAM Chip enable
vid_ram_din_o, // Video-RAM Data input
vid_ram_addr_nxt_o, // Video-RAM Next address
vid_ram_access_o, // Video-RAM Access
 
// INPUTs
mclk, // Main system clock
puc_rst, // Main system reset
 
vid_ram_cfg_wr_i, // VID_RAMx_CFG Write strobe
vid_ram_width_wr_i, // VID_RAMx_WIDTH Write strobe
`ifdef VRAM_BIGGER_4_KW
vid_ram_addr_hi_wr_i, // VID_RAMx_ADDR_HI Write strobe
`endif
vid_ram_addr_lo_wr_i, // VID_RAMx_ADDR_LO Write strobe
vid_ram_data_wr_i, // VID_RAMx_DATA Write strobe
vid_ram_data_rd_i, // VID_RAMx_DATA Read strobe
 
dbg_freeze_i, // Freeze auto-increment on read when CPU stopped
display_width_i, // Display width
gfx_mode_1_bpp_i, // Graphic mode 1 bpp resolution
gfx_mode_2_bpp_i, // Graphic mode 2 bpp resolution
gfx_mode_4_bpp_i, // Graphic mode 4 bpp resolution
gfx_mode_8_bpp_i, // Graphic mode 8 bpp resolution
gfx_mode_16_bpp_i, // Graphic mode 16 bpp resolution
 
per_din_i, // Peripheral data input
vid_ram_base_addr_i, // Video-RAM base address
vid_ram_dout_i // Video-RAM data input
);
 
// OUTPUTs
//=========
output [15:0] vid_ram_cfg_o; // VID_RAMx_CFG Register
output [15:0] vid_ram_width_o; // VID_RAMx_WIDTH Register
`ifdef VRAM_BIGGER_4_KW
output [15:0] vid_ram_addr_hi_o; // VID_RAMx_ADDR_HI Register
`endif
output [15:0] vid_ram_addr_lo_o; // VID_RAMx_ADDR_LO Register
output [15:0] vid_ram_data_o; // VID_RAMx_DATA Register
 
output vid_ram_we_o; // Video-RAM Write strobe
output vid_ram_ce_o; // Video-RAM Chip enable
output [15:0] vid_ram_din_o; // Video-RAM Data input
output [`APIX_MSB:0] vid_ram_addr_nxt_o; // Video-RAM Next address
output vid_ram_access_o; // Video-RAM Access
 
// INPUTs
//=========
input mclk; // Main system clock
input puc_rst; // Main system reset
 
input vid_ram_cfg_wr_i; // VID_RAMx_CFG Write strobe
input vid_ram_width_wr_i; // VID_RAMx_WIDTH Write strobe
`ifdef VRAM_BIGGER_4_KW
input vid_ram_addr_hi_wr_i; // VID_RAMx_ADDR_HI Write strobe
`endif
input vid_ram_addr_lo_wr_i; // VID_RAMx_ADDR_LO Write strobe
input vid_ram_data_wr_i; // VID_RAMx_DATA Write strobe
input vid_ram_data_rd_i; // VID_RAMx_DATA Read strobe
 
input dbg_freeze_i; // Freeze auto-increment on read when CPU stopped
input [`LPIX_MSB:0] display_width_i; // Display width
input gfx_mode_1_bpp_i; // Graphic mode 1 bpp resolution
input gfx_mode_2_bpp_i; // Graphic mode 2 bpp resolution
input gfx_mode_4_bpp_i; // Graphic mode 4 bpp resolution
input gfx_mode_8_bpp_i; // Graphic mode 8 bpp resolution
input gfx_mode_16_bpp_i; // Graphic mode 16 bpp resolution
 
input [15:0] per_din_i; // Peripheral data input
input [`APIX_MSB:0] vid_ram_base_addr_i; // Video-RAM base address
input [15:0] vid_ram_dout_i; // Video-RAM data input
 
 
//=============================================================================
// 1) WIRE AND FUNCTION DECLARATIONS
//=============================================================================
 
// 16 bits one-hot decoder
function [15:0] one_hot16;
input [3:0] binary;
begin
one_hot16 = 16'h0000;
one_hot16[binary] = 1'b1;
end
endfunction
 
 
 
//============================================================================
// 2) REGISTERS
//============================================================================
 
//------------------------------------------------
// VID_RAMx_CFG Register
//------------------------------------------------
reg vid_ram_rmw_mode;
reg vid_ram_msk_mode;
reg vid_ram_win_mode;
reg vid_ram_win_x_swap;
reg vid_ram_win_y_swap;
reg vid_ram_win_cl_swap;
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst)
begin
vid_ram_win_cl_swap <= 1'b0;
vid_ram_win_y_swap <= 1'b0;
vid_ram_win_x_swap <= 1'b0;
vid_ram_rmw_mode <= 1'b0;
vid_ram_msk_mode <= 1'b0;
vid_ram_win_mode <= 1'b0;
end
else if (vid_ram_cfg_wr_i)
begin
vid_ram_win_cl_swap <= per_din_i[0];
vid_ram_win_y_swap <= per_din_i[1];
vid_ram_win_x_swap <= per_din_i[2];
vid_ram_rmw_mode <= per_din_i[4];
vid_ram_msk_mode <= per_din_i[5];
vid_ram_win_mode <= per_din_i[6];
end
 
assign vid_ram_cfg_o = {8'h00, 1'b0, vid_ram_win_mode, vid_ram_msk_mode, vid_ram_rmw_mode ,
1'b0, vid_ram_win_x_swap, vid_ram_win_y_swap, vid_ram_win_cl_swap};
 
//------------------------------------------------
// VID_RAMx_WIDTH Register
//------------------------------------------------
reg [`LPIX_MSB:0] vid_ram_width;
 
// width must be at least 1
wire [`LPIX_MSB:0] vid_ram_width_nxt = (|per_din_i[`LPIX_MSB:0]) ? per_din_i[`LPIX_MSB:0] : {{`LPIX_MSB{1'b0}}, 1'b1};
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) vid_ram_width <= {{`LPIX_MSB{1'b0}}, 1'b1};
else if (vid_ram_width_wr_i) vid_ram_width <= vid_ram_width_nxt;
 
wire [16:0] vid_ram_width_tmp = {{16-`LPIX_MSB{1'b0}}, vid_ram_width};
assign vid_ram_width_o = vid_ram_width_tmp[15:0];
 
 
//------------------------------------------------
// VID_RAMx_ADDR_HI Register
//------------------------------------------------
wire [`APIX_MSB:0] vid_ram_addr;
wire [`APIX_MSB:0] vid_ram_addr_inc;
wire vid_ram_addr_inc_wr;
 
`ifdef VRAM_BIGGER_4_KW
reg [`APIX_HI_MSB:0] vid_ram_addr_hi;
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) vid_ram_addr_hi <= {`APIX_HI_MSB+1{1'b0}};
else if (vid_ram_addr_hi_wr_i) vid_ram_addr_hi <= per_din_i[`APIX_HI_MSB:0];
else if (vid_ram_addr_inc_wr) vid_ram_addr_hi <= vid_ram_addr_inc[`APIX_MSB:16];
 
wire [16:0] vid_ram_addr_hi_tmp = {{16-`APIX_HI_MSB{1'b0}},vid_ram_addr_hi};
assign vid_ram_addr_hi_o = vid_ram_addr_hi_tmp[15:0];
`endif
 
//------------------------------------------------
// VID_RAMx_ADDR_LO Register
//------------------------------------------------
reg [`APIX_LO_MSB:0] vid_ram_addr_lo;
reg vid_ram_addr_lo_wr_dly;
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) vid_ram_addr_lo <= {`APIX_LO_MSB+1{1'b0}};
else if (vid_ram_addr_lo_wr_i) vid_ram_addr_lo <= per_din_i[`APIX_LO_MSB:0];
else if (vid_ram_addr_inc_wr) vid_ram_addr_lo <= vid_ram_addr_inc[`APIX_LO_MSB:0];
 
`ifdef VRAM_BIGGER_4_KW
assign vid_ram_addr = {vid_ram_addr_hi[`APIX_HI_MSB:0], vid_ram_addr_lo};
assign vid_ram_addr_lo_o = vid_ram_addr_lo;
`else
assign vid_ram_addr = {vid_ram_addr_lo[`APIX_LO_MSB:0]};
wire [16:0] vid_ram_addr_lo_tmp = {{16-`APIX_LO_MSB{1'b0}},vid_ram_addr_lo};
assign vid_ram_addr_lo_o = vid_ram_addr_lo_tmp[15:0];
`endif
 
// Compute the next address
ogfx_reg_vram_addr ogfx_reg_vram_addr_inst (
 
// OUTPUTs
.vid_ram_addr_nxt_o ( vid_ram_addr_inc ), // Next Video-RAM address
 
// INPUTs
.mclk ( mclk ), // Main system clock
.puc_rst ( puc_rst ), // Main system reset
.display_width_i ( display_width_i ), // Display width
.gfx_mode_1_bpp_i ( gfx_mode_1_bpp_i ), // Graphic mode 1 bpp resolution
.gfx_mode_2_bpp_i ( gfx_mode_2_bpp_i ), // Graphic mode 2 bpp resolution
.gfx_mode_4_bpp_i ( gfx_mode_4_bpp_i ), // Graphic mode 4 bpp resolution
.gfx_mode_8_bpp_i ( gfx_mode_8_bpp_i ), // Graphic mode 8 bpp resolution
.gfx_mode_16_bpp_i ( gfx_mode_16_bpp_i ), // Graphic mode 16 bpp resolution
.vid_ram_addr_i ( vid_ram_addr ), // Video-RAM address
.vid_ram_addr_init_i ( vid_ram_addr_lo_wr_dly ), // Video-RAM address initialization
.vid_ram_addr_step_i ( vid_ram_addr_inc_wr ), // Video-RAM address step
.vid_ram_width_i ( vid_ram_width ), // Video-RAM width
.vid_ram_msk_mode_i ( vid_ram_msk_mode ), // Video-RAM Mask mode enable
.vid_ram_win_mode_i ( vid_ram_win_mode ), // Video-RAM Windows mode enable
.vid_ram_win_x_swap_i ( vid_ram_win_x_swap ), // Video-RAM X-Swap configuration
.vid_ram_win_y_swap_i ( vid_ram_win_y_swap ), // Video-RAM Y-Swap configuration
.vid_ram_win_cl_swap_i ( vid_ram_win_cl_swap ) // Video-RAM CL-Swap configuration
);
 
 
//------------------------------------------------
// VID_RAMx_DATA Register
//------------------------------------------------
 
// Format input data for masked mode
wire [15:0] per_din_mask_mode = (({16{gfx_mode_1_bpp_i & vid_ram_msk_mode }} & {16{per_din_i[0] }}) |
({16{gfx_mode_2_bpp_i & vid_ram_msk_mode }} & {8{per_din_i[1:0]}}) |
({16{gfx_mode_4_bpp_i & vid_ram_msk_mode }} & {4{per_din_i[3:0]}}) |
({16{gfx_mode_8_bpp_i & vid_ram_msk_mode }} & {2{per_din_i[7:0]}}) |
({16{gfx_mode_16_bpp_i | ~vid_ram_msk_mode }} & per_din_i ) );
 
// Prepare data to be written according to mask mode enable
reg [15:0] vid_ram_data_mask;
wire [15:0] per_din_ram_nxt = per_din_mask_mode & vid_ram_data_mask;
 
// VIDEO-RAM data Register
reg [15:0] vid_ram_data;
wire [15:0] vid_ram_data_mux;
wire vid_ram_dout_rdy;
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) vid_ram_data <= 16'h0000;
else if (vid_ram_data_wr_i) vid_ram_data <= per_din_ram_nxt | (vid_ram_data_mux & ~vid_ram_data_mask);
else if (vid_ram_dout_rdy) vid_ram_data <= vid_ram_dout_i;
 
// Make value available in case of early read
assign vid_ram_data_mux = vid_ram_dout_rdy ? vid_ram_dout_i : vid_ram_data;
 
// Format read-path for mask mode
wire [15:0] vid_ram_data_rd_mask = vid_ram_data_mux & vid_ram_data_mask;
wire vid_ram_data_rd_mask_1_bpp = (|vid_ram_data_rd_mask);
wire [1:0] vid_ram_data_rd_mask_2_bpp = {(|{vid_ram_data_rd_mask[15], vid_ram_data_rd_mask[13], vid_ram_data_rd_mask[11], vid_ram_data_rd_mask[9], vid_ram_data_rd_mask[7], vid_ram_data_rd_mask[5], vid_ram_data_rd_mask[3], vid_ram_data_rd_mask[1]}),
(|{vid_ram_data_rd_mask[14], vid_ram_data_rd_mask[12], vid_ram_data_rd_mask[10], vid_ram_data_rd_mask[8], vid_ram_data_rd_mask[6], vid_ram_data_rd_mask[4], vid_ram_data_rd_mask[2], vid_ram_data_rd_mask[0]})};
wire [3:0] vid_ram_data_rd_mask_4_bpp = {(|{vid_ram_data_rd_mask[15], vid_ram_data_rd_mask[11], vid_ram_data_rd_mask[7] , vid_ram_data_rd_mask[3]}),
(|{vid_ram_data_rd_mask[14], vid_ram_data_rd_mask[10], vid_ram_data_rd_mask[6] , vid_ram_data_rd_mask[2]}),
(|{vid_ram_data_rd_mask[13], vid_ram_data_rd_mask[9] , vid_ram_data_rd_mask[5] , vid_ram_data_rd_mask[1]}),
(|{vid_ram_data_rd_mask[12], vid_ram_data_rd_mask[8] , vid_ram_data_rd_mask[4] , vid_ram_data_rd_mask[0]})};
wire [7:0] vid_ram_data_rd_mask_8_bpp = {(|{vid_ram_data_rd_mask[15], vid_ram_data_rd_mask[7]}),
(|{vid_ram_data_rd_mask[14], vid_ram_data_rd_mask[6]}),
(|{vid_ram_data_rd_mask[13], vid_ram_data_rd_mask[5]}),
(|{vid_ram_data_rd_mask[12], vid_ram_data_rd_mask[4]}),
(|{vid_ram_data_rd_mask[11], vid_ram_data_rd_mask[3]}),
(|{vid_ram_data_rd_mask[10], vid_ram_data_rd_mask[2]}),
(|{vid_ram_data_rd_mask[9] , vid_ram_data_rd_mask[1]}),
(|{vid_ram_data_rd_mask[8] , vid_ram_data_rd_mask[0]})};
wire [15:0] vid_ram_data_rd_mask_16_bpp = vid_ram_data_rd_mask;
 
assign vid_ram_data_o = ({16{gfx_mode_1_bpp_i & vid_ram_msk_mode }} & {{15{1'b0}},vid_ram_data_rd_mask_1_bpp}) |
({16{gfx_mode_2_bpp_i & vid_ram_msk_mode }} & {{14{1'b0}},vid_ram_data_rd_mask_2_bpp}) |
({16{gfx_mode_4_bpp_i & vid_ram_msk_mode }} & {{12{1'b0}},vid_ram_data_rd_mask_4_bpp}) |
({16{gfx_mode_8_bpp_i & vid_ram_msk_mode }} & { {8{1'b0}},vid_ram_data_rd_mask_8_bpp}) |
({16{gfx_mode_16_bpp_i | ~vid_ram_msk_mode }} & vid_ram_data_rd_mask_16_bpp) ;
 
 
//============================================================================
// 3) VIDEO MEMORY INTERFACE
//============================================================================
//
// Trigger a VIDEO-RAM write access after:
// - a VID_RAMx_DATA register write access
//
// Trigger a VIDEO-RAM read access immediately after:
// - a VID_RAMx_ADDR_LO register write access
// - a VID_RAMx_DATA register read access
// - a VID_RAMx_DATA register write access in MSK mode (for resolutions lower than 16bpp)
//
 
//--------------------------------------------------
// VID_RAM0: Delay software read and write strobes
//--------------------------------------------------
 
// Strobe writing to VID_RAMx_ADDR_LO register
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) vid_ram_addr_lo_wr_dly <= 1'b0;
else vid_ram_addr_lo_wr_dly <= vid_ram_addr_lo_wr_i;
 
// Strobe reading from VID_RAMx_DATA register
reg vid_ram_data_rd_dly;
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) vid_ram_data_rd_dly <= 1'b0;
else vid_ram_data_rd_dly <= vid_ram_data_rd_i;
 
// Strobe writing to VID_RAMx_DATA register
reg vid_ram_data_wr_dly;
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) vid_ram_data_wr_dly <= 1'b0;
else vid_ram_data_wr_dly <= vid_ram_data_wr_i;
 
// Trigger read access after a write in MSK mode
wire vid_ram_data_rd_msk = ((vid_ram_data_wr_dly | vid_ram_data_rd_dly | vid_ram_addr_lo_wr_i) & vid_ram_msk_mode & ~gfx_mode_16_bpp_i);
 
 
//------------------------------------------------
// Compute VIDEO-RAM Strobes & Data
//------------------------------------------------
 
// Write access strobe
// - one cycle after a VID_RAM_DATA register write access
assign vid_ram_we_o = vid_ram_data_wr_dly;
 
// Chip enable.
// Note: we perform a data read access:
// - one cycle after a VID_RAM_DATA register read access (so that the address has been incremented)
// - one cycle after a VID_RAM_ADDR_LO register write
wire vid_ram_ce_early = (vid_ram_addr_lo_wr_i | vid_ram_data_rd_dly | vid_ram_data_rd_msk | // Read access
vid_ram_data_wr_i); // Write access
 
reg [1:0] vid_ram_ce;
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) vid_ram_ce <= 2'b00;
else vid_ram_ce <= {vid_ram_ce[0] & ~vid_ram_data_wr_dly, vid_ram_ce_early};
 
assign vid_ram_ce_o = vid_ram_ce[0];
 
// Data to be written
assign vid_ram_din_o = {16{vid_ram_ce[0]}} & vid_ram_data;
 
// Update the VRAM_DATA register one cycle after each memory access
assign vid_ram_dout_rdy = vid_ram_ce[1];
 
 
//------------------------------------------------
// Compute VIDEO-RAM Address
//------------------------------------------------
 
// Mux ram address for early read access when ADDR_LO is updated
`ifdef VRAM_BIGGER_4_KW
wire [`APIX_MSB:0] vid_ram_addr_mux = vid_ram_addr_lo_wr_i ? {vid_ram_addr[`APIX_MSB:16], per_din_i} :
vid_ram_data_rd_msk ? vid_ram_addr_inc : vid_ram_addr;
`else
wire [`APIX_MSB:0] vid_ram_addr_mux = vid_ram_addr_lo_wr_i ? {per_din_i[`APIX_LO_MSB:0]} :
vid_ram_data_rd_msk ? vid_ram_addr_inc : vid_ram_addr;
`endif
 
// Add frame pointer offset
wire [`APIX_MSB:0] vid_ram_addr_offset = vid_ram_base_addr_i + vid_ram_addr_mux;
 
// Detect memory accesses for ADDR update
wire vid_ram_access_o = vid_ram_data_wr_i | vid_ram_data_rd_dly | vid_ram_addr_lo_wr_i | vid_ram_data_rd_msk;
 
// Mux Address between the two interfaces
wire [`APIX_MSB:0] vid_ram_addr_nxt_o = {`APIX_MSB+1{vid_ram_access_o}} & vid_ram_addr_offset;
 
// Increment the address when accessing the VID_RAMx_DATA register:
// - one clock cycle after a write access
// - with the read access (if not in read-modify-write mode)
assign vid_ram_addr_inc_wr = vid_ram_addr_lo_wr_dly | vid_ram_data_wr_dly | (vid_ram_data_rd_i & ~dbg_freeze_i & ~vid_ram_rmw_mode);
 
// Compute mask for the address LSBs depending on BPP resolution
wire [3:0] gfx_mode_addr_msk = ( {4{gfx_mode_1_bpp_i}} | // Take 4 address LSBs in 1bpp mode
{1'b0, {3{gfx_mode_2_bpp_i}}} | // Take 3 address LSBs in 2bpp mode
{2'b00, {2{gfx_mode_4_bpp_i}}} | // Take 2 address LSBs in 4bpp mode
{3'b000, gfx_mode_8_bpp_i}); // Take 1 address LSB in 8bpp mode
// Take no address LSB in 16bpp mode
// Generate Data-Mask for the mask mode (Bank 0)
wire [15:0] vid_ram_data_mask_shift = one_hot16(vid_ram_addr_offset[3:0] & gfx_mode_addr_msk);
wire [15:0] vid_ram_data_mask_nxt = ({16{gfx_mode_1_bpp_i }} & vid_ram_data_mask_shift ) |
({16{gfx_mode_2_bpp_i }} & {{2{vid_ram_data_mask_shift[7]}},
{2{vid_ram_data_mask_shift[6]}},
{2{vid_ram_data_mask_shift[5]}},
{2{vid_ram_data_mask_shift[4]}},
{2{vid_ram_data_mask_shift[3]}},
{2{vid_ram_data_mask_shift[2]}},
{2{vid_ram_data_mask_shift[1]}},
{2{vid_ram_data_mask_shift[0]}}}) |
({16{gfx_mode_4_bpp_i }} & {{4{vid_ram_data_mask_shift[3]}},
{4{vid_ram_data_mask_shift[2]}},
{4{vid_ram_data_mask_shift[1]}},
{4{vid_ram_data_mask_shift[0]}}}) |
({16{gfx_mode_8_bpp_i }} & {{8{vid_ram_data_mask_shift[1]}},
{8{vid_ram_data_mask_shift[0]}}}) |
({16{gfx_mode_16_bpp_i}} & {16{1'b1}} ) ;
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) vid_ram_data_mask <= 16'hffff;
else if (vid_ram_data_rd_msk) vid_ram_data_mask <= vid_ram_data_mask_nxt;
else if (vid_ram_access_o) vid_ram_data_mask <= 16'hffff;
 
 
endmodule // ogfx_reg_vram_if
 
`ifdef OGFX_NO_INCLUDE
`else
`include "openGFX430_undefines.v"
`endif
/core/rtl/verilog/ogfx_reg_fifo.v
0,0 → 1,184
//----------------------------------------------------------------------------
// Copyright (C) 2015 Authors
//
// This source file may be used and distributed without restriction provided
// that this copyright statement is not removed from the file and that any
// derivative work contains the original copyright notice and the associated
// disclaimer.
//
// This source file is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This source is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
// License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this source; if not, write to the Free Software Foundation,
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
//----------------------------------------------------------------------------
//
// *File Name: ogfx_backend_lut_fifo.v
//
// *Module Description:
// Simple FIFO module
//
// *Author(s):
// - Olivier Girard, olgirard@gmail.com
//
//----------------------------------------------------------------------------
// $Rev$
// $LastChangedBy$
// $LastChangedDate$
//----------------------------------------------------------------------------
`ifdef OGFX_NO_INCLUDE
`else
`include "openGFX430_defines.v"
`endif
 
module ogfx_reg_fifo (
 
// OUTPUTs
fifo_cnt_o, // Fifo counter
fifo_data_o, // Read data output
fifo_done_evt_o, // Fifo has been emptied
fifo_empty_o, // Fifo is currentely empty
fifo_full_o, // Fifo is currentely full
fifo_ovfl_evt_o, // Fifo overflow event
 
// INPUTs
mclk, // Main system clock
puc_rst, // Main system reset
 
fifo_data_i, // Read data input
fifo_enable_i, // Enable fifo (flushed when disabled)
fifo_pop_i, // Pop data from the fifo
fifo_push_i // Push new data to the fifo
);
 
// OUTPUTs
//=========
output [3:0] fifo_cnt_o; // Fifo counter
output [15:0] fifo_data_o; // Read data output
output fifo_done_evt_o; // Fifo has been emptied
output fifo_empty_o; // Fifo is currentely empty
output fifo_full_o; // Fifo is currentely full
output fifo_ovfl_evt_o; // Fifo overflow event
 
// INPUTs
//=========
input mclk; // Main system clock
input puc_rst; // Main system reset
 
input [15:0] fifo_data_i; // Read data input
input fifo_enable_i; // Enable fifo (flushed when disabled)
input fifo_pop_i; // Pop data from the fifo
input fifo_push_i; // Push new data to the fifo
 
 
//=============================================================================
// 1) WIRE, REGISTERS AND PARAMETER DECLARATION
//=============================================================================
 
// Some parameter(s)
parameter FIFO_EMPTY = 4'h0,
FIFO_FULL = 4'hf;
 
// Others
reg [3:0] fifo_cnt_o;
wire [3:0] fifo_cnt_nxt;
 
 
//============================================================================
// 5) FIFO COUNTER
//============================================================================
 
// Control signals
wire fifo_full_o = (fifo_cnt_o == FIFO_FULL);
wire fifo_empty_o = (fifo_cnt_o == FIFO_EMPTY);
wire fifo_push_int = fifo_push_i & !fifo_full_o;
wire fifo_pop_int = fifo_pop_i & !fifo_empty_o;
 
// Events
assign fifo_done_evt_o = ~fifo_empty_o & (fifo_cnt_nxt == FIFO_EMPTY);
assign fifo_ovfl_evt_o = fifo_push_i & fifo_full_o;
 
 
// Fifo counter
assign fifo_cnt_nxt = ~fifo_enable_i ? FIFO_EMPTY : // Initialize
(fifo_push_int & fifo_pop_int) ? fifo_cnt_o : // Keep value (pop & push at the same time)
fifo_push_int ? fifo_cnt_o + 3'h1 : // Push
fifo_pop_int ? fifo_cnt_o - 3'h1 : // Pop
fifo_cnt_o; // Hold
 
always @(posedge mclk or posedge puc_rst)
if (puc_rst) fifo_cnt_o <= FIFO_EMPTY;
else fifo_cnt_o <= fifo_cnt_nxt;
 
 
//============================================================================
// 6) FIFO MEMORY & RD/WR POINTERS
//============================================================================
 
// Write pointer
reg [3:0] wr_ptr;
always @(posedge mclk or posedge puc_rst)
if (puc_rst) wr_ptr <= 4'h0;
else if (~fifo_enable_i) wr_ptr <= 4'h0;
else if (fifo_push_int)
begin
if (wr_ptr==(FIFO_FULL-1)) wr_ptr <= 4'h0;
else wr_ptr <= wr_ptr + 4'h1;
end
 
// Memory
reg [15:0] fifo_mem [0:15];
always @(posedge mclk or posedge puc_rst)
if (puc_rst)
begin
fifo_mem[0] <= 16'h0000;
fifo_mem[1] <= 16'h0000;
fifo_mem[2] <= 16'h0000;
fifo_mem[3] <= 16'h0000;
fifo_mem[4] <= 16'h0000;
fifo_mem[5] <= 16'h0000;
fifo_mem[6] <= 16'h0000;
fifo_mem[7] <= 16'h0000;
fifo_mem[8] <= 16'h0000;
fifo_mem[9] <= 16'h0000;
fifo_mem[10] <= 16'h0000;
fifo_mem[11] <= 16'h0000;
fifo_mem[12] <= 16'h0000;
fifo_mem[13] <= 16'h0000;
fifo_mem[14] <= 16'h0000;
fifo_mem[15] <= 16'h0000;
end
else if (fifo_push_int)
begin
fifo_mem[wr_ptr] <= fifo_data_i;
end
 
// Read pointer
reg [3:0] rd_ptr;
always @(posedge mclk or posedge puc_rst)
if (puc_rst) rd_ptr <= 4'h0;
else if (~fifo_enable_i) rd_ptr <= 4'h0;
else if (fifo_pop_int)
begin
if (rd_ptr==(FIFO_FULL-1)) rd_ptr <= 4'h0;
else rd_ptr <= rd_ptr + 4'h1;
end
 
assign fifo_data_o = fifo_mem[rd_ptr];
 
 
endmodule // ogfx_reg_fifo
 
`ifdef OGFX_NO_INCLUDE
`else
`include "openGFX430_undefines.v"
`endif
/core/rtl/verilog/ogfx_ram_arbiter.v
0,0 → 1,264
//----------------------------------------------------------------------------
// Copyright (C) 2015 Authors
//
// This source file may be used and distributed without restriction provided
// that this copyright statement is not removed from the file and that any
// derivative work contains the original copyright notice and the associated
// disclaimer.
//
// This source file is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This source is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
// License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this source; if not, write to the Free Software Foundation,
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
//----------------------------------------------------------------------------
//
// *File Name: ogfx_ram_arbiter.v
//
// *Module Description:
// RAM arbiter for LUT and VIDEO memories
// LUT-RAM arbitration:
//
// - Software interface: fixed highest priority
// - Refresh interface: fixed lowest priority
//
// Video-RAM arbitration:
//
// - Software interface: fixed highest priority
// - Refresh interface: round-robin with GPIO if
// - GPU interface: round-robin with Refresh if
//
// *Author(s):
// - Olivier Girard, olgirard@gmail.com
//
//----------------------------------------------------------------------------
// $Rev$
// $LastChangedBy$
// $LastChangedDate$
//----------------------------------------------------------------------------
`ifdef OGFX_NO_INCLUDE
`else
`include "openGFX430_defines.v"
`endif
 
module ogfx_ram_arbiter (
 
mclk, // Main system clock
puc_rst, // Main system reset
 
//------------------------------------------------------------
 
// SW interface, fixed highest priority
lut_ram_sw_addr_i, // LUT-RAM Software address
lut_ram_sw_din_i, // LUT-RAM Software data
lut_ram_sw_wen_i, // LUT-RAM Software write strobe (active low)
lut_ram_sw_cen_i, // LUT-RAM Software chip enable (active low)
lut_ram_sw_dout_o, // LUT-RAM Software data input
 
// Refresh-backend, fixed lowest priority
lut_ram_refr_addr_i, // LUT-RAM Refresh address
lut_ram_refr_din_i, // LUT-RAM Refresh data
lut_ram_refr_wen_i, // LUT-RAM Refresh write strobe (active low)
lut_ram_refr_cen_i, // LUT-RAM Refresh enable (active low)
lut_ram_refr_dout_o, // LUT-RAM Refresh data output
lut_ram_refr_dout_rdy_nxt_o, // LUT-RAM Refresh data output ready during next cycle
 
// LUT Memory interface
lut_ram_addr_o, // LUT-RAM address
lut_ram_din_o, // LUT-RAM data
lut_ram_wen_o, // LUT-RAM write strobe (active low)
lut_ram_cen_o, // LUT-RAM chip enable (active low)
lut_ram_dout_i, // LUT-RAM data input
 
//------------------------------------------------------------
 
// SW interface, fixed highest priority
vid_ram_sw_addr_i, // Video-RAM Software address
vid_ram_sw_din_i, // Video-RAM Software data
vid_ram_sw_wen_i, // Video-RAM Software write strobe (active low)
vid_ram_sw_cen_i, // Video-RAM Software chip enable (active low)
vid_ram_sw_dout_o, // Video-RAM Software data input
 
// GPU interface (round-robin with refresh-backend)
vid_ram_gpu_addr_i, // Video-RAM GPU address
vid_ram_gpu_din_i, // Video-RAM GPU data
vid_ram_gpu_wen_i, // Video-RAM GPU write strobe (active low)
vid_ram_gpu_cen_i, // Video-RAM GPU chip enable (active low)
vid_ram_gpu_dout_o, // Video-RAM GPU data input
vid_ram_gpu_dout_rdy_nxt_o, // Video-RAM GPU data output ready during next cycle
 
// Refresh-backend (round-robin with GPU interface)
vid_ram_refr_addr_i, // Video-RAM Refresh address
vid_ram_refr_din_i, // Video-RAM Refresh data
vid_ram_refr_wen_i, // Video-RAM Refresh write strobe (active low)
vid_ram_refr_cen_i, // Video-RAM Refresh enable (active low)
vid_ram_refr_dout_o, // Video-RAM Refresh data output
vid_ram_refr_dout_rdy_nxt_o, // Video-RAM Refresh data output ready during next cycle
 
// Video Memory interface
vid_ram_addr_o, // Video-RAM address
vid_ram_din_o, // Video-RAM data
vid_ram_wen_o, // Video-RAM write strobe (active low)
vid_ram_cen_o, // Video-RAM chip enable (active low)
vid_ram_dout_i // Video-RAM data input
 
//------------------------------------------------------------
);
 
// CLOCK/RESET
//=============
input mclk; // Main system clock
input puc_rst; // Main system reset
 
// LUT MEMORY
//=============
 
// SW interface, fixed highest priority
input [`LRAM_MSB:0] lut_ram_sw_addr_i; // LUT-RAM Software address
input [15:0] lut_ram_sw_din_i; // LUT-RAM Software data
input lut_ram_sw_wen_i; // LUT-RAM Software write strobe (active low)
input lut_ram_sw_cen_i; // LUT-RAM Software chip enable (active low)
output [15:0] lut_ram_sw_dout_o; // LUT-RAM Software data input
 
// Refresh-backend, fixed lowest priority
input [`LRAM_MSB:0] lut_ram_refr_addr_i; // LUT-RAM Refresh address
input [15:0] lut_ram_refr_din_i; // LUT-RAM Refresh data
input lut_ram_refr_wen_i; // LUT-RAM Refresh write strobe (active low)
input lut_ram_refr_cen_i; // LUT-RAM Refresh enable (active low)
output [15:0] lut_ram_refr_dout_o; // LUT-RAM Refresh data output
output lut_ram_refr_dout_rdy_nxt_o; // LUT-RAM Refresh data output ready during next cycle
 
// LUT Memory interface
output [`LRAM_MSB:0] lut_ram_addr_o; // LUT-RAM address
output [15:0] lut_ram_din_o; // LUT-RAM data
output lut_ram_wen_o; // LUT-RAM write strobe (active low)
output lut_ram_cen_o; // LUT-RAM chip enable (active low)
input [15:0] lut_ram_dout_i; // LUT-RAM data input
 
// VIDEO MEMORY
//==============
 
// SW interface, fixed highest priority
input [`VRAM_MSB:0] vid_ram_sw_addr_i; // Video-RAM Software address
input [15:0] vid_ram_sw_din_i; // Video-RAM Software data
input vid_ram_sw_wen_i; // Video-RAM Software write strobe (active low)
input vid_ram_sw_cen_i; // Video-RAM Software chip enable (active low)
output [15:0] vid_ram_sw_dout_o; // Video-RAM Software data input
 
// GPU interface (round-robin with refresh-backend)
input [`VRAM_MSB:0] vid_ram_gpu_addr_i; // Video-RAM GPU address
input [15:0] vid_ram_gpu_din_i; // Video-RAM GPU data
input vid_ram_gpu_wen_i; // Video-RAM GPU write strobe (active low)
input vid_ram_gpu_cen_i; // Video-RAM GPU chip enable (active low)
output [15:0] vid_ram_gpu_dout_o; // Video-RAM GPU data input
output vid_ram_gpu_dout_rdy_nxt_o; // Video-RAM GPU data output ready during next cycle
 
// Refresh-backend (round-robin with GPU interface)
input [`VRAM_MSB:0] vid_ram_refr_addr_i; // Video-RAM Refresh address
input [15:0] vid_ram_refr_din_i; // Video-RAM Refresh data
input vid_ram_refr_wen_i; // Video-RAM Refresh write strobe (active low)
input vid_ram_refr_cen_i; // Video-RAM Refresh enable (active low)
output [15:0] vid_ram_refr_dout_o; // Video-RAM Refresh data output
output vid_ram_refr_dout_rdy_nxt_o; // Video-RAM Refresh data output ready during next cycle
 
// Video Memory interface
output [`VRAM_MSB:0] vid_ram_addr_o; // Video-RAM address
output [15:0] vid_ram_din_o; // Video-RAM data
output vid_ram_wen_o; // Video-RAM write strobe (active low)
output vid_ram_cen_o; // Video-RAM chip enable (active low)
input [15:0] vid_ram_dout_i; // Video-RAM data input
 
 
//=============================================================================
// 1) WIRE, REGISTERS AND PARAMETER DECLARATION
//=============================================================================
 
reg gpu_is_last_owner;
 
 
//=============================================================================
// 2) LUT MEMORY ARBITER
//=============================================================================
 
// Arbitration signals
wire sw_lram_access_granted = ~lut_ram_sw_cen_i;
wire refr_lram_access_granted = ~sw_lram_access_granted & ~lut_ram_refr_cen_i;
 
// LUT RAM signal muxing
assign lut_ram_sw_dout_o = lut_ram_dout_i;
 
assign lut_ram_refr_dout_o = lut_ram_dout_i;
assign lut_ram_refr_dout_rdy_nxt_o = refr_lram_access_granted;
 
assign lut_ram_addr_o = ({`LRAM_AWIDTH{ sw_lram_access_granted }} & lut_ram_sw_addr_i ) |
({`LRAM_AWIDTH{ refr_lram_access_granted}} & lut_ram_refr_addr_i) ;
 
assign lut_ram_din_o = ({ 16{ sw_lram_access_granted }} & lut_ram_sw_din_i ) |
({ 16{ refr_lram_access_granted}} & lut_ram_refr_din_i ) ;
 
assign lut_ram_wen_o = ( ~sw_lram_access_granted | lut_ram_sw_wen_i ) &
( ~refr_lram_access_granted | lut_ram_refr_wen_i ) ;
 
assign lut_ram_cen_o = lut_ram_sw_cen_i & lut_ram_refr_cen_i;
 
 
//=============================================================================
// 3) VIDEO MEMORY ARBITER
//=============================================================================
 
 
// Arbitration signals
wire sw_vram_access_granted = ~vid_ram_sw_cen_i;
wire gpu_vram_access_granted = ~sw_vram_access_granted & // No SW access
((~vid_ram_gpu_cen_i & vid_ram_refr_cen_i) | // GPU requests alone
(~vid_ram_gpu_cen_i & ~vid_ram_refr_cen_i & ~gpu_is_last_owner)) ; // GPU & REFR both requests (arbitration required)
 
wire refr_vram_access_granted = ~sw_vram_access_granted & // No SW access
(( vid_ram_gpu_cen_i & ~vid_ram_refr_cen_i) | // GPU requests alone
(~vid_ram_gpu_cen_i & ~vid_ram_refr_cen_i & gpu_is_last_owner)) ; // GPU & REFR both requests (arbitration required)
 
// Detect who was the last to own the RAM between the GPU and Refresh interface
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) gpu_is_last_owner <= 1'b0;
else if (gpu_vram_access_granted ) gpu_is_last_owner <= 1'b1;
else if (refr_vram_access_granted) gpu_is_last_owner <= 1'b0;
 
// Video RAM signal muxing
assign vid_ram_sw_dout_o = vid_ram_dout_i;
 
assign vid_ram_gpu_dout_o = vid_ram_dout_i;
assign vid_ram_gpu_dout_rdy_nxt_o = gpu_vram_access_granted;
 
assign vid_ram_refr_dout_o = vid_ram_dout_i;
assign vid_ram_refr_dout_rdy_nxt_o = refr_vram_access_granted;
 
assign vid_ram_addr_o = ({`VRAM_AWIDTH{ sw_vram_access_granted }} & vid_ram_sw_addr_i ) |
({`VRAM_AWIDTH{ gpu_vram_access_granted }} & vid_ram_gpu_addr_i ) |
({`VRAM_AWIDTH{ refr_vram_access_granted}} & vid_ram_refr_addr_i) ;
 
assign vid_ram_din_o = ({ 16{ sw_vram_access_granted }} & vid_ram_sw_din_i ) |
({ 16{ gpu_vram_access_granted }} & vid_ram_gpu_din_i ) |
({ 16{ refr_vram_access_granted}} & vid_ram_refr_din_i ) ;
 
assign vid_ram_wen_o = ( ~sw_vram_access_granted | vid_ram_sw_wen_i ) &
( ~gpu_vram_access_granted | vid_ram_gpu_wen_i ) &
( ~refr_vram_access_granted | vid_ram_refr_wen_i ) ;
 
assign vid_ram_cen_o = vid_ram_sw_cen_i & vid_ram_gpu_cen_i & vid_ram_refr_cen_i;
 
 
endmodule // ogfx_ram_arbiter
 
`ifdef OGFX_NO_INCLUDE
`else
`include "openGFX430_undefines.v"
`endif
/core/rtl/verilog/ogfx_backend.v
0,0 → 1,217
//----------------------------------------------------------------------------
// Copyright (C) 2015 Authors
//
// This source file may be used and distributed without restriction provided
// that this copyright statement is not removed from the file and that any
// derivative work contains the original copyright notice and the associated
// disclaimer.
//
// This source file is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This source is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
// License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this source; if not, write to the Free Software Foundation,
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
//----------------------------------------------------------------------------
//
// *File Name: ogfx_backend.v
//
// *Module Description:
// Backend module of the graphic controller.
// The purpose of this block is to:
//
// - fetch the data from the specified frame buffer
// - convert data depending on selected video mode
//
// *Author(s):
// - Olivier Girard, olgirard@gmail.com
//
//----------------------------------------------------------------------------
// $Rev$
// $LastChangedBy$
// $LastChangedDate$
//----------------------------------------------------------------------------
`ifdef OGFX_NO_INCLUDE
`else
`include "openGFX430_defines.v"
`endif
 
module ogfx_backend (
 
// OUTPUTs
refresh_data_o, // Display refresh data
refresh_data_ready_o, // Display refresh new data is ready
 
vid_ram_addr_o, // Video-RAM refresh address
vid_ram_cen_o, // Video-RAM refresh enable (active low)
 
`ifdef WITH_PROGRAMMABLE_LUT
lut_ram_addr_o, // LUT-RAM refresh address
lut_ram_cen_o, // LUT-RAM refresh enable (active low)
`endif
 
// INPUTs
mclk, // Main system clock
puc_rst, // Main system reset
 
display_width_i, // Display width
display_height_i, // Display height
display_size_i, // Display size (number of pixels)
display_y_swap_i, // Display configuration: swap Y axis (horizontal symmetry)
display_x_swap_i, // Display configuration: swap X axis (vertical symmetry)
display_cl_swap_i, // Display configuration: swap column/lines
 
gfx_mode_i, // Video mode (1xx:16bpp / 011:8bpp / 010:4bpp / 001:2bpp / 000:1bpp)
 
`ifdef WITH_PROGRAMMABLE_LUT
lut_ram_dout_i, // LUT-RAM data output
lut_ram_dout_rdy_nxt_i, // LUT-RAM data output ready during next cycle
`endif
 
vid_ram_dout_i, // Video-RAM data output
vid_ram_dout_rdy_nxt_i, // Video-RAM data output ready during next cycle
 
refresh_active_i, // Display refresh on going
refresh_data_request_i, // Display refresh new data request
refresh_frame_base_addr_i, // Refresh frame base address
refresh_lut_select_i // Refresh LUT bank selection
);
 
// OUTPUTs
//=========
output [15:0] refresh_data_o; // Display refresh data
output refresh_data_ready_o; // Display refresh new data is ready
 
output [`VRAM_MSB:0] vid_ram_addr_o; // Video-RAM refresh address
output vid_ram_cen_o; // Video-RAM refresh enable (active low)
 
`ifdef WITH_PROGRAMMABLE_LUT
output [`LRAM_MSB:0] lut_ram_addr_o; // LUT-RAM refresh address
output lut_ram_cen_o; // LUT-RAM refresh enable (active low)
`endif
 
// INPUTs
//=========
input mclk; // Main system clock
input puc_rst; // Main system reset
 
input [`LPIX_MSB:0] display_width_i; // Display width
input [`LPIX_MSB:0] display_height_i; // Display height
input [`SPIX_MSB:0] display_size_i; // Display size (number of pixels)
input display_y_swap_i; // Display configuration: swap Y axis (horizontal symmetry)
input display_x_swap_i; // Display configuration: swap X axis (vertical symmetry)
input display_cl_swap_i; // Display configuration: swap column/lines
 
input [2:0] gfx_mode_i; // Video mode (1xx:16bpp / 011:8bpp / 010:4bpp / 001:2bpp / 000:1bpp)
 
`ifdef WITH_PROGRAMMABLE_LUT
input [15:0] lut_ram_dout_i; // LUT-RAM data output
input lut_ram_dout_rdy_nxt_i; // LUT-RAM data output ready during next cycle
`endif
 
input [15:0] vid_ram_dout_i; // Video-RAM data output
input vid_ram_dout_rdy_nxt_i; // Video-RAM data output ready during next cycle
 
input refresh_active_i; // Display refresh on going
input refresh_data_request_i; // Display refresh new data request
input [`APIX_MSB:0] refresh_frame_base_addr_i; // Refresh frame base address
input [1:0] refresh_lut_select_i; // Refresh LUT bank selection
 
 
//=============================================================================
// 1) WIRE, REGISTERS AND PARAMETER DECLARATION
//=============================================================================
 
// Wires
wire [15:0] frame_data;
wire frame_data_ready;
wire frame_data_request;
 
 
//============================================================================
// 2) FRAME MEMORY ACCESS
//============================================================================
 
ogfx_backend_frame_fifo ogfx_backend_frame_fifo_inst (
 
// OUTPUTs
.frame_data_o ( frame_data ), // Frame data
.frame_data_ready_o ( frame_data_ready ), // Frame data ready
 
.vid_ram_addr_o ( vid_ram_addr_o ), // Video-RAM address
.vid_ram_cen_o ( vid_ram_cen_o ), // Video-RAM enable (active low)
 
// INPUTs
.mclk ( mclk ), // Main system clock
.puc_rst ( puc_rst ), // Main system reset
 
.display_width_i ( display_width_i ), // Display width
.display_height_i ( display_height_i ), // Display height
.display_size_i ( display_size_i ), // Display size (number of pixels)
.display_y_swap_i ( display_y_swap_i ), // Display configuration: swap Y axis (horizontal symmetry)
.display_x_swap_i ( display_x_swap_i ), // Display configuration: swap X axis (vertical symmetry)
.display_cl_swap_i ( display_cl_swap_i ), // Display configuration: swap column/lines
 
.frame_data_request_i ( frame_data_request ), // Request for next frame data
 
.gfx_mode_i ( gfx_mode_i ), // Video mode (1xx:16bpp / 011:8bpp / 010:4bpp / 001:2bpp / 000:1bpp)
 
.vid_ram_dout_i ( vid_ram_dout_i ), // Video-RAM data output
.vid_ram_dout_rdy_nxt_i ( vid_ram_dout_rdy_nxt_i ), // Video-RAM data output ready during next cycle
 
.refresh_active_i ( refresh_active_i ), // Display refresh on going
.refresh_frame_base_addr_i ( refresh_frame_base_addr_i ) // Refresh frame base address
);
 
 
//============================================================================
// 3) LUT MEMORY ACCESS
//============================================================================
 
ogfx_backend_lut_fifo ogfx_backend_lut_fifo_inst (
 
// OUTPUTs
.frame_data_request_o ( frame_data_request ), // Request for next frame data
 
.refresh_data_o ( refresh_data_o ), // Display Refresh data
.refresh_data_ready_o ( refresh_data_ready_o ), // Display Refresh data ready
 
`ifdef WITH_PROGRAMMABLE_LUT
.lut_ram_addr_o ( lut_ram_addr_o ), // LUT-RAM address
.lut_ram_cen_o ( lut_ram_cen_o ), // LUT-RAM enable (active low)
`endif
 
// INPUTs
.mclk ( mclk ), // Main system clock
.puc_rst ( puc_rst ), // Main system reset
 
.frame_data_i ( frame_data ), // Frame data
.frame_data_ready_i ( frame_data_ready ), // Frame data ready
 
.gfx_mode_i ( gfx_mode_i ), // Video mode (1xx:16bpp / 011:8bpp / 010:4bpp / 001:2bpp / 000:1bpp)
 
`ifdef WITH_PROGRAMMABLE_LUT
.lut_ram_dout_i ( lut_ram_dout_i ), // LUT-RAM data output
.lut_ram_dout_rdy_nxt_i ( lut_ram_dout_rdy_nxt_i ), // LUT-RAM data output ready during next cycle
`endif
 
.refresh_active_i ( refresh_active_i ), // Display refresh on going
.refresh_data_request_i ( refresh_data_request_i ), // Request for next refresh data
.refresh_lut_select_i ( refresh_lut_select_i ) // Refresh LUT bank selection
);
 
 
endmodule // ogfx_backend
 
`ifdef OGFX_NO_INCLUDE
`else
`include "openGFX430_undefines.v"
`endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.