/*** * nexys_a7_top.sv - top level design module specific to Nexys A7100T. * * @author: Waylon Cude, Dilanthi Prentice * @date: 6/12/2025 * * **/ `ifdef VERILATOR `include "sdvd_defs.sv" `endif import sdvd_defs::SPEED; module nexys_a7_top( input logic CLK100MHZ, CPU_RESETN, input logic BTNC, BTNR, output logic AUD_PWM, AUD_SD, output logic CA,CB,CC,CD,CE,CF,CG, output logic [7:0] AN, output wire LED[0:0], output wire SD_RESET,SD_SCK, inout wire [3:0] SD_DAT, inout wire SD_CMD, input wire SD_CD ); // Active high reset wire reset; assign reset = ~CPU_RESETN; logic clk_1khz, clk_10hz; logic clk_48khz, clk_1mhz; logic seconds_pulse; SPEED speed; audio_buffer_interface audio_interface(); // Map C{A-G} to an array of 7-segment displays wire [6:0] segments [7:0]; wire [2:0] segment_mux_select; // These segments are currently unused assign segments[7] = 0; assign segments[6] = 0; // These are the ones we're using assign {CA,CB,CC,CD,CE,CF,CG} = ~segments[segment_mux_select]; logic [$clog2(60)-1:0] seconds; logic [$clog2(60)-1:0] minutes; logic [$clog2(60)-1:0] hours; logic [15:0] audio_sample; logic sd_ready; logic playing; assign LED[0] = playing; assign AUD_SD = playing; low_freq_clock_gen clockGen(CLK100MHZ, reset, speed, 'z, clk_10hz, seconds_pulse); modular_clock_gen #(100_000) anodeClock(CLK100MHZ, reset, clk_1khz); // Create a clock with a divisor of 2083, making ~48khz modular_clock_gen #(2083) audioClock(CLK100MHZ, reset, clk_48khz); modular_clock_gen #(100) pwmClock(CLK100MHZ, reset, clk_1mhz); // Count the number on seconds, hours, and minutes elapsed // If the speed is faster this will pulse more often than once a second // but will still theoretically be a second of video time always_ff @(posedge seconds_pulse or posedge reset) begin if (reset) begin seconds <= 0; minutes <= 0; hours <= 0; end else if (seconds == 59) begin seconds <= 0; if (minutes == 59) begin minutes <= 0; hours <= hours + 1; end else minutes <= minutes + 1; end else seconds <= seconds + 1; end display_anode_driver anodeDriver(clk_1khz,reset,AN,segment_mux_select); sixty_display secondsSegment (seconds, segments[1], segments[0]); sixty_display minutesSegment (minutes, segments[3], segments[2]); sixty_display hoursSegment (hours, segments[5], segments[4]); // Run the playback speed state machine at a lower rate // Gets rid of button bouncing playback_controller playbackController (clk_10hz,reset,BTNC, BTNR, speed); `ifdef ROM rom_sd #("even_flow_16.mem") romSdPlayer(clk_1mhz,reset,sd_ready,audio_interface.driver); assign {SD_RESET,SD_DAT,SD_CMD,SD_SCK} = 'z; audio_buffer audioBuffer( clk_48khz, reset, sd_ready, '0, // stop signal not used right now speed, playing, audio_sample, audio_interface.receiver ); pwm audioOutput(CLK100MHZ, reset, clk_48khz, audio_sample, AUD_PWM); `else // Power the sd slot assign SD_RESET = 0; // We don't use more than one dat line logic clk_100khz; logic clk_25mhz; // We can clock this at around 200khz before things start breaking // Even at 200khz sometimes things break modular_clock_gen #(500) slowSdClock(CLK100MHZ, reset, clk_100khz); // Try clocking this slower than max speed // To see if that makes it actually work // // NOTE: It did not make it work modular_clock_gen #(400) fastSdClock(CLK100MHZ, reset, clk_25mhz); sd_controller realSdPlayer( clk_100khz, clk_25mhz, CLK100MHZ, reset, SD_DAT, SD_CMD, sd_ready, SD_SCK, audio_interface.driver ); audio_buffer #(.SIZE(8)) audioBuffer( clk_48khz, reset, sd_ready, '0, // stop signal not used right now speed, playing, audio_sample, audio_interface.receiver ); pwm #(8) audioOutput(CLK100MHZ, reset, clk_48khz, audio_sample, AUD_PWM); `endif endmodule