OpenFPGA/openfpga_flow/benchmarks/iwls2005/vga_lcd/rtl/vga_colproc.v

511 lines
13 KiB
Verilog

/////////////////////////////////////////////////////////////////////
//// ////
//// WISHBONE rev.B2 compliant VGA/LCD Core ////
//// Enhanced Color Processor ////
//// ////
//// Author: Richard Herveille ////
//// richard@asics.ws ////
//// www.asics.ws ////
//// ////
//// Downloaded from: http://www.opencores.org/projects/vga_lcd ////
//// ////
/////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001, 2002 Richard Herveille ////
//// richard@asics.ws ////
//// ////
//// 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
//// 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. ////
//// ////
/////////////////////////////////////////////////////////////////////
// CVS Log
//
// $Id: vga_colproc.v,v 1.8 2003/05/07 09:48:54 rherveille Exp $
//
// $Date: 2003/05/07 09:48:54 $
// $Revision: 1.8 $
// $Author: rherveille $
// $Locker: $
// $State: Exp $
//
// Change History:
// $Log: vga_colproc.v,v $
// Revision 1.8 2003/05/07 09:48:54 rherveille
// Fixed some Wishbone RevB.3 related bugs.
// Changed layout of the core. Blocks are located more logically now.
// Started work on a dual clocked/double edge 12bit output. Commonly used by external devices like DVI transmitters.
//
// Revision 1.7 2002/03/04 11:01:59 rherveille
// Added 64x64pixels 4bpp hardware cursor support.
//
// Revision 1.6 2002/02/07 05:42:10 rherveille
// Fixed some bugs discovered by modified testbench
// Removed / Changed some strange logic constructions
// Started work on hardware cursor support (not finished yet)
// Changed top-level name to vga_enh_top.v
//
//synopsys translate_off
`include "timescale.v"
//synopsys translate_on
module vga_colproc(clk, srst, vdat_buffer_di, ColorDepth, PseudoColor,
vdat_buffer_empty, vdat_buffer_rreq, rgb_fifo_full,
rgb_fifo_wreq, r, g, b,
clut_req, clut_ack, clut_offs, clut_q
);
//
// inputs & outputs
//
input clk; // master clock
input srst; // synchronous reset
input [31:0] vdat_buffer_di; // video memory data input
input [1:0] ColorDepth; // color depth (8bpp, 16bpp, 24bpp)
input PseudoColor; // pseudo color enabled (only for 8bpp color depth)
input vdat_buffer_empty;
output vdat_buffer_rreq; // pixel buffer read request
reg vdat_buffer_rreq;
input rgb_fifo_full;
output rgb_fifo_wreq;
reg rgb_fifo_wreq;
output [7:0] r, g, b; // pixel color information
reg [7:0] r, g, b;
output clut_req; // clut request
reg clut_req;
input clut_ack; // clut acknowledge
output [ 7:0] clut_offs; // clut offset
reg [7:0] clut_offs;
input [23:0] clut_q; // clut data in
//
// variable declarations
//
reg [31:0] DataBuffer;
reg [7:0] Ra, Ga, Ba;
reg [1:0] colcnt;
reg RGBbuf_wreq;
//
// Module body
//
// store word from pixelbuffer / wishbone input
always @(posedge clk)
if (vdat_buffer_rreq)
DataBuffer <= #1 vdat_buffer_di;
//
// generate statemachine
//
// extract color information from data buffer
parameter idle = 7'b000_0000,
fill_buf = 7'b000_0001,
bw_8bpp = 7'b000_0010,
col_8bpp = 7'b000_0100,
col_16bpp_a = 7'b000_1000,
col_16bpp_b = 7'b001_0000,
col_24bpp = 7'b010_0000,
col_32bpp = 7'b100_0000;
reg [6:0] c_state; // xsynopsys enum_state
reg [6:0] nxt_state; // xsynopsys enum_state
// next state decoder
always @(c_state or vdat_buffer_empty or ColorDepth or PseudoColor or rgb_fifo_full or colcnt or clut_ack)
begin : nxt_state_decoder
// initial value
nxt_state = c_state;
case (c_state) // synopsis full_case parallel_case
// idle state
idle:
if (!vdat_buffer_empty && !rgb_fifo_full)
nxt_state = fill_buf;
// fill data buffer
fill_buf:
case (ColorDepth) // synopsis full_case parallel_case
2'b00:
if (PseudoColor)
nxt_state = col_8bpp;
else
nxt_state = bw_8bpp;
2'b01:
nxt_state = col_16bpp_a;
2'b10:
nxt_state = col_24bpp;
2'b11:
nxt_state = col_32bpp;
endcase
//
// 8 bits per pixel
//
bw_8bpp:
if (!rgb_fifo_full && !(|colcnt) )
if (!vdat_buffer_empty)
nxt_state = fill_buf;
else
nxt_state = idle;
col_8bpp:
// Do NOT check for rgb_fifo_full here.
// In 8bpp pseudo-color mode the color-processor must always finish
// the current 4pixel-block(i.e. it runs until colcnt = '11').
// This is because of the late clut-response which shuffles all
// signals the state-machine depends on.
// Because of this we can not do an early video_memory_data fetch,
// i.e. we can not jump to the fill_buf state. Instead we always
// jump to idle and check for rgb_fifo_full there.
//
// The addition of the cursor-processors forces us to increase the
// rgb-fifo size. The increased rgb-fifo also handles the above
// described problem. Thus erradicating the above comment.
// We add the early video_memory_data fetch again.
if (!(|colcnt))
if (!vdat_buffer_empty && !rgb_fifo_full)
nxt_state = fill_buf;
else
nxt_state = idle;
//
// 16 bits per pixel
//
col_16bpp_a:
if (!rgb_fifo_full)
nxt_state = col_16bpp_b;
col_16bpp_b:
if (!rgb_fifo_full)
if (!vdat_buffer_empty)
nxt_state = fill_buf;
else
nxt_state = idle;
//
// 24 bits per pixel
//
col_24bpp:
if (!rgb_fifo_full)
if (colcnt == 2'h1) // (colcnt == 1)
nxt_state = col_24bpp; // stay in current state
else if (!vdat_buffer_empty)
nxt_state = fill_buf;
else
nxt_state = idle;
//
// 32 bits per pixel
//
col_32bpp:
if (!rgb_fifo_full)
if (!vdat_buffer_empty)
nxt_state = fill_buf;
else
nxt_state = idle;
endcase
end // next state decoder
// generate state registers
always @(posedge clk)
if (srst)
c_state <= #1 idle;
else
c_state <= #1 nxt_state;
reg iclut_req;
reg ivdat_buf_rreq;
reg [7:0] iR, iG, iB, iRa, iGa, iBa;
// output decoder
always @(c_state or vdat_buffer_empty or colcnt or DataBuffer or rgb_fifo_full or clut_ack or clut_q or Ba or Ga or Ra)
begin : output_decoder
// initial values
ivdat_buf_rreq = 1'b0;
RGBbuf_wreq = 1'b0;
iclut_req = 1'b0;
iR = 'h0;
iG = 'h0;
iB = 'h0;
iRa = 'h0;
iGa = 'h0;
iBa = 'h0;
case (c_state) // synopsis full_case parallel_case
idle:
begin
if (!rgb_fifo_full)
if (!vdat_buffer_empty)
ivdat_buf_rreq = 1'b1;
// when entering from 8bpp_pseudo_color_mode
RGBbuf_wreq = clut_ack;
iR = clut_q[23:16];
iG = clut_q[15: 8];
iB = clut_q[ 7: 0];
end
fill_buf:
begin
// when entering from 8bpp_pseudo_color_mode
RGBbuf_wreq = clut_ack;
iR = clut_q[23:16];
iG = clut_q[15: 8];
iB = clut_q[ 7: 0];
end
//
// 8 bits per pixel
//
bw_8bpp:
begin
if (!rgb_fifo_full)
begin
RGBbuf_wreq = 1'b1;
if ( (!vdat_buffer_empty) && !(|colcnt) )
ivdat_buf_rreq = 1'b1;
end
case (colcnt) // synopsis full_case parallel_case
2'b11:
begin
iR = DataBuffer[31:24];
iG = DataBuffer[31:24];
iB = DataBuffer[31:24];
end
2'b10:
begin
iR = DataBuffer[23:16];
iG = DataBuffer[23:16];
iB = DataBuffer[23:16];
end
2'b01:
begin
iR = DataBuffer[15:8];
iG = DataBuffer[15:8];
iB = DataBuffer[15:8];
end
default:
begin
iR = DataBuffer[7:0];
iG = DataBuffer[7:0];
iB = DataBuffer[7:0];
end
endcase
end
col_8bpp:
begin
// Do NOT check for rgb_fifo_full here.
// In 8bpp pseudo-color mode the color-processor must always finish
// the current 4pixel-block(i.e. it runs until colcnt = '11').
// This is because of the late clut-response which shuffles all
// signals the state-machine depends on.
// Because of this we can not do an early video_memory_data fetch,
// i.e. we can not jump to the fill_buf state. Instead we always
// jump to idle and check for rgb_fifo_full there.
//
// The addition of the cursor-processors forces us to increase the
// rgb-fifo size. The increased rgb-fifo also handles the above
// described problem. Thus erradicating the above comment.
// We add the early video_memory_data fetch again.
if (!(|colcnt))
if (!vdat_buffer_empty && !rgb_fifo_full)
ivdat_buf_rreq = 1'b1;
RGBbuf_wreq = clut_ack;
iR = clut_q[23:16];
iG = clut_q[15: 8];
iB = clut_q[ 7: 0];
iclut_req = !rgb_fifo_full || (colcnt[1] ^ colcnt[0]);
end
//
// 16 bits per pixel
//
col_16bpp_a:
begin
if (!rgb_fifo_full)
RGBbuf_wreq = 1'b1;
iR[7:3] = DataBuffer[31:27];
iG[7:2] = DataBuffer[26:21];
iB[7:3] = DataBuffer[20:16];
end
col_16bpp_b:
begin
if (!rgb_fifo_full)
begin
RGBbuf_wreq = 1'b1;
if (!vdat_buffer_empty)
ivdat_buf_rreq = 1'b1;
end
iR[7:3] = DataBuffer[15:11];
iG[7:2] = DataBuffer[10: 5];
iB[7:3] = DataBuffer[ 4: 0];
end
//
// 24 bits per pixel
//
col_24bpp:
begin
if (!rgb_fifo_full)
begin
RGBbuf_wreq = 1'b1;
if ( (colcnt != 2'h1) && !vdat_buffer_empty)
ivdat_buf_rreq = 1'b1;
end
case (colcnt) // synopsis full_case parallel_case
2'b11:
begin
iR = DataBuffer[31:24];
iG = DataBuffer[23:16];
iB = DataBuffer[15: 8];
iRa = DataBuffer[ 7: 0];
end
2'b10:
begin
iR = Ra;
iG = DataBuffer[31:24];
iB = DataBuffer[23:16];
iRa = DataBuffer[15: 8];
iGa = DataBuffer[ 7: 0];
end
2'b01:
begin
iR = Ra;
iG = Ga;
iB = DataBuffer[31:24];
iRa = DataBuffer[23:16];
iGa = DataBuffer[15: 8];
iBa = DataBuffer[ 7: 0];
end
default:
begin
iR = Ra;
iG = Ga;
iB = Ba;
end
endcase
end
//
// 32 bits per pixel
//
col_32bpp:
begin
if (!rgb_fifo_full)
begin
RGBbuf_wreq = 1'b1;
if (!vdat_buffer_empty)
ivdat_buf_rreq = 1'b1;
end
iR[7:0] = DataBuffer[23:16];
iG[7:0] = DataBuffer[15:8];
iB[7:0] = DataBuffer[7:0];
end
endcase
end // output decoder
// generate output registers
always @(posedge clk)
begin
r <= #1 iR;
g <= #1 iG;
b <= #1 iB;
if (RGBbuf_wreq)
begin
Ra <= #1 iRa;
Ba <= #1 iBa;
Ga <= #1 iGa;
end
if (srst)
begin
vdat_buffer_rreq <= #1 1'b0;
rgb_fifo_wreq <= #1 1'b0;
clut_req <= #1 1'b0;
end
else
begin
vdat_buffer_rreq <= #1 ivdat_buf_rreq;
rgb_fifo_wreq <= #1 RGBbuf_wreq;
clut_req <= #1 iclut_req;
end
end
// assign clut offset
always @(colcnt or DataBuffer)
case (colcnt) // synopsis full_case parallel_case
2'b11: clut_offs = DataBuffer[31:24];
2'b10: clut_offs = DataBuffer[23:16];
2'b01: clut_offs = DataBuffer[15: 8];
2'b00: clut_offs = DataBuffer[ 7: 0];
endcase
//
// color counter
//
always @(posedge clk)
if (srst)
colcnt <= #1 2'b11;
else if (RGBbuf_wreq)
colcnt <= #1 colcnt -2'h1;
endmodule