SDVD/design/nexys_a7_top.sv
Waylon Cude fe227d1b61
All checks were successful
ci/woodpecker/push/test-workflow Pipeline was successful
Broken SD card
How tf did it break bro
2025-06-09 15:41:13 -07:00

143 lines
3.7 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);
seconds_display secondsSegment (seconds, segments[1], segments[0]);
seconds_display minutesSegment (minutes, segments[3], segments[2]);
seconds_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);
pwm audioOutput(CLK100MHZ, reset, clk_48khz, audio_sample, AUD_PWM);
audio_buffer audioBuffer(
clk_48khz,
reset,
sd_ready,
'0, // stop signal not used right now
speed,
playing,
audio_sample,
audio_interface.receiver
);
`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;
`else
// Power the sd slot
assign SD_RESET = 0;
// We don't use more than one dat line
assign SD_DAT[3:1] = 'z;
logic clk_100khz;
logic clk_25mhz;
// Actually 200khz now
// 200khz is slightly unstable??????
modular_clock_gen #(1000) slowSdClock(CLK100MHZ, reset, clk_100khz);
// Try clocking this slower than max speed
// To see if that makes it actually work ...
modular_clock_gen #(1000) fastSdClock(CLK100MHZ, reset, clk_25mhz);
sd_controller realSdPlayer(
clk_100khz,
clk_25mhz,
CLK100MHZ,
reset,
SD_DAT[0],
SD_CMD,
sd_ready,
SD_SCK,
audio_interface.driver
);
`endif
endmodule