From 927437e12c45d7c4cf0b84aeea8e42f93c9bb961 Mon Sep 17 00:00:00 2001 From: Waylon Cude Date: Mon, 26 May 2025 22:52:14 -0700 Subject: [PATCH] Fixup to get main demo working This adds some unnecessary stuff into the debug core that I used to troubleshoot. There are like 5 bugfixes here. Especially of note is the low freq clock gen, I was trying to use modulo like you would do in a computer program but it was too slow, so I had to move the logic around a bunch. --- Nexys-A7-100T-Master.xdc | 110 ++- SDVD.xpr | 691 +++++++++--------- design/audio/audio_buffer.sv | 7 + design/low_freq_clock_gen.sv | 61 +- design/nexys_a7_top.sv | 13 +- .../segment_display/display_anode_driver.sv | 17 +- 6 files changed, 505 insertions(+), 394 deletions(-) create mode 100644 design/audio/audio_buffer.sv diff --git a/Nexys-A7-100T-Master.xdc b/Nexys-A7-100T-Master.xdc index 5003bed..af0239a 100644 --- a/Nexys-A7-100T-Master.xdc +++ b/Nexys-A7-100T-Master.xdc @@ -5,8 +5,11 @@ ## 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] +create_clock -period 10.000 -name sys_clk_pin -waveform {0.000 5.000} -add [get_ports CLK100MHZ] + +set_property CFGBVS VCCO [current_design] +set_property CONFIG_VOLTAGE 3.3 [current_design] ##Switches @@ -54,31 +57,31 @@ create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports {CL #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] +set_property -dict {PACKAGE_PIN R10 IOSTANDARD LVCMOS33} [get_ports CB] +set_property -dict {PACKAGE_PIN K16 IOSTANDARD LVCMOS33} [get_ports CC] +set_property -dict {PACKAGE_PIN K13 IOSTANDARD LVCMOS33} [get_ports CD] +set_property -dict {PACKAGE_PIN P15 IOSTANDARD LVCMOS33} [get_ports CE] +set_property -dict {PACKAGE_PIN T11 IOSTANDARD LVCMOS33} [get_ports CF] +set_property -dict {PACKAGE_PIN L18 IOSTANDARD LVCMOS33} [get_ports 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]}] +set_property -dict {PACKAGE_PIN J18 IOSTANDARD LVCMOS33} [get_ports {AN[1]}] +set_property -dict {PACKAGE_PIN T9 IOSTANDARD LVCMOS33} [get_ports {AN[2]}] +set_property -dict {PACKAGE_PIN J14 IOSTANDARD LVCMOS33} [get_ports {AN[3]}] +set_property -dict {PACKAGE_PIN P14 IOSTANDARD LVCMOS33} [get_ports {AN[4]}] +set_property -dict {PACKAGE_PIN T14 IOSTANDARD LVCMOS33} [get_ports {AN[5]}] +set_property -dict {PACKAGE_PIN K2 IOSTANDARD LVCMOS33} [get_ports {AN[6]}] +set_property -dict {PACKAGE_PIN U13 IOSTANDARD LVCMOS33} [get_ports {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] ##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] #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] #set_property -dict { PACKAGE_PIN P18 IOSTANDARD LVCMOS33 } [get_ports { BTND }]; #IO_L9N_T1_DQS_D13_14 Sch=btnd @@ -212,3 +215,70 @@ set_property -dict { PACKAGE_PIN M17 IOSTANDARD LVCMOS33 } [get_ports { BTNR } #set_property -dict { PACKAGE_PIN L14 IOSTANDARD LVCMOS33 } [get_ports { QSPI_DQ[2] }]; #IO_L2P_T0_D02_14 Sch=qspi_dq[2] #set_property -dict { PACKAGE_PIN M14 IOSTANDARD LVCMOS33 } [get_ports { QSPI_DQ[3] }]; #IO_L2N_T0_D03_14 Sch=qspi_dq[3] #set_property -dict { PACKAGE_PIN L13 IOSTANDARD LVCMOS33 } [get_ports { QSPI_CSN }]; #IO_L6P_T0_FCS_B_14 Sch=qspi_csn + +create_debug_core u_ila_0 ila +set_property ALL_PROBE_SAME_MU true [get_debug_cores u_ila_0] +set_property ALL_PROBE_SAME_MU_CNT 1 [get_debug_cores u_ila_0] +set_property C_ADV_TRIGGER false [get_debug_cores u_ila_0] +set_property C_DATA_DEPTH 1024 [get_debug_cores u_ila_0] +set_property C_EN_STRG_QUAL false [get_debug_cores u_ila_0] +set_property C_INPUT_PIPE_STAGES 0 [get_debug_cores u_ila_0] +set_property C_TRIGIN_EN false [get_debug_cores u_ila_0] +set_property C_TRIGOUT_EN false [get_debug_cores u_ila_0] +set_property port_width 1 [get_debug_ports u_ila_0/clk] +connect_debug_port u_ila_0/clk [get_nets [list CLK100MHZ_IBUF_BUFG]] +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe0] +set_property port_width 6 [get_debug_ports u_ila_0/probe0] +connect_debug_port u_ila_0/probe0 [get_nets [list {seconds_reg[0]} {seconds_reg[1]} {seconds_reg[2]} {seconds_reg[3]} {seconds_reg[4]} {seconds_reg[5]}]] +create_debug_port u_ila_0 probe +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe1] +set_property port_width 6 [get_debug_ports u_ila_0/probe1] +connect_debug_port u_ila_0/probe1 [get_nets [list {minutes[0]} {minutes[1]} {minutes[2]} {minutes[3]} {minutes[4]} {minutes[5]}]] +create_debug_port u_ila_0 probe +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe2] +set_property port_width 3 [get_debug_ports u_ila_0/probe2] +connect_debug_port u_ila_0/probe2 [get_nets [list {playbackController/current[0]} {playbackController/current[1]} {playbackController/current[2]}]] +create_debug_port u_ila_0 probe +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe3] +set_property port_width 6 [get_debug_ports u_ila_0/probe3] +connect_debug_port u_ila_0/probe3 [get_nets [list {hours_reg[0]} {hours_reg[1]} {hours_reg[2]} {hours_reg[3]} {hours_reg[4]} {hours_reg[5]}]] +create_debug_port u_ila_0 probe +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe4] +set_property port_width 3 [get_debug_ports u_ila_0/probe4] +connect_debug_port u_ila_0/probe4 [get_nets [list {anodeDriver/mux_select[0]} {anodeDriver/mux_select[1]} {anodeDriver/mux_select[2]}]] +create_debug_port u_ila_0 probe +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe5] +set_property port_width 8 [get_debug_ports u_ila_0/probe5] +connect_debug_port u_ila_0/probe5 [get_nets [list {AN_OBUF[0]} {AN_OBUF[1]} {AN_OBUF[2]} {AN_OBUF[3]} {AN_OBUF[4]} {AN_OBUF[5]} {AN_OBUF[6]} {AN_OBUF[7]}]] +create_debug_port u_ila_0 probe +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe6] +set_property port_width 1 [get_debug_ports u_ila_0/probe6] +connect_debug_port u_ila_0/probe6 [get_nets [list CA_OBUF]] +create_debug_port u_ila_0 probe +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe7] +set_property port_width 1 [get_debug_ports u_ila_0/probe7] +connect_debug_port u_ila_0/probe7 [get_nets [list CB_OBUF]] +create_debug_port u_ila_0 probe +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe8] +set_property port_width 1 [get_debug_ports u_ila_0/probe8] +connect_debug_port u_ila_0/probe8 [get_nets [list CC_OBUF]] +create_debug_port u_ila_0 probe +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe9] +set_property port_width 1 [get_debug_ports u_ila_0/probe9] +connect_debug_port u_ila_0/probe9 [get_nets [list CD_OBUF]] +create_debug_port u_ila_0 probe +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe10] +set_property port_width 1 [get_debug_ports u_ila_0/probe10] +connect_debug_port u_ila_0/probe10 [get_nets [list CE_OBUF]] +create_debug_port u_ila_0 probe +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe11] +set_property port_width 1 [get_debug_ports u_ila_0/probe11] +connect_debug_port u_ila_0/probe11 [get_nets [list CF_OBUF]] +create_debug_port u_ila_0 probe +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe12] +set_property port_width 1 [get_debug_ports u_ila_0/probe12] +connect_debug_port u_ila_0/probe12 [get_nets [list CG_OBUF]] +set_property C_CLK_INPUT_FREQ_HZ 300000000 [get_debug_cores dbg_hub] +set_property C_ENABLE_CLK_DIVIDER false [get_debug_cores dbg_hub] +set_property C_USER_SCAN_CHAIN 1 [get_debug_cores dbg_hub] +connect_debug_port dbg_hub/clk [get_nets CLK100MHZ_IBUF_BUFG] diff --git a/SDVD.xpr b/SDVD.xpr index ec14c89..a4d4e3b 100644 --- a/SDVD.xpr +++ b/SDVD.xpr @@ -1,340 +1,351 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Vivado Synthesis Defaults - - - - - - - - - - - Default settings for Implementation. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - default_dashboard - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + default_dashboard + + + diff --git a/design/audio/audio_buffer.sv b/design/audio/audio_buffer.sv new file mode 100644 index 0000000..b3a121e --- /dev/null +++ b/design/audio/audio_buffer.sv @@ -0,0 +1,7 @@ +//this interfaces with block ram +module audio_buffer( + input logic clk, reset, + + + +); diff --git a/design/low_freq_clock_gen.sv b/design/low_freq_clock_gen.sv index 60b68bc..ff28149 100644 --- a/design/low_freq_clock_gen.sv +++ b/design/low_freq_clock_gen.sv @@ -8,38 +8,49 @@ module low_freq_clock_gen( output logic clk1k, clk10h, seconds_pulse ); -logic [$clog2(100_000_000):0] counter; -logic [$clog2(4000):0] seconds_counter; -logic clk4k; +// Hardcoded to be 1,000,000/4,000 +// Relying on constant maths makes it the wrong size +localparam num_cycles = 25_000; + +logic [$clog2(num_cycles):0] counter; +logic [$clog2(4000):0] seconds_counter; +logic [$clog2(4000):0] clock_divider_counter; -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 + counter <= num_cycles; + clk1k <= 0; + clk10h <= 0; seconds_pulse <= 0; seconds_counter <= 0; + clock_divider_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; + // At 4khz increment the seconds counter and output clocks + else if (counter == 0) begin + counter <= num_cycles; seconds_counter <= seconds_counter + {9'b0, speed}; - end -end + clock_divider_counter <= clock_divider_counter + 1; + if (seconds_counter >= 4000) begin + seconds_counter <= seconds_counter-4000; + // Should we flop it or pulse at 100MHz? + seconds_pulse <= 1; + end + else + seconds_pulse <= 0; + if (clock_divider_counter == 4000) + clock_divider_counter <= 0; + + // Generate output clocks + if (clock_divider_counter % 4 == 0) + clk1k <= ~clk1k; + if (clock_divider_counter % 400 == 0) + clk10h <= ~clk10h; + end + else + counter <= counter - 1; + +end + endmodule diff --git a/design/nexys_a7_top.sv b/design/nexys_a7_top.sv index 647708c..ec3042c 100644 --- a/design/nexys_a7_top.sv +++ b/design/nexys_a7_top.sv @@ -3,7 +3,7 @@ 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 CA,CB,CC,CD,CE,CF,CG, output logic [7:0] AN ); @@ -18,9 +18,12 @@ 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 +wire [2:0] segment_mux_select; + +// These segments are currently unused +assign segments[7] = 0; +assign segments[6] = 0; +assign {CA,CB,CC,CD,CE,CF,CG} = ~segments[segment_mux_select]; logic [$clog2(60)-1:0] seconds; logic [$clog2(60)-1:0] minutes; @@ -50,7 +53,7 @@ always_ff @(posedge seconds_pulse) begin seconds <= seconds + 1; end -display_anode_driver anodeDriver(clk_1khz,reset,AN); +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]); diff --git a/design/segment_display/display_anode_driver.sv b/design/segment_display/display_anode_driver.sv index cb9d790..90a2cd2 100644 --- a/design/segment_display/display_anode_driver.sv +++ b/design/segment_display/display_anode_driver.sv @@ -1,11 +1,20 @@ // 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); +module display_anode_driver( + input logic clk, + input logic reset, + output logic [7:0] AN, + output logic [2:0] mux_select); // This is just a shift register that drives each anode individually always_ff @(posedge clk) begin - if (reset) - AN <= 1; - else + if (reset) begin + AN <= '1 - 1; + mux_select <= 0; + end + else begin AN <= {AN[6:0], AN[7]}; + // Letting this overflow will automatically reset it + mux_select <= mux_select + 1; + end end endmodule