// ============================================================================ // (C) 2008 Robert T Finch // All rights reserved. // rob@birdcomputer.ca // // Bitmap Controller (360h x 225v x 15bpp): // // Displays a bitmap from memory. // The controller interfaces to the rest of the system using a burst mode // WISHBONE compatible bus controller. // // // This source code is available for evaluation and validation purposes // only. This copyright statement and disclaimer must remain present in // the file. // // // NO WARRANTY. // THIS Work, IS PROVIDEDED "AS IS" WITH NO WARRANTIES OF ANY KIND, WHETHER // EXPRESS OR IMPLIED. The user must assume the entire risk of using the // Work. // // IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY // INCIDENTAL, CONSEQUENTIAL, OR PUNITIVE DAMAGES WHATSOEVER RELATING TO // THE USE OF THIS WORK, OR YOUR RELATIONSHIP WITH THE AUTHOR. // // IN ADDITION, IN NO EVENT DOES THE AUTHOR AUTHORIZE YOU TO USE THE WORK // IN APPLICATIONS OR SYSTEMS WHERE THE WORK'S FAILURE TO PERFORM CAN // REASONABLY BE EXPECTED TO RESULT IN A SIGNIFICANT PHYSICAL INJURY, OR IN // LOSS OF LIFE. ANY SUCH USE BY YOU IS ENTIRELY AT YOUR OWN RISK, AND YOU // AGREE TO HOLD THE AUTHOR AND CONTRIBUTORS HARMLESS FROM ANY CLAIMS OR // LOSSES RELATING TO SUCH UNAUTHORIZED USE. // // The default base screen address is: // $100000 - the second 1 Mb of RAM // // // Verilog 1995 // Webpack 9.2i xc3s1000-4ft256 // 113 slices / 193 LUTs / 99.345 MHz // 101 ff's / 1 BRAM (1024x16) / 2 MULT (18x18) // // // +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // |WISHBONE Datasheet // |WISHBONE SoC Architecture Specification, Revision B.3 // | // |Description: Specifications: // +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // |General Description: Bitmap Controller // +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // |Supported Cycles: MASTER,BURST READ // | SLAVE,READ/WRITE // | SLAVE,BLOCK READ/WRITE // | SLAVE,RMW // +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // |Data port, size: 16 bit // |Data port, granularity: 16 bit // |Data port, maximum operand size: 16 bit // |Data transfer ordering: Undefined // |Data transfer sequencing: Undefined // +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // |Clock frequency constraints: none // +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // |MASTER Port // |Supported signal list and Signal Name WISHBONE equiv. // |cross reference to equivalent ack_i ACK_I // |WISHBONE signals adr_o[31:0] ADR_O() // | clk_i CLK_I // | rst_i RST_I() // | dat_i(15:0) DAT_I() // | dat_o(15:0) DAT_O() // | cyc_o CYC_O // | stb_o STB_O // | we_o WE_O // | bte_o(1:0) BTE_O() // | cti_o(2:0) CTI_O() // | // |SLAVE Port // |cross reference to equivalent wbs_ack_o ACK_O // |WISHBONE signals wbs_adr_i[31:0] ADR_I() // | clk_i CLK_I // | rst_i RST_I() // | wbs_dat_i(15:0) DAT_I() // | wbs_dat_o(15:0) DAT_O() // | wbs_cyc_i CYC_I // | wbs_stb_i STB_I // | wbs_we_i WE_I // | // +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // |Special requirements: // +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // // // ============================================================================ module ETF_BitmapController( rst_i, clk_i, cyc_o, stb_o, cti_o, bte_o, ack_i, we_o, sel_o, adr_o, dat_i, dat_o, wbs_cyc_i, wbs_stb_i, wbs_ack_o, wbs_we_i, wbs_sel_i, wbs_adr_i, wbs_dat_i, wbs_dat_o, vclk, eol, eof, blank, rgbo ); // WISHBONE SYSCON input rst_i; // system reset input clk_i; // system bus interface clock // WISHBONE Master // Used to read memory via burst access output cyc_o; // cycle is valid output stb_o; // data transfer strobe output [2:0] cti_o; // cycle type indicator output [1:0] bte_o; // burst type indicator input ack_i; // acknowledge from memory output we_o; // write to memory (always inactive) output [ 1:0] sel_o; // byte lane selects output [31:0] adr_o; // address for memory access input [15:0] dat_i; // memory data input output [15:0] dat_o; // data to memory (not really used) // WISHBONE Slave port // Used to set control register input wbs_cyc_i; // cycle is valid input wbs_stb_i; // data transfer acknowledge output wbs_ack_o; // controller acknowledge out input wbs_we_i; // write to controller input [ 1:0] wbs_sel_i; // byte lane select input [31:0] wbs_adr_i; // address for control register input [15:0] wbs_dat_i; // register data input output [15:0] wbs_dat_o; // register data output // Video input vclk; // Video clock 96.000 MHz input eol; // end of scan line input eof; // end of frame input blank; // blank the output output [23:0] rgbo; // 24-bit RGB output // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // IO registers // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - reg cyc_o; reg stb_o; reg [ 2:0] cti_o; reg [ 1:0] sel_o; reg [31:0] adr_o; reg [15:0] wbs_dat_o; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - reg [ 2:0] cnt; // counts the curst cycle number wire [15:0] rgb_int; // RGB data value from line buffer wire [11:0] hctr; // horizontal reference counter wire [11:0] vctr; // vertical reference counter reg [ 8:0] ra; // video buffer read address reg [31:0] bmBaseAddr; wire cs_reg = wbs_cyc_i && wbs_stb_i && wbs_adr_i[31:8]==24'hFFD0_D0; assign wbs_ack_o = cs_reg; always @(posedge clk_i) if (rst_i) begin bmBaseAddr <= 32'h0010_0000; end else begin if (cs_reg & wbs_we_i) begin case(wbs_adr_i[4:1]) 4'd0: begin if (wbs_sel_i[0]) bmBaseAddr[ 7: 1] <= wbs_dat_i[ 7:1]; if (wbs_sel_i[1]) bmBaseAddr[15: 8] <= wbs_dat_i[15:8]; end 4'd1: begin if (wbs_sel_i[0]) bmBaseAddr[23:16] <= wbs_dat_i[ 7:0]; if (wbs_sel_i[1]) bmBaseAddr[31:24] <= wbs_dat_i[15:8]; end endcase end end always @(wbs_adr_i or cs_reg or bmBaseAddr) if (cs_reg) case(wbs_adr_i) 4'd0: wbs_dat_o <= bmBaseAddr[15: 0]; 4'd1: wbs_dat_o <= bmBaseAddr[31:16]; endcase else wbs_dat_o <= 16'h0000; // Horizontal and Vertical timing reference counters VT163 #(12) u1 ( .clk(vclk), .clr_n(!rst_i), .ent(1'b1), .enp(1'b1), .ld_n(!eol), .d(12'hF9C), .q(hctr), .rco() ); VT163 #(12) u3 ( .clk(vclk), .clr_n(!rst_i), .ent(eol), .enp(1'b1), .ld_n(!eof), .d(12'hFC8), .q(vctr), .rco() ); wire hFetch = hctr < 12'd1536; // = 1536/128 = 12 wire vFetch = vctr < 12'd0900; // Burst mode bus controller // assign bte_o = 2'b10; // 00=linear burst 10 = 8 wrap assign we_o = 2'b0; // always read assign dat_o = 16'hFFEF; reg vreq; always @(posedge vclk) if (rst_i) vreq <= 1'b0; else begin if (hctr[6:0]==7'h00) vreq <= 1'b1; else if (cyc_o & stb_o) vreq <= 1'b0; end always @(posedge clk_i) if (rst_i) begin cnt <= 3'd0; cyc_o <= 1'b0; stb_o <= 1'b0; cti_o <= 3'b000; sel_o <= 2'b00; adr_o <= 32'hFFFF_FFFF; end else begin if (vreq && hFetch && vFetch) begin cnt <= 3'd0; cyc_o <= 1'b1; stb_o <= 1'b1; cti_o <= 3'b010; sel_o <= 2'b11; adr_o <= {bmBaseAddr[31:1] + vctr * 90 + hctr[11:7],4'b0}; end else if (cyc_o & stb_o) begin if (ack_i) begin if (cti_o==3'b000) begin cyc_o <= 1'b0; stb_o <= 1'b0; sel_o <= 2'b00; end else begin cnt <= cnt + 3'd1; // indicate last burst cycle if (cnt==3'd6) cti_o <= 3'b111; // terminate burst else if (cnt==3'd7) begin cyc_o <= 1'b0; stb_o <= 1'b0; cti_o <= 3'b000; sel_o <= 2'b00; end adr_o <= adr_o + 32'd2; end end end end // Computer video address // Calculated from horizontal and vertical counts // always @(posedge vclk) ra <= bmBaseAddr[31:1] + vctr[11:2] * 360 + hctr[11:2]; // Video line buffer // Flips between buffer halves. // Storage for 512x16 bit pixels // `define SPARTAN3 `ifdef SPARTAN3 RAMB16_S18_S18 ram0( .CLKA(clk_i), .ADDRA({vctr[2],adr_o[9:1]}), .DIA(dat_i), .DIPA(2'b11), .DOA(), .ENA(cyc_o & stb_o), .WEA(ack_i), .SSRA(1'b1), .CLKB(vclk), .ADDRB({~vctr[2],ra}), .DIB(16'hFFFF), .DIPB(2'b11), .DOB(rgb_int), .ENB(1'b1), .WEB(1'b0), .SSRB(blank) ); `else reg [11:0] mem [1023:0]; reg [10:1] ma; always @(posedge clk_i) if (cyc_o & stb_o) if (ack_i) mem[{vctr[2],adr_o[9:1]}] <= dat_i; always @(posedge vclk) ma <= {~vctr[2],ra}; assign rgb_int = mem[ma]; `endif assign rgbo = {rgb_int[14:10],3'b0,rgb_int[9:5],3'b0,rgb_int[4:0],3'd0}; endmodule