mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2025-04-28 20:38:09 +00:00
verilog-vga: updated presets
This commit is contained in:
parent
e44a0734dd
commit
cde43b361f
presets/verilog-vga
src/platform
244
presets/verilog-vga/ball_paddle.v
Normal file
244
presets/verilog-vga/ball_paddle.v
Normal file
@ -0,0 +1,244 @@
|
||||
|
||||
`include "hvsync_generator.v"
|
||||
`include "digits10.v"
|
||||
`include "scoreboard.v"
|
||||
|
||||
/*
|
||||
A brick-smashing ball-and-paddle game.
|
||||
*/
|
||||
|
||||
module ball_paddle_top(clk, reset, hpaddle, hsync, vsync, rgb);
|
||||
|
||||
input clk;
|
||||
input reset;
|
||||
input hpaddle;
|
||||
output hsync, vsync;
|
||||
output [2:0] rgb;
|
||||
wire display_on;
|
||||
wire [9:0] hpos;
|
||||
wire [9:0] vpos;
|
||||
|
||||
reg [9:0] paddle_pos; // paddle X position
|
||||
|
||||
reg [9:0] ball_x; // ball X position
|
||||
reg [9:0] ball_y; // ball Y position
|
||||
reg ball_dir_x; // ball X direction (0=left, 1=right)
|
||||
reg ball_speed_x; // ball speed (0=1 pixel/frame, 1=2 pixels/frame)
|
||||
reg ball_dir_y; // ball Y direction (0=up, 1=down)
|
||||
|
||||
reg brick_array [0:BRICKS_H*BRICKS_V-1]; // 16*8 = 128 bits
|
||||
|
||||
wire [3:0] score0; // score right digit
|
||||
wire [3:0] score1; // score left digit
|
||||
wire [3:0] lives; // # lives remaining
|
||||
reg incscore; // incscore signal
|
||||
reg declives = 0; // TODO
|
||||
|
||||
localparam BRICKS_H = 16; // # of bricks across
|
||||
localparam BRICKS_V = 8; // # of bricks down
|
||||
|
||||
localparam BALL_DIR_LEFT = 0;
|
||||
localparam BALL_DIR_RIGHT = 1;
|
||||
localparam BALL_DIR_DOWN = 1;
|
||||
localparam BALL_DIR_UP = 0;
|
||||
|
||||
localparam PADDLE_WIDTH = 63; // horizontal paddle size
|
||||
localparam BALL_SIZE = 12; // square ball size
|
||||
|
||||
// video sync generator
|
||||
hvsync_generator hvsync_gen(
|
||||
.clk(clk),
|
||||
.reset(reset),
|
||||
.hsync(hsync),
|
||||
.vsync(vsync),
|
||||
.display_on(display_on),
|
||||
.hpos(hpos),
|
||||
.vpos(vpos)
|
||||
);
|
||||
|
||||
// scoreboard
|
||||
wire score_gfx; // output from score generator
|
||||
player_stats stats(
|
||||
.reset(reset),
|
||||
.score0(score0),
|
||||
.score1(score1),
|
||||
.incscore(incscore),
|
||||
.lives(lives),
|
||||
.declives(declives)
|
||||
);
|
||||
|
||||
scoreboard_generator score_gen(
|
||||
.score0(score0),
|
||||
.score1(score1),
|
||||
.lives(lives),
|
||||
.vpos(vpos),
|
||||
.hpos(hpos),
|
||||
.board_gfx(score_gfx)
|
||||
);
|
||||
|
||||
wire [5:0] hcell = hpos[9:4]; // horizontal brick index
|
||||
wire [5:0] vcell = vpos[9:4]; // vertical brick index
|
||||
wire lr_border = hcell==0 || hcell==31; // along horizontal border?
|
||||
|
||||
// TODO: unsigned compare doesn't work in JS
|
||||
wire [9:0] paddle_rel_x = ((hpos-paddle_pos) & 10'h3ff);
|
||||
|
||||
// player paddle graphics signal
|
||||
wire paddle_gfx = (vcell == 28) && (paddle_rel_x < PADDLE_WIDTH);
|
||||
|
||||
// difference between ball position and video beam
|
||||
wire [9:0] ball_rel_x = (hpos - ball_x);
|
||||
wire [9:0] ball_rel_y = (vpos - ball_y);
|
||||
|
||||
// ball graphics signal
|
||||
wire ball_gfx = ball_rel_x < BALL_SIZE
|
||||
&& ball_rel_y < BALL_SIZE;
|
||||
|
||||
reg main_gfx; // main graphics signal (bricks and borders)
|
||||
reg brick_present; // 1 when we are drawing a brick
|
||||
reg [6:0] brick_index;// index into array of current brick
|
||||
// brick graphics signal
|
||||
wire brick_gfx = lr_border || (brick_present && vpos[3:1] != 0 && hpos[4:2] != 4);
|
||||
|
||||
// scan bricks: compute brick_index and brick_present flag
|
||||
always @(posedge clk)
|
||||
// see if we are scanning brick area
|
||||
if (vpos[9:7] == 1 && !lr_border)
|
||||
begin
|
||||
// every 16th pixel, starting at 8
|
||||
if (hpos[4:0] == 8) begin
|
||||
// compute brick index
|
||||
brick_index <= {vpos[6:4], hpos[8:5]};
|
||||
end
|
||||
// every 17th pixel
|
||||
else if (hpos[4:0] == 9) begin
|
||||
// load brick bit from array
|
||||
brick_present <= !brick_array[brick_index];
|
||||
end
|
||||
end else begin
|
||||
brick_present <= 0;
|
||||
end
|
||||
|
||||
// only works when paddle at bottom of screen!
|
||||
// (we don't want to mess w/ paddle position during visible portion)
|
||||
always @(posedge hsync)
|
||||
if (!hpaddle)
|
||||
paddle_pos <= vpos;
|
||||
|
||||
// 1 when ball signal intersects main (brick + border) signal
|
||||
wire ball_pixel_collide = main_gfx & ball_gfx;
|
||||
|
||||
reg ball_collide_paddle = 0;
|
||||
reg [3:0] ball_collide_bits = 0;
|
||||
|
||||
// compute ball collisions with paddle and playfield
|
||||
always @(posedge clk)
|
||||
// clear all collide bits for frame
|
||||
if (vsync) begin
|
||||
ball_collide_bits <= 0;
|
||||
ball_collide_paddle <= 0;
|
||||
end else begin
|
||||
if (ball_pixel_collide) begin
|
||||
// did we collide w/ paddle?
|
||||
if (paddle_gfx) begin
|
||||
ball_collide_paddle <= 1;
|
||||
end
|
||||
// ball has 4 collision quadrants
|
||||
if (!ball_rel_x[2] & !ball_rel_y[2]) ball_collide_bits[0] <= 1;
|
||||
if (ball_rel_x[2] & !ball_rel_y[2]) ball_collide_bits[1] <= 1;
|
||||
if (!ball_rel_x[2] & ball_rel_y[2]) ball_collide_bits[2] <= 1;
|
||||
if (ball_rel_x[2] & ball_rel_y[2]) ball_collide_bits[3] <= 1;
|
||||
end
|
||||
end
|
||||
|
||||
// compute ball collisions with brick and increment score
|
||||
always @(posedge clk)
|
||||
if (ball_pixel_collide && brick_present) begin
|
||||
brick_array[brick_index] <= 1;
|
||||
incscore <= 1; // increment score
|
||||
end else begin
|
||||
incscore <= 0; // reset incscore
|
||||
end
|
||||
|
||||
// computes position of ball in relation to center of paddle
|
||||
wire signed [9:0] ball_paddle_dx = ball_x - paddle_pos + 8;
|
||||
|
||||
// ball bounce: determine new velocity/direction
|
||||
always @(posedge vsync or posedge reset)
|
||||
begin
|
||||
if (reset) begin
|
||||
ball_dir_y <= BALL_DIR_DOWN;
|
||||
end else
|
||||
// ball collided with paddle?
|
||||
if (ball_collide_paddle) begin
|
||||
// bounces upward off of paddle
|
||||
ball_dir_y <= BALL_DIR_UP;
|
||||
// which side of paddle, left/right?
|
||||
ball_dir_x <= (ball_paddle_dx < 20) ? BALL_DIR_LEFT : BALL_DIR_RIGHT;
|
||||
// hitting with edge of paddle makes it fast
|
||||
ball_speed_x <= ball_collide_bits[3:0] != 4'b1100;
|
||||
end else begin
|
||||
// collided with playfield
|
||||
// TODO: can still slip through corners
|
||||
// compute left/right bounce
|
||||
casez (ball_collide_bits[3:0])
|
||||
4'b01?1: ball_dir_x <= BALL_DIR_RIGHT; // left edge/corner
|
||||
4'b1101: ball_dir_x <= BALL_DIR_RIGHT; // left corner
|
||||
4'b101?: ball_dir_x <= BALL_DIR_LEFT; // right edge/corner
|
||||
4'b1110: ball_dir_x <= BALL_DIR_LEFT; // right corner
|
||||
default: ;
|
||||
endcase
|
||||
// compute top/bottom bounce
|
||||
casez (ball_collide_bits[3:0])
|
||||
4'b1011: ball_dir_y <= BALL_DIR_DOWN;
|
||||
4'b0111: ball_dir_y <= BALL_DIR_DOWN;
|
||||
4'b001?: ball_dir_y <= BALL_DIR_DOWN;
|
||||
4'b0001: ball_dir_y <= BALL_DIR_DOWN;
|
||||
4'b0100: ball_dir_y <= BALL_DIR_UP;
|
||||
4'b1?00: ball_dir_y <= BALL_DIR_UP;
|
||||
4'b1101: ball_dir_y <= BALL_DIR_UP;
|
||||
4'b1110: ball_dir_y <= BALL_DIR_UP;
|
||||
default: ;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
// ball motion: update ball position
|
||||
always @(negedge vsync or posedge reset)
|
||||
begin
|
||||
if (reset) begin
|
||||
// reset ball position to top center
|
||||
ball_x <= 256;
|
||||
ball_y <= 320;
|
||||
end else begin
|
||||
// move ball horizontal and vertical position
|
||||
if (ball_dir_x == BALL_DIR_RIGHT)
|
||||
ball_x <= ball_x + (ball_speed_x?1:0) + 1;
|
||||
else
|
||||
ball_x <= ball_x - (ball_speed_x?1:0) - 1;
|
||||
ball_y <= ball_y + (ball_dir_y==BALL_DIR_DOWN?1:-1);
|
||||
end
|
||||
end
|
||||
|
||||
// compute main_gfx
|
||||
always @(*)
|
||||
begin
|
||||
case (vpos[9:4])
|
||||
0,1,2: main_gfx = score_gfx; // scoreboard
|
||||
3: main_gfx = 0;
|
||||
4: main_gfx = 1; // top border
|
||||
8,9,10,11,12,13,14,15: main_gfx = brick_gfx; // brick rows 1-8
|
||||
28: main_gfx = paddle_gfx | lr_border; // paddle
|
||||
29: main_gfx = hpos[0] ^ vpos[0]; // bottom border
|
||||
default: main_gfx = lr_border; // left/right borders
|
||||
endcase
|
||||
end
|
||||
|
||||
// combine signals to RGB output
|
||||
wire grid_gfx = (((hpos&15)==0) || ((vpos&15)==0));
|
||||
wire r = display_on && (ball_gfx | paddle_gfx);
|
||||
wire g = display_on && (main_gfx | ball_gfx);
|
||||
wire b = display_on && (grid_gfx | ball_gfx | brick_present);
|
||||
assign rgb = {b,g,r};
|
||||
|
||||
endmodule
|
84
presets/verilog-vga/chardisplay.v
Normal file
84
presets/verilog-vga/chardisplay.v
Normal file
@ -0,0 +1,84 @@
|
||||
|
||||
`include "hvsync_generator.v"
|
||||
`include "digits10.v"
|
||||
`include "ram.v"
|
||||
|
||||
/*
|
||||
Displays a grid of digits on the CRT using a RAM module.
|
||||
*/
|
||||
|
||||
module test_ram1_top(clk, reset, hsync, vsync, rgb);
|
||||
|
||||
input clk, reset;
|
||||
output hsync, vsync;
|
||||
output [2:0] rgb;
|
||||
|
||||
wire display_on;
|
||||
wire [9:0] hpos;
|
||||
wire [9:0] vpos;
|
||||
|
||||
wire [9:0] ram_addr;
|
||||
wire [7:0] ram_read;
|
||||
reg [7:0] ram_write;
|
||||
reg ram_writeenable = 0;
|
||||
|
||||
// RAM to hold 32x32 array of bytes
|
||||
RAM_sync ram(
|
||||
.clk(clk),
|
||||
.dout(ram_read),
|
||||
.din(ram_write),
|
||||
.addr(ram_addr),
|
||||
.we(ram_writeenable)
|
||||
);
|
||||
|
||||
hvsync_generator hvsync_gen(
|
||||
.clk(clk),
|
||||
.reset(reset),
|
||||
.hsync(hsync),
|
||||
.vsync(vsync),
|
||||
.display_on(display_on),
|
||||
.hpos(hpos),
|
||||
.vpos(vpos)
|
||||
);
|
||||
|
||||
wire [4:0] row = vpos[7:3]; // 5-bit row, vpos / 8
|
||||
wire [4:0] col = hpos[7:3]; // 5-bit column, hpos / 8
|
||||
wire [2:0] rom_yofs = vpos[2:0]; // scanline of cell
|
||||
wire [4:0] rom_bits; // 5 pixels per scanline
|
||||
|
||||
wire [3:0] digit = ram_read[3:0]; // read digit from RAM
|
||||
wire [2:0] xofs = hpos[2:0]; // which pixel to draw (0-7)
|
||||
|
||||
assign ram_addr = {row,col}; // 10-bit RAM address
|
||||
|
||||
// digits ROM
|
||||
digits10_case numbers(
|
||||
.digit(digit),
|
||||
.yofs(rom_yofs),
|
||||
.bits(rom_bits)
|
||||
);
|
||||
|
||||
// extract bit from ROM output
|
||||
wire r = display_on && 0;
|
||||
wire g = display_on && rom_bits[~xofs];
|
||||
wire b = display_on && 0;
|
||||
assign rgb = {b,g,r};
|
||||
|
||||
// increment the current RAM cell
|
||||
always @(posedge clk)
|
||||
case (hpos[2:0])
|
||||
// on 7th pixel of cell
|
||||
6: begin
|
||||
// increment RAM cell
|
||||
ram_write <= (ram_read + 1);
|
||||
// only enable write on last scanline of cell
|
||||
ram_writeenable <= (vpos[2:0] == 7);
|
||||
end
|
||||
// on 8th pixel of cell
|
||||
7: begin
|
||||
// disable write
|
||||
ram_writeenable <= 0;
|
||||
end
|
||||
endcase
|
||||
|
||||
endmodule
|
211
presets/verilog-vga/digits10.v
Normal file
211
presets/verilog-vga/digits10.v
Normal file
@ -0,0 +1,211 @@
|
||||
|
||||
`ifndef DIGITS10_H
|
||||
`define DIGITS10_H
|
||||
|
||||
`include "hvsync_generator.v"
|
||||
|
||||
/*
|
||||
ROM module with 5x5 bitmaps for the digits 0-9.
|
||||
|
||||
digits10_case - Uses the case statement.
|
||||
digits10_array - Uses an array and initial block.
|
||||
|
||||
These two modules are functionally equivalent.
|
||||
*/
|
||||
|
||||
// module for 10-digit bitmap ROM
|
||||
module digits10_case(digit, yofs, bits);
|
||||
|
||||
input [3:0] digit; // digit 0-9
|
||||
input [2:0] yofs; // vertical offset (0-4)
|
||||
output reg [4:0] bits; // output (5 bits)
|
||||
|
||||
// combine {digit,yofs} into single ROM address
|
||||
wire [6:0] caseexpr = {digit,yofs};
|
||||
|
||||
always @(*)
|
||||
case (caseexpr)/*{w:5,h:5,count:10}*/
|
||||
7'o00: bits = 5'b11111;
|
||||
7'o01: bits = 5'b10001;
|
||||
7'o02: bits = 5'b10001;
|
||||
7'o03: bits = 5'b10001;
|
||||
7'o04: bits = 5'b11111;
|
||||
|
||||
7'o10: bits = 5'b01100;
|
||||
7'o11: bits = 5'b00100;
|
||||
7'o12: bits = 5'b00100;
|
||||
7'o13: bits = 5'b00100;
|
||||
7'o14: bits = 5'b11111;
|
||||
|
||||
7'o20: bits = 5'b11111;
|
||||
7'o21: bits = 5'b00001;
|
||||
7'o22: bits = 5'b11111;
|
||||
7'o23: bits = 5'b10000;
|
||||
7'o24: bits = 5'b11111;
|
||||
|
||||
7'o30: bits = 5'b11111;
|
||||
7'o31: bits = 5'b00001;
|
||||
7'o32: bits = 5'b11111;
|
||||
7'o33: bits = 5'b00001;
|
||||
7'o34: bits = 5'b11111;
|
||||
|
||||
7'o40: bits = 5'b10001;
|
||||
7'o41: bits = 5'b10001;
|
||||
7'o42: bits = 5'b11111;
|
||||
7'o43: bits = 5'b00001;
|
||||
7'o44: bits = 5'b00001;
|
||||
|
||||
7'o50: bits = 5'b11111;
|
||||
7'o51: bits = 5'b10000;
|
||||
7'o52: bits = 5'b11111;
|
||||
7'o53: bits = 5'b00001;
|
||||
7'o54: bits = 5'b11111;
|
||||
|
||||
7'o60: bits = 5'b11111;
|
||||
7'o61: bits = 5'b10000;
|
||||
7'o62: bits = 5'b11111;
|
||||
7'o63: bits = 5'b10001;
|
||||
7'o64: bits = 5'b11111;
|
||||
|
||||
7'o70: bits = 5'b11111;
|
||||
7'o71: bits = 5'b00001;
|
||||
7'o72: bits = 5'b00001;
|
||||
7'o73: bits = 5'b00001;
|
||||
7'o74: bits = 5'b00001;
|
||||
|
||||
7'o100: bits = 5'b11111;
|
||||
7'o101: bits = 5'b10001;
|
||||
7'o102: bits = 5'b11111;
|
||||
7'o103: bits = 5'b10001;
|
||||
7'o104: bits = 5'b11111;
|
||||
|
||||
7'o110: bits = 5'b11111;
|
||||
7'o111: bits = 5'b10001;
|
||||
7'o112: bits = 5'b11111;
|
||||
7'o113: bits = 5'b00001;
|
||||
7'o114: bits = 5'b11111;
|
||||
|
||||
default: bits = 0;
|
||||
endcase
|
||||
endmodule
|
||||
|
||||
module digits10_array(digit, yofs, bits);
|
||||
|
||||
input [3:0] digit; // digit 0-9
|
||||
input [2:0] yofs; // vertical offset (0-4)
|
||||
output [4:0] bits; // output (5 bits)
|
||||
|
||||
reg [4:0] bitarray[0:15][0:4]; // ROM array (16 x 5 x 5 bits)
|
||||
|
||||
assign bits = bitarray[digit][yofs]; // assign module output
|
||||
|
||||
integer i,j;
|
||||
|
||||
initial begin/*{w:5,h:5,count:10}*/
|
||||
bitarray[0][0] = 5'b11111;
|
||||
bitarray[0][1] = 5'b10001;
|
||||
bitarray[0][2] = 5'b10001;
|
||||
bitarray[0][3] = 5'b10001;
|
||||
bitarray[0][4] = 5'b11111;
|
||||
|
||||
bitarray[1][0] = 5'b01100;
|
||||
bitarray[1][1] = 5'b00100;
|
||||
bitarray[1][2] = 5'b00100;
|
||||
bitarray[1][3] = 5'b00100;
|
||||
bitarray[1][4] = 5'b11111;
|
||||
|
||||
bitarray[2][0] = 5'b11111;
|
||||
bitarray[2][1] = 5'b00001;
|
||||
bitarray[2][2] = 5'b11111;
|
||||
bitarray[2][3] = 5'b10000;
|
||||
bitarray[2][4] = 5'b11111;
|
||||
|
||||
bitarray[3][0] = 5'b11111;
|
||||
bitarray[3][1] = 5'b00001;
|
||||
bitarray[3][2] = 5'b11111;
|
||||
bitarray[3][3] = 5'b00001;
|
||||
bitarray[3][4] = 5'b11111;
|
||||
|
||||
bitarray[4][0] = 5'b10001;
|
||||
bitarray[4][1] = 5'b10001;
|
||||
bitarray[4][2] = 5'b11111;
|
||||
bitarray[4][3] = 5'b00001;
|
||||
bitarray[4][4] = 5'b00001;
|
||||
|
||||
bitarray[5][0] = 5'b11111;
|
||||
bitarray[5][1] = 5'b10000;
|
||||
bitarray[5][2] = 5'b11111;
|
||||
bitarray[5][3] = 5'b00001;
|
||||
bitarray[5][4] = 5'b11111;
|
||||
|
||||
bitarray[6][0] = 5'b11111;
|
||||
bitarray[6][1] = 5'b10000;
|
||||
bitarray[6][2] = 5'b11111;
|
||||
bitarray[6][3] = 5'b10001;
|
||||
bitarray[6][4] = 5'b11111;
|
||||
|
||||
bitarray[7][0] = 5'b11111;
|
||||
bitarray[7][1] = 5'b00001;
|
||||
bitarray[7][2] = 5'b00001;
|
||||
bitarray[7][3] = 5'b00001;
|
||||
bitarray[7][4] = 5'b00001;
|
||||
|
||||
bitarray[8][0] = 5'b11111;
|
||||
bitarray[8][1] = 5'b10001;
|
||||
bitarray[8][2] = 5'b11111;
|
||||
bitarray[8][3] = 5'b10001;
|
||||
bitarray[8][4] = 5'b11111;
|
||||
|
||||
bitarray[9][0] = 5'b11111;
|
||||
bitarray[9][1] = 5'b10001;
|
||||
bitarray[9][2] = 5'b11111;
|
||||
bitarray[9][3] = 5'b00001;
|
||||
bitarray[9][4] = 5'b11111;
|
||||
|
||||
// clear unused array entries
|
||||
for (i = 10; i <= 15; i++)
|
||||
for (j = 0; j <= 4; j++)
|
||||
bitarray[i][j] = 0;
|
||||
end
|
||||
endmodule
|
||||
|
||||
// test module
|
||||
module test_numbers_top(clk, reset, hsync, vsync, rgb);
|
||||
|
||||
input clk, reset;
|
||||
output hsync, vsync;
|
||||
output [2:0] rgb;
|
||||
|
||||
wire display_on;
|
||||
wire [8:0] hpos;
|
||||
wire [8:0] vpos;
|
||||
|
||||
hvsync_generator hvsync_gen(
|
||||
.clk(clk),
|
||||
.reset(reset),
|
||||
.hsync(hsync),
|
||||
.vsync(vsync),
|
||||
.display_on(display_on),
|
||||
.hpos(hpos),
|
||||
.vpos(vpos)
|
||||
);
|
||||
|
||||
wire [3:0] digit = hpos[7:4];
|
||||
wire [2:0] xofs = hpos[3:1];
|
||||
wire [2:0] yofs = vpos[3:1];
|
||||
wire [4:0] bits;
|
||||
|
||||
digits10_array numbers(
|
||||
.digit(digit),
|
||||
.yofs(yofs),
|
||||
.bits(bits)
|
||||
);
|
||||
|
||||
wire r = display_on && 0;
|
||||
wire g = display_on && bits[xofs ^ 3'b111];
|
||||
wire b = display_on && 0;
|
||||
assign rgb = {b,g,r};
|
||||
|
||||
endmodule
|
||||
|
||||
`endif
|
@ -3,7 +3,8 @@
|
||||
`define HVSYNC_GENERATOR_H
|
||||
|
||||
/*
|
||||
Video sync generator, used to drive a simulated CRT.
|
||||
Video sync generator, used to drive a VGA monitor.
|
||||
Timing from: https://en.wikipedia.org/wiki/Video_Graphics_Array
|
||||
To use:
|
||||
- Wire the hsync and vsync signals to top level outputs
|
||||
- Add a 3-bit (or more) "rgb" output to the top level
|
||||
@ -15,20 +16,20 @@ module hvsync_generator(clk, reset, hsync, vsync, display_on, hpos, vpos);
|
||||
input reset;
|
||||
output reg hsync, vsync;
|
||||
output display_on;
|
||||
output reg [8:0] hpos;
|
||||
output reg [8:0] vpos;
|
||||
output reg [9:0] hpos;
|
||||
output reg [9:0] vpos;
|
||||
|
||||
// declarations for TV-simulator sync parameters
|
||||
// horizontal constants
|
||||
parameter H_DISPLAY = 256; // horizontal display width
|
||||
parameter H_BACK = 23; // horizontal left border (back porch)
|
||||
parameter H_FRONT = 7; // horizontal right border (front porch)
|
||||
parameter H_SYNC = 23; // horizontal sync width
|
||||
parameter H_DISPLAY = 640; // horizontal display width
|
||||
parameter H_BACK = 48; // horizontal left border (back porch)
|
||||
parameter H_FRONT = 16; // horizontal right border (front porch)
|
||||
parameter H_SYNC = 96; // horizontal sync width
|
||||
// vertical constants
|
||||
parameter V_DISPLAY = 240; // vertical display height
|
||||
parameter V_TOP = 5; // vertical top border
|
||||
parameter V_BOTTOM = 14; // vertical bottom border
|
||||
parameter V_SYNC = 3; // vertical sync # lines
|
||||
parameter V_DISPLAY = 480; // vertical display height
|
||||
parameter V_TOP = 33; // vertical top border
|
||||
parameter V_BOTTOM = 10; // vertical bottom border
|
||||
parameter V_SYNC = 2; // vertical sync # lines
|
||||
// derived constants
|
||||
parameter H_SYNC_START = H_DISPLAY + H_FRONT;
|
||||
parameter H_SYNC_END = H_DISPLAY + H_FRONT + H_SYNC - 1;
|
||||
|
114
presets/verilog-vga/scoreboard.v
Normal file
114
presets/verilog-vga/scoreboard.v
Normal file
@ -0,0 +1,114 @@
|
||||
|
||||
`ifndef SCOREBOARD_H
|
||||
`define SCOREBOARD_H
|
||||
|
||||
`include "hvsync_generator.v"
|
||||
`include "digits10.v"
|
||||
|
||||
/*
|
||||
player_stats - Holds two-digit score and one-digit lives counter.
|
||||
scoreboard_generator - Outputs video signal with score/lives digits.
|
||||
*/
|
||||
|
||||
module player_stats(reset, score0, score1, lives, incscore, declives);
|
||||
|
||||
input reset;
|
||||
output reg [3:0] score0;
|
||||
output reg [3:0] score1;
|
||||
input incscore;
|
||||
output reg [3:0] lives;
|
||||
input declives;
|
||||
|
||||
always @(posedge incscore or posedge reset)
|
||||
begin
|
||||
if (reset) begin
|
||||
score0 <= 0;
|
||||
score1 <= 0;
|
||||
end else if (score0 == 9) begin
|
||||
score0 <= 0;
|
||||
score1 <= score1 + 1;
|
||||
end else begin
|
||||
score0 <= score0 + 1;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge declives or posedge reset)
|
||||
begin
|
||||
if (reset)
|
||||
lives <= 3;
|
||||
else if (lives != 0)
|
||||
lives <= lives - 1;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
module scoreboard_generator(score0, score1, lives, vpos, hpos, board_gfx);
|
||||
|
||||
input [3:0] score0;
|
||||
input [3:0] score1;
|
||||
input [3:0] lives;
|
||||
input [9:0] vpos;
|
||||
input [9:0] hpos;
|
||||
output board_gfx;
|
||||
|
||||
reg [3:0] score_digit;
|
||||
reg [4:0] score_bits;
|
||||
|
||||
always @(*)
|
||||
begin
|
||||
case (hpos[8:6])
|
||||
1: score_digit = score1;
|
||||
2: score_digit = score0;
|
||||
6: score_digit = lives;
|
||||
default: score_digit = 15; // no digit
|
||||
endcase
|
||||
end
|
||||
|
||||
digits10_array digits(
|
||||
.digit(score_digit),
|
||||
.yofs(vpos[5:3]),
|
||||
.bits(score_bits)
|
||||
);
|
||||
|
||||
assign board_gfx = score_bits[hpos[5:3] ^ 3'b111];
|
||||
|
||||
endmodule
|
||||
|
||||
module scoreboard_top(clk, reset, hsync, vsync, rgb);
|
||||
|
||||
input clk, reset;
|
||||
output hsync, vsync;
|
||||
output [2:0] rgb;
|
||||
wire display_on;
|
||||
wire [9:0] hpos;
|
||||
wire [9:0] vpos;
|
||||
|
||||
wire board_gfx;
|
||||
|
||||
hvsync_generator hvsync_gen(
|
||||
.clk(clk),
|
||||
.reset(reset),
|
||||
.hsync(hsync),
|
||||
.vsync(vsync),
|
||||
.display_on(display_on),
|
||||
.hpos(hpos),
|
||||
.vpos(vpos)
|
||||
);
|
||||
|
||||
scoreboard_generator scoreboard_gen(
|
||||
.score0(0),
|
||||
.score1(1),
|
||||
.lives(3),
|
||||
.vpos(vpos),
|
||||
.hpos(hpos),
|
||||
.board_gfx(board_gfx)
|
||||
);
|
||||
|
||||
wire r = display_on && board_gfx;
|
||||
wire g = display_on && board_gfx;
|
||||
wire b = display_on && board_gfx;
|
||||
assign rgb = {b,g,r};
|
||||
|
||||
endmodule
|
||||
|
||||
`endif
|
42
presets/verilog-vga/starfield.v
Normal file
42
presets/verilog-vga/starfield.v
Normal file
@ -0,0 +1,42 @@
|
||||
|
||||
`include "hvsync_generator.v"
|
||||
`include "lfsr.v"
|
||||
|
||||
/*
|
||||
Scrolling starfield generator using a period (2^16-1) LFSR.
|
||||
*/
|
||||
|
||||
module starfield_top(clk, reset, hsync, vsync, rgb);
|
||||
|
||||
input clk, reset;
|
||||
output hsync, vsync;
|
||||
output [2:0] rgb;
|
||||
wire display_on;
|
||||
wire [9:0] hpos;
|
||||
wire [9:0] vpos;
|
||||
wire [15:0] lfsr;
|
||||
|
||||
hvsync_generator hvsync_gen(
|
||||
.clk(clk),
|
||||
.reset(reset),
|
||||
.hsync(hsync),
|
||||
.vsync(vsync),
|
||||
.display_on(display_on),
|
||||
.hpos(hpos),
|
||||
.vpos(vpos)
|
||||
);
|
||||
|
||||
// enable LFSR only in 512x512 area
|
||||
wire star_enable = !hpos[9] & !vpos[9];
|
||||
|
||||
// LFSR with period = 2^16-1 = 256*256-1
|
||||
LFSR #(16'b1000000001011,0) lfsr_gen(
|
||||
.clk(clk),
|
||||
.reset(reset),
|
||||
.enable(star_enable),
|
||||
.lfsr(lfsr));
|
||||
|
||||
wire star_on = &lfsr[15:9]; // all 7 bits must be set
|
||||
assign rgb = display_on && star_on ? lfsr[2:0] : 0;
|
||||
|
||||
endmodule
|
@ -11,8 +11,8 @@ module test_hvsync_top(clk, reset, hsync, vsync, rgb);
|
||||
output hsync, vsync;
|
||||
output [2:0] rgb;
|
||||
wire display_on;
|
||||
wire [8:0] hpos;
|
||||
wire [8:0] vpos;
|
||||
wire [9:0] hpos;
|
||||
wire [9:0] vpos;
|
||||
|
||||
hvsync_generator hvsync_gen(
|
||||
.clk(clk),
|
||||
|
@ -761,6 +761,9 @@ var VerilogPlatform = function(mainElement, options) {
|
||||
var VERILOG_VGA_PRESETS = [
|
||||
{id:'hvsync_generator.v', name:'Video Sync Generator'},
|
||||
{id:'test_hvsync.v', name:'Test Pattern'},
|
||||
{id:'chardisplay.v', name:'RAM Text Display'},
|
||||
{id:'starfield.v', name:'Scrolling Starfield'},
|
||||
{id:'ball_paddle.v', name:'Brick Smash Game'},
|
||||
];
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user