315 lines
9.8 KiB
Coq
315 lines
9.8 KiB
Coq
|
/////////////////////////////////////////////////////////////////////
|
||
|
//// ////
|
||
|
//// WISHBONE rev.B2 compliant enhanced VGA/LCD Core ////
|
||
|
//// Hardware Cursor Processor ////
|
||
|
//// ////
|
||
|
//// Author: Richard Herveille ////
|
||
|
//// richard@asics.ws ////
|
||
|
//// www.asics.ws ////
|
||
|
//// ////
|
||
|
//// Downloaded from: http://www.opencores.org/projects/vga_lcd ////
|
||
|
//// ////
|
||
|
/////////////////////////////////////////////////////////////////////
|
||
|
//// ////
|
||
|
//// Copyright (C) 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_curproc.v,v 1.4 2003/05/07 09:48:54 rherveille Exp $
|
||
|
//
|
||
|
// $Date: 2003/05/07 09:48:54 $
|
||
|
// $Revision: 1.4 $
|
||
|
// $Author: rherveille $
|
||
|
// $Locker: $
|
||
|
// $State: Exp $
|
||
|
//
|
||
|
// Change History:
|
||
|
// $Log: vga_curproc.v,v $
|
||
|
// Revision 1.4 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.3 2002/03/04 16:05:52 rherveille
|
||
|
// Added hardware cursor support to wishbone master.
|
||
|
// Added provision to turn-off 3D cursors.
|
||
|
// Fixed some minor bugs.
|
||
|
//
|
||
|
// Revision 1.2 2002/03/04 11:01:59 rherveille
|
||
|
// Added 64x64pixels 4bpp hardware cursor support.
|
||
|
//
|
||
|
// Revision 1.1 2002/02/16 10:40:00 rherveille
|
||
|
// Some minor bug-fixes.
|
||
|
// Changed vga_ssel into vga_curproc (cursor processor).
|
||
|
//
|
||
|
// Revision 1.1 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_curproc (clk, rst_i, Thgate, Tvgate, idat, idat_wreq,
|
||
|
cursor_xy, cursor_en, cursor_res,
|
||
|
cursor_wadr, cursor_wdat, cursor_we,
|
||
|
cc_adr_o, cc_dat_i,
|
||
|
rgb_fifo_wreq, rgb);
|
||
|
|
||
|
//
|
||
|
// inputs & outputs
|
||
|
//
|
||
|
|
||
|
// wishbone signals
|
||
|
input clk; // master clock input
|
||
|
input rst_i; // synchronous active high reset
|
||
|
|
||
|
// image size
|
||
|
input [15:0] Thgate, Tvgate; // horizontal/vertical gate
|
||
|
// image data
|
||
|
input [23:0] idat; // image data input
|
||
|
input idat_wreq; // image data write request
|
||
|
|
||
|
// cursor data
|
||
|
input [31:0] cursor_xy; // cursor (x,y)
|
||
|
input cursor_en; // cursor enable (on/off)
|
||
|
input cursor_res; // cursor resolution (32x32 or 64x64 pixels)
|
||
|
input [ 8:0] cursor_wadr; // cursor buffer write address
|
||
|
input [31:0] cursor_wdat; // cursor buffer write data
|
||
|
input cursor_we; // cursor buffer write enable
|
||
|
|
||
|
// color registers interface
|
||
|
output [ 3:0] cc_adr_o; // cursor color registers address
|
||
|
reg [ 3:0] cc_adr_o;
|
||
|
input [15:0] cc_dat_i; // cursor color registers data
|
||
|
|
||
|
// rgb-fifo connections
|
||
|
output rgb_fifo_wreq; // rgb-out write request
|
||
|
reg rgb_fifo_wreq;
|
||
|
output [23:0] rgb; // rgb data output
|
||
|
reg [23:0] rgb;
|
||
|
|
||
|
//
|
||
|
// variable declarations
|
||
|
//
|
||
|
reg dcursor_en, ddcursor_en, dddcursor_en;
|
||
|
reg [15:0] xcnt, ycnt;
|
||
|
wire xdone, ydone;
|
||
|
wire [15:0] cursor_x, cursor_y;
|
||
|
wire cursor_isalpha;
|
||
|
reg [15:0] cdat, dcdat;
|
||
|
wire [ 7:0] cursor_r, cursor_g, cursor_b, cursor_alpha;
|
||
|
reg inbox_x, inbox_y;
|
||
|
wire inbox;
|
||
|
reg dinbox, ddinbox, dddinbox;
|
||
|
|
||
|
reg [23:0] didat, ddidat, dddidat;
|
||
|
reg didat_wreq, ddidat_wreq;
|
||
|
wire [31:0] cbuf_q;
|
||
|
reg [11:0] cbuf_ra;
|
||
|
reg [ 2:0] dcbuf_ra;
|
||
|
wire [ 8:0] cbuf_a;
|
||
|
|
||
|
reg store1, store2;
|
||
|
|
||
|
//
|
||
|
// module body
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// generate x-y counters
|
||
|
always@(posedge clk)
|
||
|
if(rst_i || xdone)
|
||
|
xcnt <= #1 16'h0;
|
||
|
else if (idat_wreq)
|
||
|
xcnt <= #1 xcnt + 16'h1;
|
||
|
|
||
|
assign xdone = (xcnt == Thgate) && idat_wreq;
|
||
|
|
||
|
always@(posedge clk)
|
||
|
if(rst_i || ydone)
|
||
|
ycnt <= #1 16'h0;
|
||
|
else if (xdone)
|
||
|
ycnt <= #1 ycnt + 16'h1;
|
||
|
|
||
|
assign ydone = (ycnt == Tvgate) && xdone;
|
||
|
|
||
|
|
||
|
// decode cursor (x,y)
|
||
|
assign cursor_x = cursor_xy[15: 0];
|
||
|
assign cursor_y = cursor_xy[31:16];
|
||
|
|
||
|
//
|
||
|
// generate inbox signals
|
||
|
always@(posedge clk)
|
||
|
begin
|
||
|
inbox_x <= #1 (xcnt >= cursor_x) && (xcnt < (cursor_x + (cursor_res ? 16'h7f : 16'h1f) ));
|
||
|
inbox_y <= #1 (ycnt >= cursor_y) && (ycnt < (cursor_y + (cursor_res ? 16'h7f : 16'h1f) ));
|
||
|
end
|
||
|
|
||
|
assign inbox = inbox_x && inbox_y;
|
||
|
|
||
|
always@(posedge clk)
|
||
|
dinbox <= #1 inbox;
|
||
|
|
||
|
always@(posedge clk)
|
||
|
if (didat_wreq)
|
||
|
ddinbox <= #1 dinbox;
|
||
|
|
||
|
always@(posedge clk)
|
||
|
dddinbox <= #1 ddinbox;
|
||
|
|
||
|
//
|
||
|
// generate cursor buffer address counter
|
||
|
always@(posedge clk)
|
||
|
if (!cursor_en || ydone)
|
||
|
cbuf_ra <= #1 12'h0;
|
||
|
else if (inbox && idat_wreq)
|
||
|
cbuf_ra <= #1 cbuf_ra +12'h1;
|
||
|
|
||
|
always@(posedge clk)
|
||
|
dcbuf_ra <= #1 cbuf_ra[2:0];
|
||
|
|
||
|
assign cbuf_a = cursor_we ? cursor_wadr : cursor_res ? cbuf_ra[11:3] : cbuf_ra[9:1];
|
||
|
|
||
|
// hookup local cursor memory (generic synchronous single port memory)
|
||
|
// cursor memory should never be written to/read from at the same time
|
||
|
generic_spram #(9, 32) cbuf(
|
||
|
.clk(clk),
|
||
|
.rst(1'b0), // no reset
|
||
|
.ce(1'b1), // always enable memory
|
||
|
.we(cursor_we),
|
||
|
.oe(1'b1), // always output data
|
||
|
.addr(cbuf_a),
|
||
|
.di(cursor_wdat),
|
||
|
.do(cbuf_q)
|
||
|
);
|
||
|
|
||
|
//
|
||
|
// decode cursor data for 32x32x16bpp mode
|
||
|
always@(posedge clk)
|
||
|
if (didat_wreq)
|
||
|
cdat <= #1 dcbuf_ra[0] ? cbuf_q[31:16] : cbuf_q[15:0];
|
||
|
|
||
|
always@(posedge clk)
|
||
|
dcdat <= #1 cdat;
|
||
|
|
||
|
//
|
||
|
// decode cursor data for 64x64x4bpp mode
|
||
|
|
||
|
// generate cursor-color address
|
||
|
always@(posedge clk)
|
||
|
if (didat_wreq)
|
||
|
case (dcbuf_ra)
|
||
|
3'b000: cc_adr_o <= cbuf_q[ 3: 0];
|
||
|
3'b001: cc_adr_o <= cbuf_q[ 7: 4];
|
||
|
3'b010: cc_adr_o <= cbuf_q[11: 8];
|
||
|
3'b011: cc_adr_o <= cbuf_q[15:12];
|
||
|
3'b100: cc_adr_o <= cbuf_q[19:16];
|
||
|
3'b101: cc_adr_o <= cbuf_q[23:20];
|
||
|
3'b110: cc_adr_o <= cbuf_q[27:24];
|
||
|
3'b111: cc_adr_o <= cbuf_q[31:28];
|
||
|
endcase
|
||
|
|
||
|
//
|
||
|
// generate cursor colors
|
||
|
assign cursor_isalpha = cursor_res ? cc_dat_i[15] : dcdat[15];
|
||
|
assign cursor_alpha = cursor_res ? cc_dat_i[7:0] : dcdat[7:0];
|
||
|
assign cursor_r = {cursor_res ? cc_dat_i[14:10] : dcdat[14:10], 3'h0};
|
||
|
assign cursor_g = {cursor_res ? cc_dat_i[ 9: 5] : dcdat[ 9: 5], 3'h0};
|
||
|
assign cursor_b = {cursor_res ? cc_dat_i[ 4: 0] : dcdat[ 4: 0], 3'h0};
|
||
|
|
||
|
//
|
||
|
// delay image data
|
||
|
always@(posedge clk)
|
||
|
didat <= #1 idat;
|
||
|
|
||
|
always@(posedge clk)
|
||
|
if (didat_wreq)
|
||
|
ddidat <= #1 didat;
|
||
|
|
||
|
always@(posedge clk)
|
||
|
dddidat <= #1 ddidat;
|
||
|
|
||
|
always@(posedge clk)
|
||
|
begin
|
||
|
didat_wreq <= #1 idat_wreq;
|
||
|
ddidat_wreq <= #1 didat_wreq;
|
||
|
end
|
||
|
|
||
|
//
|
||
|
// generate selection unit
|
||
|
always@(posedge clk)
|
||
|
dcursor_en <= #1 cursor_en;
|
||
|
|
||
|
always@(posedge clk)
|
||
|
if (didat_wreq)
|
||
|
ddcursor_en <= #1 dcursor_en;
|
||
|
|
||
|
always@(posedge clk)
|
||
|
dddcursor_en <= #1 ddcursor_en;
|
||
|
|
||
|
// Alpha blending:
|
||
|
// rgb = (rgb1 * alhpa1) + (rgb2 * alpha2)
|
||
|
// We generate an alpha mixer (alpha1 + alpha2 = 1)
|
||
|
// rgb = (alpha1)(rgb1) + (1-alpha1)(rgb2)
|
||
|
// We always mix to black (rgb2 = 0)
|
||
|
// rgb = (alpha1)(rgb1)
|
||
|
always@(posedge clk)
|
||
|
if (ddidat_wreq)
|
||
|
if (!dddcursor_en || !dddinbox)
|
||
|
rgb <= #1 dddidat;
|
||
|
else if (cursor_isalpha)
|
||
|
`ifdef VGA_HWC_3D
|
||
|
rgb <= #1 dddidat * cursor_alpha;
|
||
|
`else
|
||
|
rgb <= #1 dddidat;
|
||
|
`endif
|
||
|
else
|
||
|
rgb <= #1 {cursor_r, cursor_g, cursor_b};
|
||
|
|
||
|
//
|
||
|
// generate write request signal
|
||
|
always@(posedge clk)
|
||
|
if (rst_i)
|
||
|
begin
|
||
|
store1 <= #1 1'b0;
|
||
|
store2 <= #1 1'b0;
|
||
|
end
|
||
|
else
|
||
|
begin
|
||
|
store1 <= #1 didat_wreq | store1;
|
||
|
store2 <= #1 (didat_wreq & store1) | store2;
|
||
|
end
|
||
|
|
||
|
// skip 2 idat_wreq signal, to keep in pace with rgb_fifo_full signal
|
||
|
always@(posedge clk)
|
||
|
rgb_fifo_wreq <= #1 ddidat_wreq & store2;
|
||
|
|
||
|
endmodule
|