All checks were successful
ci/woodpecker/push/test-workflow Pipeline was successful
The audio output is still messed up, but this commit gets everything as ready as it can get. Fixed up all the testbenches and added state machines for everything
154 lines
4.0 KiB
Systemverilog
154 lines
4.0 KiB
Systemverilog
/***
|
|
* 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;
|
|
// Actually 200khz now
|
|
modular_clock_gen #(500) slowSdClock(CLK100MHZ, reset, clk_100khz);
|
|
// Try clocking this slower than max speed
|
|
// To see if that makes it actually work ...
|
|
// If these are different speeds bad things happen :) oops
|
|
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
|