Untitled

 avatar
unknown
plain_text
9 days ago
13 kB
13
Indexable
`timescale 1 ns/ 100 ps
module VGAController(    
      input clk,              // 100 MHz System Clock
      input reset,            // Reset Signal
      output hSync,           // H Sync Signal
      output vSync,           // Veritcal Sync Signal
      output[3:0] VGA_R,  // Red Signal Bits
      output[3:0] VGA_G,  // Green Signal Bits
      output[3:0] VGA_B,  // Blue Signal Bits
      inout ps2_clk,
      inout ps2_data,
      input BTNC,
      input BTNU,
      input BTNL,
      input BTNR,
      input BTND
      // output[14:0] LED
      );
      
      // Lab Memory Files Location
      localparam FILES_PATH = "C:/Users/yg205/Downloads/lab6_kit/";

      // Clock divider 100 MHz -> 25 MHz
      wire clk25; // 25MHz clock

      reg[1:0] pixCounter = 0;      // Pixel counter to divide the clock
    assign clk25 = pixCounter[1]; // Set the clock high whenever the second bit (2) is high
      always @(posedge clk) begin
            pixCounter <= pixCounter + 1; // Since the reg is only 3 bits, it will reset every 8 cycles
      end

      // VGA Timing Generation for a Standard VGA Screen
      localparam
            VIDEO_WIDTH = 640,  // Standard VGA Width
            VIDEO_HEIGHT = 480; // Standard VGA Height

      wire active, screenEnd;
      wire[9:0] x;
      wire[8:0] y;
      
      VGATimingGenerator #(
            .HEIGHT(VIDEO_HEIGHT), // Use the standard VGA Values
            .WIDTH(VIDEO_WIDTH))
      Display(
            .clk25(clk25),       // 25MHz Pixel Clock
            .reset(reset),             // Reset Signal
            .screenEnd(screenEnd), // High for one cycle when between two frames
            .active(active),     // High when drawing pixels
            .hSync(hSync),       // Set Generated H Signal
            .vSync(vSync),             // Set Generated V Signal
            .x(x),                           // X Coordinate (from left)
            .y(y));                    // Y Coordinate (from top)   

      // Image Data to Map Pixel Location to Color Address
      localparam
            PIXEL_COUNT = VIDEO_WIDTH*VIDEO_HEIGHT,                // Number of pixels on the screen
            PIXEL_ADDRESS_WIDTH = $clog2(PIXEL_COUNT) + 1,           // Use built in log2 command
            BITS_PER_COLOR = 12,                                                     // Nexys A7 uses 12 bits/color
            PALETTE_COLOR_COUNT = 256,                                               // Number of Colors available
            PALETTE_ADDRESS_WIDTH = $clog2(PALETTE_COLOR_COUNT) + 1; // Use built in log2 Command

      wire[PIXEL_ADDRESS_WIDTH-1:0] imgAddress;        // Image address for the image data
      wire[PALETTE_ADDRESS_WIDTH-1:0] colorAddr;       // Color address for the color palette
      assign imgAddress = x + 640*y;                         // Address calculated coordinate

      RAM #(            
            .DEPTH(PIXEL_COUNT),                           // Set RAM depth to contain every pixel
            .DATA_WIDTH(PALETTE_ADDRESS_WIDTH),      // Set data width according to the color palette
            .ADDRESS_WIDTH(PIXEL_ADDRESS_WIDTH),     // Set address with according to the pixel count
            .MEMFILE({FILES_PATH, "image.mem"})) // Memory initialization
      ImageData(
            .clk(clk),                                 // Falling edge of the 100 MHz clk
            .addr(imgAddress),                               // Image data address
            .dataOut(colorAddr),                       // Color palette address
            .wEn(1'b0));                                     // We're always reading

      // Color Palette to Map Color Address to 12-Bit Color
      wire[BITS_PER_COLOR-1:0] colorData; // 12-bit color data at current pixel

      RAM #(
            .DEPTH(PALETTE_COLOR_COUNT),               // Set depth to contain every color            
            .DATA_WIDTH(BITS_PER_COLOR),               // Set data width according to the bits per color
            .ADDRESS_WIDTH(PALETTE_ADDRESS_WIDTH),     // Set address width according to the color count
            .MEMFILE({FILES_PATH, "colors.mem"}))  // Memory initialization
      ColorPalette(
            .clk(clk),                                               // Rising edge of the 100 MHz clk
            .addr(colorAddr),                                // Address from the ImageData RAM
            .dataOut(colorData),                             // Color at current pixel
            .wEn(1'b0));                                           // We're always reading
      
      
      wire [7:0] rx_data;
      wire read_data, busy, err;

      Ps2Interface ps2(
            ps2_clk,
            ps2_data,
            clk,
            reset,
            8'b0,
            8'b0,
            rx_data,
            read_data,
            busy,
            err
      );
      
    reg [7:0] code_out;
    initial begin
        code_out = 8'h1c;
    end
      
      always @(read_data) begin
//          pixCounter <= pixCounter + 1; // Since the reg is only 3 bits, it will reset every 8 cycles
            if (rx_data != 8'hf0) begin
              code_out = rx_data;
            end  
      end

      localparam
            BITS_PER_ASCII = 7,
            SPRITE_COUNT = 235000, //50*50,
            SPRITE_ADDRESS_WIDTH = $clog2(SPRITE_COUNT) + 1;      


      wire[BITS_PER_ASCII-1:0] ascii_value; // 12-bit color data at current pixel

      RAM #(
            .DEPTH(PALETTE_COLOR_COUNT),               // Set depth to contain every color            
            .DATA_WIDTH(BITS_PER_ASCII),               // Set data width according to the bits per color
            .ADDRESS_WIDTH(PALETTE_ADDRESS_WIDTH),     // Set address width according to the color count
            .MEMFILE({FILES_PATH, "ascii.mem"}))  // Memory initialization
      ASCIIDATA(
            .clk(clk),                                               // Rising edge of the 100 MHz clk
            .addr(code_out),                                 // Address from the ImageData RAM
            .dataOut(ascii_value),                           // Color at current pixel
            .wEn(1'b0));                                           // We're always reading

      wire[18:0] scan_code;

      // wire[BITS_PER_ASCII-1:0] ascii_val;
      // assign ascii_val = 50;
      assign scan_code = 50*50*(ascii_value-33) + currentPos;

      wire spirte_on;
      //Sprite mapping
      RAM #(            
            .DEPTH(SPRITE_COUNT),                          // Set RAM depth to contain every pixel
            .DATA_WIDTH(1),      // Set data width according to the color palette
            .ADDRESS_WIDTH(SPRITE_ADDRESS_WIDTH),     // Set address with according to the pixel count
            .MEMFILE({FILES_PATH, "sprites.mem"})) // Memory initialization
      SPRITEDATA(
            .clk(clk),                                 // Falling edge of the 100 MHz clk
            .addr(scan_code),                          // Image data address
            .dataOut(spirte_on),                       // Color palette address
            .wEn(1'b0));                                     // We're always reading



      // Assign to output color from register if active
      wire[BITS_PER_COLOR-1:0] colorOut;                // Output color
      wire [BITS_PER_COLOR-1:0] colorFinal;
      assign colorFinal = (xCheck & yCheck) ? 12'd0 : colorData ;
      assign colorOut = active ? colorFinal : 12'd0; // When not active, output black

      // Quickly assign the output colors to their channels using concatenation
      assign {VGA_R, VGA_G, VGA_B} = colorOut;

      reg [9:0] ax = 10'd20;
      reg [8:0] ay = 9'd20;

      wire [9:0] maxX;
      assign maxX = ax + 10'd50;
      wire [8:0] maxY;
      assign maxY = ay + 9'd50;

      wire xCheck, yCheck;
      assign xCheck = (x < maxX ? (x > ax) : 1'b0) & spirte_on;
      assign yCheck = (y < maxY ? (y > ay) : 1'b0) & spirte_on;
      
      //sprite on ids top left
      // wire bottomR;
      // assign bottomR = topR+2500;
      wire [9:0] xOffset;
      wire [8:0] yOffset;
      wire [18:0] currentPos;
      assign xOffset = x-ax;
      assign yOffset = y-ay;
      assign currentPos = xOffset*1+yOffset*50;

      always @(posedge screenEnd) begin
//          pixCounter <= pixCounter + 1; // Since the reg is only 3 bits, it will reset every 8 cycles
            if (BTNR)
              ax <= ax + BTNR;
        else if (BTNL)
            ax <= ax - BTNL;
        else if (BTND)    
            ay <= ay + BTND;
        else if (BTNU)
            ay <= ay - BTNU;
      end

endmodule
Editor is loading...
Leave a Comment