diff --git a/Nexys-A7-100T-Master.xdc b/Nexys-A7-100T-Master.xdc
index afd0916..5003bed 100644
--- a/Nexys-A7-100T-Master.xdc
+++ b/Nexys-A7-100T-Master.xdc
@@ -5,8 +5,8 @@
## Note: As the Nexys 4 DDR was rebranded to the Nexys A7 with no substantial changes, this XDC file will also work for the Nexys 4 DDR.
## Clock signal
-#set_property -dict { PACKAGE_PIN E3 IOSTANDARD LVCMOS33 } [get_ports { CLK100MHZ }]; #IO_L12P_T1_MRCC_35 Sch=clk100mhz
-#create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports {CLK100MHZ}];
+set_property -dict { PACKAGE_PIN E3 IOSTANDARD LVCMOS33 } [get_ports { CLK100MHZ }]; #IO_L12P_T1_MRCC_35 Sch=clk100mhz
+create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports {CLK100MHZ}];
##Switches
@@ -54,31 +54,31 @@
#set_property -dict { PACKAGE_PIN N16 IOSTANDARD LVCMOS33 } [get_ports { LED17_R }]; #IO_L11N_T1_SRCC_14 Sch=led17_r
##7 segment display
-#set_property -dict { PACKAGE_PIN T10 IOSTANDARD LVCMOS33 } [get_ports { CA }]; #IO_L24N_T3_A00_D16_14 Sch=ca
-#set_property -dict { PACKAGE_PIN R10 IOSTANDARD LVCMOS33 } [get_ports { CB }]; #IO_25_14 Sch=cb
-#set_property -dict { PACKAGE_PIN K16 IOSTANDARD LVCMOS33 } [get_ports { CC }]; #IO_25_15 Sch=cc
-#set_property -dict { PACKAGE_PIN K13 IOSTANDARD LVCMOS33 } [get_ports { CD }]; #IO_L17P_T2_A26_15 Sch=cd
-#set_property -dict { PACKAGE_PIN P15 IOSTANDARD LVCMOS33 } [get_ports { CE }]; #IO_L13P_T2_MRCC_14 Sch=ce
-#set_property -dict { PACKAGE_PIN T11 IOSTANDARD LVCMOS33 } [get_ports { CF }]; #IO_L19P_T3_A10_D26_14 Sch=cf
-#set_property -dict { PACKAGE_PIN L18 IOSTANDARD LVCMOS33 } [get_ports { CG }]; #IO_L4P_T0_D04_14 Sch=cg
+set_property -dict { PACKAGE_PIN T10 IOSTANDARD LVCMOS33 } [get_ports { CA }]; #IO_L24N_T3_A00_D16_14 Sch=ca
+set_property -dict { PACKAGE_PIN R10 IOSTANDARD LVCMOS33 } [get_ports { CB }]; #IO_25_14 Sch=cb
+set_property -dict { PACKAGE_PIN K16 IOSTANDARD LVCMOS33 } [get_ports { CC }]; #IO_25_15 Sch=cc
+set_property -dict { PACKAGE_PIN K13 IOSTANDARD LVCMOS33 } [get_ports { CD }]; #IO_L17P_T2_A26_15 Sch=cd
+set_property -dict { PACKAGE_PIN P15 IOSTANDARD LVCMOS33 } [get_ports { CE }]; #IO_L13P_T2_MRCC_14 Sch=ce
+set_property -dict { PACKAGE_PIN T11 IOSTANDARD LVCMOS33 } [get_ports { CF }]; #IO_L19P_T3_A10_D26_14 Sch=cf
+set_property -dict { PACKAGE_PIN L18 IOSTANDARD LVCMOS33 } [get_ports { CG }]; #IO_L4P_T0_D04_14 Sch=cg
#set_property -dict { PACKAGE_PIN H15 IOSTANDARD LVCMOS33 } [get_ports { DP }]; #IO_L19N_T3_A21_VREF_15 Sch=dp
-#set_property -dict { PACKAGE_PIN J17 IOSTANDARD LVCMOS33 } [get_ports { AN[0] }]; #IO_L23P_T3_FOE_B_15 Sch=an[0]
-#set_property -dict { PACKAGE_PIN J18 IOSTANDARD LVCMOS33 } [get_ports { AN[1] }]; #IO_L23N_T3_FWE_B_15 Sch=an[1]
-#set_property -dict { PACKAGE_PIN T9 IOSTANDARD LVCMOS33 } [get_ports { AN[2] }]; #IO_L24P_T3_A01_D17_14 Sch=an[2]
-#set_property -dict { PACKAGE_PIN J14 IOSTANDARD LVCMOS33 } [get_ports { AN[3] }]; #IO_L19P_T3_A22_15 Sch=an[3]
-#set_property -dict { PACKAGE_PIN P14 IOSTANDARD LVCMOS33 } [get_ports { AN[4] }]; #IO_L8N_T1_D12_14 Sch=an[4]
-#set_property -dict { PACKAGE_PIN T14 IOSTANDARD LVCMOS33 } [get_ports { AN[5] }]; #IO_L14P_T2_SRCC_14 Sch=an[5]
-#set_property -dict { PACKAGE_PIN K2 IOSTANDARD LVCMOS33 } [get_ports { AN[6] }]; #IO_L23P_T3_35 Sch=an[6]
-#set_property -dict { PACKAGE_PIN U13 IOSTANDARD LVCMOS33 } [get_ports { AN[7] }]; #IO_L23N_T3_A02_D18_14 Sch=an[7]
+set_property -dict { PACKAGE_PIN J17 IOSTANDARD LVCMOS33 } [get_ports { AN[0] }]; #IO_L23P_T3_FOE_B_15 Sch=an[0]
+set_property -dict { PACKAGE_PIN J18 IOSTANDARD LVCMOS33 } [get_ports { AN[1] }]; #IO_L23N_T3_FWE_B_15 Sch=an[1]
+set_property -dict { PACKAGE_PIN T9 IOSTANDARD LVCMOS33 } [get_ports { AN[2] }]; #IO_L24P_T3_A01_D17_14 Sch=an[2]
+set_property -dict { PACKAGE_PIN J14 IOSTANDARD LVCMOS33 } [get_ports { AN[3] }]; #IO_L19P_T3_A22_15 Sch=an[3]
+set_property -dict { PACKAGE_PIN P14 IOSTANDARD LVCMOS33 } [get_ports { AN[4] }]; #IO_L8N_T1_D12_14 Sch=an[4]
+set_property -dict { PACKAGE_PIN T14 IOSTANDARD LVCMOS33 } [get_ports { AN[5] }]; #IO_L14P_T2_SRCC_14 Sch=an[5]
+set_property -dict { PACKAGE_PIN K2 IOSTANDARD LVCMOS33 } [get_ports { AN[6] }]; #IO_L23P_T3_35 Sch=an[6]
+set_property -dict { PACKAGE_PIN U13 IOSTANDARD LVCMOS33 } [get_ports { AN[7] }]; #IO_L23N_T3_A02_D18_14 Sch=an[7]
##CPU Reset Button
-#set_property -dict { PACKAGE_PIN C12 IOSTANDARD LVCMOS33 } [get_ports { CPU_RESETN }]; #IO_L3P_T0_DQS_AD1P_15 Sch=cpu_resetn
+set_property -dict { PACKAGE_PIN C12 IOSTANDARD LVCMOS33 } [get_ports { CPU_RESETN }]; #IO_L3P_T0_DQS_AD1P_15 Sch=cpu_resetn
##Buttons
-#set_property -dict { PACKAGE_PIN N17 IOSTANDARD LVCMOS33 } [get_ports { BTNC }]; #IO_L9P_T1_DQS_14 Sch=btnc
+set_property -dict { PACKAGE_PIN N17 IOSTANDARD LVCMOS33 } [get_ports { BTNC }]; #IO_L9P_T1_DQS_14 Sch=btnc
#set_property -dict { PACKAGE_PIN M18 IOSTANDARD LVCMOS33 } [get_ports { BTNU }]; #IO_L4N_T0_D05_14 Sch=btnu
#set_property -dict { PACKAGE_PIN P17 IOSTANDARD LVCMOS33 } [get_ports { BTNL }]; #IO_L12P_T1_MRCC_14 Sch=btnl
-#set_property -dict { PACKAGE_PIN M17 IOSTANDARD LVCMOS33 } [get_ports { BTNR }]; #IO_L10N_T1_D15_14 Sch=btnr
+set_property -dict { PACKAGE_PIN M17 IOSTANDARD LVCMOS33 } [get_ports { BTNR }]; #IO_L10N_T1_D15_14 Sch=btnr
#set_property -dict { PACKAGE_PIN P18 IOSTANDARD LVCMOS33 } [get_ports { BTND }]; #IO_L9N_T1_DQS_D13_14 Sch=btnd
diff --git a/SDVD.xpr b/SDVD.xpr
index 0573c12..b371300 100644
--- a/SDVD.xpr
+++ b/SDVD.xpr
@@ -48,6 +48,7 @@
+
@@ -98,6 +99,13 @@
+
+
+
+
+
+
+
@@ -107,7 +115,13 @@
-
+
+
+
+
+
+
+
@@ -115,7 +129,7 @@
-
+
@@ -143,7 +157,7 @@
-
+
diff --git a/design/display_anode_driver.sv b/design/display_anode_driver.sv
new file mode 100644
index 0000000..cb9d790
--- /dev/null
+++ b/design/display_anode_driver.sv
@@ -0,0 +1,11 @@
+// NOTE: This expects to be driven with a 100khz clock
+module display_anode_driver(input logic clk, input logic reset, output logic [7:0] AN);
+
+// This is just a shift register that drives each anode individually
+always_ff @(posedge clk) begin
+ if (reset)
+ AN <= 1;
+ else
+ AN <= {AN[6:0], AN[7]};
+end
+endmodule
diff --git a/design/low_freq_clock_gen.sv b/design/low_freq_clock_gen.sv
new file mode 100644
index 0000000..60b68bc
--- /dev/null
+++ b/design/low_freq_clock_gen.sv
@@ -0,0 +1,45 @@
+`include "sdvd_defs.sv"
+import sdvd_defs::SPEED;
+// Takes in a 100MHz clock and generates the very low freq signals needed
+// for driving the control logic
+module low_freq_clock_gen(
+ input logic clk, reset,
+ input SPEED speed,
+ output logic clk1k, clk10h, seconds_pulse
+);
+
+logic [$clog2(100_000_000):0] counter;
+logic [$clog2(4000):0] seconds_counter;
+logic clk4k;
+
+assign clk1k = (counter % (100_000_000/1000)) != 0;
+assign clk10h = (counter % (100_000_000/10)) != 0;
+assign clk4k = (counter % (100_000_000/4000)) != 0;
+
+always_ff @(posedge clk) begin
+ // NOTE: This generates a pulse on the same clock cycle that reset is
+ // asserted. Is that bad??
+ if (reset)
+ counter <= 0;
+ // Roll the counter over back to zero every second
+ else if (counter == 99_999_999)
+ counter <= 0;
+ else
+ counter <= counter + 1;
+
+ // This logic handles the variable-speed seconds counter
+ if (reset) begin
+ seconds_pulse <= 0;
+ seconds_counter <= 0;
+ end
+ else if (clk4k && seconds_counter >= 4000) begin
+ seconds_counter <= seconds_counter-4000;
+ seconds_pulse <= 1;
+ end
+ else if (clk4k) begin
+ seconds_pulse <= 0;
+ seconds_counter <= seconds_counter + {9'b0, speed};
+ end
+end
+
+endmodule
diff --git a/design/nexys_a7_top.sv b/design/nexys_a7_top.sv
new file mode 100644
index 0000000..b1e70c1
--- /dev/null
+++ b/design/nexys_a7_top.sv
@@ -0,0 +1,67 @@
+`include "sdvd_defs.sv"
+import sdvd_defs::SPEED;
+module nexys_a7_top(
+ input logic CLK100MHZ, CPU_RESETN,
+ input logic BTNC, BTNR,
+ output logic [7:0] CA,CB,CC,CD,CE,CF,CG,
+ output logic [7:0] AN
+);
+
+// Active high reset
+wire reset;
+assign reset = ~CPU_RESETN;
+
+logic clk_1khz, clk_10hz;
+logic seconds_pulse;
+
+SPEED speed;
+
+// Map C{A-G} to an array of 7-segment displays
+wire [6:0] segments [7:0];
+for (genvar i = 0; i<8; i++) begin: segmentGenerate
+ assign {CG[i],CF[i],CE[i],CD[i],CC[i],CB[i],CA[i]} = segments[i];
+end
+
+logic [$clog2(60):0] seconds;
+logic [$clog2(60):0] minutes;
+logic [$clog2(60):0] hours;
+
+low_freq_clock_gen clockGen(CLK100MHZ, reset, speed, clk_1khz, clk_10hz, seconds_pulse);
+
+// 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) 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);
+
+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);
+
+
+
+
+
+endmodule
diff --git a/design/playback_controller.sv b/design/playback_controller.sv
index cda3c60..05a49fe 100644
--- a/design/playback_controller.sv
+++ b/design/playback_controller.sv
@@ -1,4 +1,7 @@
-module Playback_Controller(
+`include "sdvd_defs.sv"
+import sdvd_defs::SPEED;
+
+module playback_controller(
// This clock should be reasonably slow
input logic clk,
input logic reset,
@@ -8,7 +11,7 @@ module Playback_Controller(
input logic ff,
// Output is 0, 1x, 2x, 4x, or 8x
- output wire [3:0] speed
+ output SPEED speed
);
wire play_pulse,ff_pulse;
diff --git a/design/sdvd_defs.sv b/design/sdvd_defs.sv
new file mode 100644
index 0000000..b1c20e3
--- /dev/null
+++ b/design/sdvd_defs.sv
@@ -0,0 +1,7 @@
+`ifndef SDVD_DEFS
+`define SDVD_DEFS
+package sdvd_defs;
+ // Playback speed type
+ typedef logic [3:0] SPEED;
+endpackage
+`endif
diff --git a/verification/seconds_display_tb.sv b/verification/seconds_display_tb.sv
new file mode 100644
index 0000000..1a5e687
--- /dev/null
+++ b/verification/seconds_display_tb.sv
@@ -0,0 +1,51 @@
+module seconds_display_tb;
+int errors = 0;
+logic [5:0] seconds;
+wire [6:0] display_tens;
+wire [6:0] display_ones;
+
+logic [6:0] expected_tens;
+logic [6:0] expected_ones;
+
+seconds_display Dut(.*);
+initial begin
+ $display("Testing seconds_display");
+ for (seconds=0; seconds<60; seconds++) begin
+ expected_ones = encode_number(seconds % 10);
+ expected_tens = encode_number(seconds /10);
+ #1
+ if (display_ones !== expected_ones) begin
+ errors++;
+ $display("Failed ones test case, displayed = %b, expected = %b",
+ display_ones,
+ expected_ones);
+ end
+ else
+ if (display_tens !== expected_tens) begin
+ errors++;
+ $display("Failed tens test case, displayed = %b, expected = %b",
+ display_tens,
+ expected_tens);
+ end
+ end
+
+ if (errors == 0)
+ $display("All tests passing");
+end
+
+endmodule
+
+function automatic logic [6:0] encode_number(logic [5:0] num);
+ case (num)
+ 0: return 7'b1111110;
+ 1: return 7'b0000110;
+ 2: return 7'b1101101;
+ 3: return 7'b1111001;
+ 4: return 7'b0110011;
+ 5: return 7'b1011011;
+ 6: return 7'b1011111;
+ 7: return 7'b1110000;
+ 8: return 7'b1111111;
+ 9: return 7'b1111011;
+ endcase
+endfunction