Permalink
Branch: master
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
88 lines (73 sloc) 2.62 KB
// FPGA VGA Graphics Part 2: Top Module
// (C)2018 Will Green - Licensed under the MIT License
// Learn more at https://timetoexplore.net/blog/arty-fpga-vga-verilog-02
// NB. This example loads an image and a palette file
// Replace .mem file names on lines 58 and 71 as appropriate
`default_nettype none
module top(
input wire CLK, // board clock: 100 MHz on Arty/Basys3/Nexys
input wire RST_BTN, // reset button
output wire VGA_HS_O, // horizontal sync output
output wire VGA_VS_O, // vertical sync output
output reg [3:0] VGA_R, // 4-bit VGA red output
output reg [3:0] VGA_G, // 4-bit VGA green output
output reg [3:0] VGA_B // 4-bit VGA blue output
);
wire rst = ~RST_BTN; // reset is active low on Arty & Nexys Video
// wire rst = RST_BTN; // reset is active high on Basys3 (BTNC)
// generate a 25 MHz pixel strobe
reg [15:0] cnt;
reg pix_stb;
always @(posedge CLK)
{pix_stb, cnt} <= cnt + 16'h4000; // divide by 4: (2^16)/4 = 0x4000
wire [9:0] x; // current pixel x position: 10-bit value: 0-1023
wire [8:0] y; // current pixel y position: 9-bit value: 0-511
wire active; // high during active pixel drawing
vga640x360 display (
.i_clk(CLK),
.i_pix_stb(pix_stb),
.i_rst(rst),
.o_hs(VGA_HS_O),
.o_vs(VGA_VS_O),
.o_x(x),
.o_y(y),
.o_active(active)
);
// VRAM frame buffers (read-write)
localparam SCREEN_WIDTH = 640;
localparam SCREEN_HEIGHT = 360;
localparam VRAM_DEPTH = SCREEN_WIDTH * SCREEN_HEIGHT;
localparam VRAM_A_WIDTH = 18; // 2^18 > 640 x 360
localparam VRAM_D_WIDTH = 6; // colour bits per pixel
reg [VRAM_A_WIDTH-1:0] address;
wire [VRAM_D_WIDTH-1:0] dataout;
sram #(
.ADDR_WIDTH(VRAM_A_WIDTH),
.DATA_WIDTH(VRAM_D_WIDTH),
.DEPTH(VRAM_DEPTH),
.MEMFILE("game.mem")) // bitmap to load
vram (
.i_addr(address),
.i_clk(CLK),
.i_write(0), // we're always reading
.i_data(0),
.o_data(dataout)
);
reg [11:0] palette [0:63]; // 64 x 12-bit colour palette entries
reg [11:0] colour;
initial begin
$display("Loading palette.");
$readmemh("game_palette.mem", palette); // bitmap palette to load
end
always @ (posedge CLK)
begin
address <= y * SCREEN_WIDTH + x;
if (active)
colour <= palette[dataout];
else
colour <= 0;
VGA_R <= colour[11:8];
VGA_G <= colour[7:4];
VGA_B <= colour[3:0];
end
endmodule