-
-
Notifications
You must be signed in to change notification settings - Fork 51
/
top_colour_cycle.sv
91 lines (80 loc) · 2.97 KB
/
top_colour_cycle.sv
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
// Project F: Racing the Beam - Colour Cycle (Arty Pmod VGA)
// (C)2023 Will Green, open source hardware released under the MIT License
// Learn more at https://projectf.io/posts/racing-the-beam/
`default_nettype none
`timescale 1ns / 1ps
module top_colour_cycle (
input wire logic clk_100m, // 100 MHz clock
input wire logic btn_rst_n, // reset button
output logic vga_hsync, // VGA horizontal sync
output logic vga_vsync, // VGA vertical sync
output logic [3:0] vga_r, // 4-bit VGA red
output logic [3:0] vga_g, // 4-bit VGA green
output logic [3:0] vga_b // 4-bit VGA blue
);
// generate pixel clock
logic clk_pix;
logic clk_pix_locked;
clock_480p clock_pix_inst (
.clk_100m,
.rst(!btn_rst_n), // reset button is active low
.clk_pix,
/* verilator lint_off PINCONNECTEMPTY */
.clk_pix_5x(), // not used for VGA output
/* verilator lint_on PINCONNECTEMPTY */
.clk_pix_locked
);
// display sync signals and coordinates
localparam CORDW = 10; // screen coordinate width in bits
/* verilator lint_off UNUSED */
logic [CORDW-1:0] sx, sy;
/* verilator lint_on UNUSED */
logic hsync, vsync, de;
simple_480p display_inst (
.clk_pix,
.rst_pix(!clk_pix_locked), // wait for clock lock
.sx,
.sy,
.hsync,
.vsync,
.de
);
// screen dimensions (must match display_inst)
localparam V_RES = 480; // vertical screen resolution
logic frame; // high for one clock tick at the start of vertical blanking
always_comb frame = (sy == V_RES && sx == 0);
// update the colour level every N frames
localparam FRAME_NUM = 30; // frames between colour level change
logic [$clog2(FRAME_NUM):0] cnt_frame; // frame counter
logic [3:0] colr_level; // level of colour being cycled
always_ff @(posedge clk_pix) begin
if (frame) begin
if (cnt_frame == FRAME_NUM-1) begin // every FRAME_NUM frames
cnt_frame <= 0;
colr_level <= colr_level + 1;
end else cnt_frame <= cnt_frame + 1;
end
end
// paint colour: based on screen position
logic [3:0] paint_r, paint_g, paint_b;
always_comb begin
paint_r = sx[7:4]; // 16 horizontal pixels of each red level
paint_g = sy[7:4]; // 16 vertical pixels of each green level
paint_b = colr_level; // blue level changes over time
end
// display colour: paint colour but black in blanking interval
logic [3:0] display_r, display_g, display_b;
always_comb begin
display_r = (de) ? paint_r : 4'h0;
display_g = (de) ? paint_g : 4'h0;
display_b = (de) ? paint_b : 4'h0;
end
// VGA Pmod output
always_ff @(posedge clk_pix) begin
vga_hsync <= hsync;
vga_vsync <= vsync;
vga_r <= display_r;
vga_g <= display_g;
vga_b <= display_b;
end
endmodule