/src/project.v
/* * Copyright (c) 2024 Chip Black * SPDX-License-Identifier: Apache-2.0 */ `default_nettype none module clock_generator( input wire clk, // 25.175MHz main clock input wire rst_n, // active low reset output wire [5:0] pwm_clock, // 393kHz PWM clock (main / 64) input wire vsync, // ~60Hz video clock output wire [1:0] atick_clock, // audio tick clock state, used for volume modulation output wire [3:0] pattern_clock // pattern clock, increments with audio_tick ); reg [5:0] r_pwm_clock; reg [2:0] r_atick_clock; reg [3:0] r_pattern_clock; always @(posedge clk, negedge rst_n) begin if (!rst_n) r_pwm_clock <= 0; else r_pwm_clock <= r_pwm_clock + 1; end assign pwm_clock = r_pwm_clock; always @(posedge vsync, negedge rst_n) begin if (!rst_n) r_atick_clock <= 0; else begin // Divide vsync by 6 to get 10Hz sequencer clock // 10Hz = 600 ticks per minute // four ticks per beat // 150 BPM if (r_atick_clock == 5) r_atick_clock <= 0; else r_atick_clock <= r_atick_clock + 1; end end assign atick_clock = r_atick_clock[2:1]; wire audio_tick = (r_atick_clock == 0); always @(posedge audio_tick, negedge rst_n) begin if (!rst_n) r_pattern_clock <= 0; else r_pattern_clock <= r_pattern_clock + 1; end assign pattern_clock = r_pattern_clock; endmodule module tt_um_bytex64_munch ( input wire [7:0] ui_in, // Dedicated inputs output wire [7:0] uo_out, // Dedicated outputs input wire [7:0] uio_in, // IOs: Input path output wire [7:0] uio_out, // IOs: Output path output wire [7:0] uio_oe, // IOs: Enable path (active high: 0=input, 1=output) input wire ena, // always 1 when the design is powered, so you can ignore it input wire clk, // clock input wire rst_n // reset_n - low to reset ); // Video timing/output signals wire [9:0] hpos; wire [9:0] vpos; wire hsync, vsync; wire display_on; wire [1:0] R; wire [1:0] G; wire [1:0] B; // Video generation signals wire [5:0] layer [1:0]; wire [5:0] pixel_color; wire [2:0] dither; wire [1:0] bright [7:0]; // 8 2-bit brightness levels wire [5:0] palette [7:0]; // 8 6-bit colors wire [2:0] munch_level; // brightness output for munch module wire text_pixel; // on/off output for text module // Audio signals wire audio; // Audio output (~200kHz PWM) wire [5:0] pwm_clock; wire [1:0] atick_clock; wire [3:0] pattern_clock; // Misc signals wire [5:0] lfsr; wire [1:0] stage; wire [3:0] stage_timer; // State reg [6:0] counter; // general 7-bit counter clock_generator clock_gen( .clk(clk), .rst_n(rst_n), .pwm_clock(pwm_clock), .vsync(vsync), .atick_clock(atick_clock), .pattern_clock(pattern_clock) ); lfsr lfsr_dev( .clk(clk), .rst_n(rst_n), .bits(lfsr) ); audio audio_mod( .pwm_clock(pwm_clock), .atick_clock(atick_clock), .pattern_clock(pattern_clock), .rst_n(rst_n), .rng(lfsr[0]), .audio(audio) ); hvsync_generator hvsync_gen( .clk(clk), .reset(!rst_n), .hsync(hsync), .vsync(vsync), .display_on(display_on), .hpos(hpos), .vpos(vpos) ); assign palette[0] = 6'b000000; assign palette[1] = 6'b110000; assign palette[2] = 6'b001100; assign palette[3] = 6'b000011; assign palette[4] = 6'b001111; assign palette[5] = 6'b110011; assign palette[6] = 6'b111100; assign palette[7] = 6'b111111; assign dither[0] = lfsr[4] & lfsr[5]; // 1/4 assign dither[1] = lfsr[3]; // 1/2 assign dither[2] = lfsr[1] | lfsr[2]; // 3/4 /* assign dither[0] = hpos[0] & vpos[0]; assign dither[1] = hpos[0] ^ vpos[0]; assign dither[2] = hpos[0] | vpos[0]; */ assign bright[0] = 2'b00; assign bright[1] = {1'b0, dither[0]}; assign bright[2] = {1'b0, dither[1]}; assign bright[3] = {1'b0, dither[2]}; assign bright[4] = 2'b01; assign bright[5] = {dither[0], dither[2]}; assign bright[6] = 2'b10; assign bright[7] = 2'b11; munch munch_gen( .counter(counter), .hpos(hpos[8:2]), .vpos(vpos[8:2]), .level(munch_level) ); text_sequencer text_gen( .selector(pattern_clock[3:2]), .hpos(hpos), .vpos(vpos), .stage(stage), .stage_timer(stage_timer), .pixel(text_pixel) ); stage_sequencer stage_seq_inst( .seq_clk(!pattern_clock[3]), .rst_n(rst_n), .stage(stage), .stage_timer(stage_timer) ); reg [2:0] background_color; wire [2:0] munch_color = stage == 0 ? 0 : (stage != 3 ? 2 : ~background_color); wire [5:0] text_color = stage == 1 && pattern_clock[3:2] != 2'b10 ? palette[0] : (stage == 3 && pattern_clock[3:2] == 2'b10 ? palette[5] & {3{bright[5]}} : palette[7]); assign layer[0] = palette[munch_color] & {3{bright[munch_level]}}; // color bars //assign layer[0] = palette[vpos[6:4]] & {3{bright[hpos[6:4]]}}; assign layer[1] = text_pixel ? text_color : 0; assign pixel_color = layer[1] != 0 ? layer[1] : (layer[0] != 0 ? layer[0] : palette[background_color]); always @(negedge pattern_clock[1], negedge rst_n) begin if (!rst_n) background_color <= 0; else if (stage == 3) background_color <= lfsr[2:0]; end always @(posedge vsync, negedge rst_n) begin if (!rst_n) counter <= 0; else counter <= counter + 1; end assign R = display_on ? pixel_color[5:4] : 2'b00; assign G = display_on ? pixel_color[3:2] : 2'b00; assign B = display_on ? pixel_color[1:0] : 2'b00; assign uo_out = {!hsync, B[0], G[0], R[0], !vsync, B[1], G[1], R[1]}; assign uio_out = {audio, pattern_clock[3:1], 4'b0}; assign uio_oe = 8'b11110000; // List all unused inputs to prevent warnings wire _unused = &{ena, ui_in, uio_in, 1'b0}; endmodule module lfsr( input wire clk, input wire rst_n, output wire [5:0] bits ); reg [10:0] lfsr; // LFSR always @(posedge clk, negedge rst_n) begin if (!rst_n) lfsr <= 11'h0; else lfsr <= {lfsr[0] ~^ lfsr[2], lfsr[10:1]}; end assign bits = lfsr[5:0]; endmodule module stage_sequencer( input wire seq_clk, input wire rst_n, output wire [1:0] stage, output wire [3:0] stage_timer ); reg [3:0] timer; reg [1:0] stage_seq; wire [3:0] stage_timings [3:0]; assign stage_timings[0] = 3; assign stage_timings[1] = 3; assign stage_timings[2] = 7; assign stage_timings[3] = 0; always @(posedge seq_clk, negedge rst_n) begin if (!rst_n) begin stage_seq <= 0; timer <= stage_timings[0]; end else begin if (stage_timings[stage_seq] != 0) begin if (timer == 0) begin stage_seq <= stage_seq + 1; timer <= stage_timings[stage_seq + 1]; end else timer <= timer - 1; end end end assign stage = stage_seq; assign stage_timer = timer; endmodule