diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7caf17870..ae8072452 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -8,8 +8,7 @@ stages: variables: XILINX_VIVADO: /non-free/Xilinx/Vivado/2020.2 CI_REGISTRY: mohs.dhcp.lbl.gov - CONTAINER_IMAGE: $CI_REGISTRY/testing_base_bookworm - # CONTAINER_IM_IMAGE: $CI_REGISTRY/riscv_bloat + CONTAINER_IMAGE: $CI_REGISTRY/bedrock_testing_base_bookworm DOCKER_HOST: tcp://docker:2375/ DOCKER_DRIVER: overlay2 @@ -19,7 +18,6 @@ services: - name: mohs.dhcp.lbl.gov/docker:20.10.12-dind command: ["--insecure-registry", "mohs.dhcp.lbl.gov"] alias: docker -# entrypoint: ["dockerd-entrypoint.sh"] include: - local: .gitlab/ci/badger.gitlab-ci.yml diff --git a/.gitlab/ci/badger.gitlab-ci.yml b/.gitlab/ci/badger.gitlab-ci.yml index 09e881e53..ae5cbd874 100644 --- a/.gitlab/ci/badger.gitlab-ci.yml +++ b/.gitlab/ci/badger.gitlab-ci.yml @@ -25,4 +25,4 @@ badger_ac701_run: dependencies: - badger_ac701 script: - - cd badger/tests && test -r ac701_rgmii_vtest.bit && sh teststand_ac701.sh + - cd badger/tests && test -r ac701_rgmii_vtest.bit && SERIAL_NUM_OPT="-s 210203356870" sh teststand_ac701.sh diff --git a/.gitlab/ci/build.gitlab-ci.yml b/.gitlab/ci/build.gitlab-ci.yml index e801342f4..91fc1f723 100644 --- a/.gitlab/ci/build.gitlab-ci.yml +++ b/.gitlab/ci/build.gitlab-ci.yml @@ -15,6 +15,7 @@ build: -t $CONTAINER_IMAGE:$CI_PROJECT_NAME-$CI_COMMIT_SHORT_SHA \ -t $CONTAINER_IMAGE:latest \ . + docker run --rm $CONTAINER_IMAGE bash -c 'echo -n "Debian version: "; cat "/etc/debian_version"' docker push $CONTAINER_IMAGE:$CI_COMMIT_REF_NAME docker push $CONTAINER_IMAGE:$CI_PROJECT_NAME-$CI_COMMIT_SHORT_SHA docker push $CONTAINER_IMAGE:latest diff --git a/.gitlab/ci/comms_top.gitlab-ci.yml b/.gitlab/ci/comms_top.gitlab-ci.yml index 47f124952..1c87bb98a 100644 --- a/.gitlab/ci/comms_top.gitlab-ci.yml +++ b/.gitlab/ci/comms_top.gitlab-ci.yml @@ -40,4 +40,4 @@ gige_sfp_ac701_run: dependencies: - gige_sfp_ac701 script: - - cd projects/comms_top/gige_eth && make hwload_ac701 && make hwtest_ac701 + - cd projects/comms_top/gige_eth && make hwload_ac701 SERIAL_NUM_OPT="-s 210203356870" && sleep 7 && make hwtest_ac701 diff --git a/.gitlab/ci/oscope.gitlab-ci.yml b/.gitlab/ci/oscope.gitlab-ci.yml index 854e258dd..a3885ee10 100644 --- a/.gitlab/ci/oscope.gitlab-ci.yml +++ b/.gitlab/ci/oscope.gitlab-ci.yml @@ -5,6 +5,20 @@ oscope_top_test: script: - make Voscope_top_tb && make Voscope_top_leep && make clean +# We know the design doesn't yet get evaluated as CDC-clean, at least in part +# due to Verilog inout ports being poorly supported by our tools. +# Please take out the error bypass (echo) if this ever gets fixed. +oscope_cdc: + before_script: + - cd projects/oscope/marble_family + stage: test + script: + - make dep && make oscope_prep_yosys.json && (make oscope_prep_cdc.txt || echo "Found CDC violation, as expected; continuing") + artifacts: + expire_in: 1 week + paths: + - projects/oscope/marble_family/oscope_prep_cdc.txt + oscope_top_bmb7: before_script: - cd projects/oscope/bmb7_cu && ls /non-free @@ -29,17 +43,15 @@ oscope_top_marble: paths: - projects/oscope/marble_family/oscope_top.bit +# LITEX_INSTALL_PATH is defined in the Docker image marble_ddr3_test: stage: synthesis before_script: - - apt-get update && apt-get install -y ninja-build && pip3 install meson==0.64.1 - - mkdir /litex_setup_dir - - (BD=$PWD && cd /litex_setup_dir && sh $BD/build-tools/litex_meta.sh) - - cd /litex_setup_dir/litex-boards/litex_boards/targets + - cd $LITEX_INSTALL_PATH/litex-boards/litex_boards/targets script: - XILINXD_LICENSE_FILE=$XILINXD_LICENSE_FILE PATH=$XILINX_VIVADO/bin:$PATH && python3 berkeleylab_marble.py --build - echo $CI_PROJECT_DIR - - cp /litex_setup_dir/litex-boards/litex_boards/targets/build/berkeleylab_marble/gateware/berkeleylab_marble.bit $CI_PROJECT_DIR/ + - cp $LITEX_INSTALL_PATH/litex-boards/litex_boards/targets/build/berkeleylab_marble/gateware/berkeleylab_marble.bit $CI_PROJECT_DIR/ artifacts: name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME" expire_in: 1 week @@ -50,9 +62,6 @@ marble_ddr3_test: litex_trigger_capture: stage: synthesis before_script: - - apt-get update && apt-get install -y ninja-build && pip3 install meson==0.64.1 - - mkdir /litex_setup_dir - - (BD=$PWD && cd /litex_setup_dir && sh $BD/build-tools/litex_meta.sh) - cd projects/trigger_capture script: XILINXD_LICENSE_FILE=$XILINXD_LICENSE_FILE PATH=$XILINX_VIVADO/bin:$PATH && make marble.bit diff --git a/Dockerfile b/Dockerfile index af52d593b..99e2ac481 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM debian:bookworm-slim as testing_base_bookworm +FROM debian:12.8-slim AS testing_base_bookworm # Vivado needs libtinfo5, at least for Artix? RUN apt-get update && \ @@ -114,3 +114,33 @@ RUN apt-get update && \ libidn12 && \ rm -rf /var/lib/apt/lists/* && \ ln -s libidn.so.12 /usr/lib/x86_64-linux-gnu/libidn.so.11 + +# Install litex +RUN apt-get update && \ + apt-get install -y \ + ninja-build \ + gcc-aarch64-linux-gnu \ + ghdl && \ + rm -rf /var/lib/apt/lists/* && \ + pip3 install \ + meson + +COPY build-tools/litex_meta.sh / + +ENV LITEX_INSTALL_PATH=/litex + +RUN mkdir ${LITEX_INSTALL_PATH} && \ + cd ${LITEX_INSTALL_PATH} && \ + sh /litex_meta.sh + +# Install sv2v +RUN apt-get update && \ + apt-get install -y \ + haskell-stack && \ + rm -rf /var/lib/apt/lists/* && \ + git clone https://github.com/zachjs/sv2v /sv2v && \ + cd /sv2v && \ + git checkout 7808819c48c167978aeb5ef34c6e5ed416e90875 && \ + make && \ + rm -rf $HOME/.stack && \ + cp bin/sv2v /usr/local/bin/ diff --git a/badger/tests/kc705/ODDR.v b/badger/tests/kc705/ODDR.v index 95c29833b..8062451ce 100644 --- a/badger/tests/kc705/ODDR.v +++ b/badger/tests/kc705/ODDR.v @@ -1,5 +1,5 @@ // pathetic model of Xilinx DDR output cell -// ignores set and reset inputs +// ignores set and reset inputs, and the SRTYPE and DDR_CLK_EDGE parameters module ODDR ( input S, input R, @@ -14,10 +14,11 @@ parameter DDR_CLK_EDGE = "SAME_EDGE"; parameter INIT = 0; parameter SRTYPE = "SYNC"; -reg qx=INIT, hold=INIT; -always @(posedge C) if (CE) qx <= D1; -always @(posedge C) if (CE) hold <= D2; -always @(negedge C) qx <= hold; -assign Q = qx; +reg hold1=INIT, hold2=INIT; +always @(posedge C) if (CE) begin + hold1 <= D1; + hold2 <= D2; +end +assign Q = C ? hold1 : hold2; endmodule diff --git a/badger/tests/teststand_ac701.sh b/badger/tests/teststand_ac701.sh index 48272720b..3b7841ad3 100644 --- a/badger/tests/teststand_ac701.sh +++ b/badger/tests/teststand_ac701.sh @@ -4,7 +4,7 @@ # Tested useful for the CI test stand (mohs) at LBNL. # Can also act as a template for other use cases. set -e -xc3sprog -c jtaghs1_fast ac701_rgmii_vtest.bit +xc3sprog -c jtaghs1_fast $SERIAL_NUM_OPT ac701_rgmii_vtest.bit echo "So far so good" sleep 8 echo "Hope links are up" diff --git a/board_support/zest/zest_if.sv b/board_support/zest/zest_if.sv index 9011453ad..a333502f4 100644 --- a/board_support/zest/zest_if.sv +++ b/board_support/zest/zest_if.sv @@ -35,7 +35,8 @@ interface zest_if ( assign {U2_D1NA, U2_D1NB, U2_D1NC, U2_D1ND} = {U2[14], U2[4], U2[26], U2[11]}; assign {U2_D1PA, U2_D1PB, U2_D1PC, U2_D1PD} = {U2[17], U2[8], U2[5], U2[12]}; assign {U2_DCON, U2_DCOP, U2_FCON, U2_FCOP} = {U2[9], U2[15], U2[10], U2[6]}; - assign {U3[10], U2[22], U4[26]} = {U2_PDWN, U2_CSB, U2_SCLK}; + assign {U2[22], U4[26]} = {U2_CSB, U2_SCLK}; + // don't set U3[10] to U2_PDWN, since it's set to U3_PDWN below wire U3_D0NA, U3_D0NB, U3_D0NC, U3_D0ND, U3_D0PA, U3_D0PB, U3_D0PC, U3_D0PD, U3_D1NA, U3_D1NB, U3_D1NC, U3_D1ND, U3_D1PA, U3_D1PB, U3_D1PC, U3_D1PD, @@ -77,9 +78,9 @@ interface zest_if ( wire U18_DOUT_RDY = U18[1]; assign {U18[0], U18[2], U18[3], U18[4]} = {U18_CLK, U18_CS, U18_DIN, U18_SCLK}; - // NOTE: Semantics of PMOD and HDMI connectors are application-dependent and + // NOTE: Semantics of Pmod and HDMI connectors are application-dependent and // thus not handled here - // PMOD - J18, J17 + // Pmod - J18, J17 // J19: HDMI // U33U1: TPS62110 DC-DC converter diff --git a/board_support/zest_soc/vita_57.1_pinout.txt b/board_support/zest_soc/vita_57.1_pinout.txt index b2f2d6665..00219af80 100644 --- a/board_support/zest_soc/vita_57.1_pinout.txt +++ b/board_support/zest_soc/vita_57.1_pinout.txt @@ -1,6 +1,6 @@ -#from https://fmchub.github.io/appendix/VITA57_FMC_HPC_LPC_SIGNALS_AND_PINOUT.html -# compactible with KC705 UG810 Appendix B -# compactible with FMC116_112_user_manual.pdf Table 8. +# from https://fmchub.github.io/appendix/VITA57_FMC_HPC_LPC_SIGNALS_AND_PINOUT.html +# compatible with KC705 UG810 Appendix B +# compatible with FMC116_112_user_manual.pdf Table 8 CLK0_M2C_N H5 CLK0_M2C_P H4 diff --git a/board_support/zest_soc/zest.v b/board_support/zest_soc/zest.v index 25e92ae2e..9fde85f49 100644 --- a/board_support/zest_soc/zest.v +++ b/board_support/zest_soc/zest.v @@ -245,7 +245,7 @@ assign PWR_EN = ~pwr_en_b; // ADC0_DIV, ADC1_DIV, DAC_DCO wire signed [PH_DIFF_DW-1:0] phdiff [N_ADC:0]; -wire [N_ADC:0] phdiff_val; +wire [N_ADC:0] phdiff_err; // DSP_CLK, ADC0_DIV, ADC1_DIV, DAC_DCO wire [27:0] f_clks [N_ADC+1:0]; wire pll_locked; @@ -318,14 +318,13 @@ generate for (ix=0; ix=16 + if (&track.cnt[4:0]) begin phase_err = phase_diff - phase_expect; phase_pass = $abs(phase_err)/FULL_RANGE < err_bar; // $display("cc: %d, phase_err: %d, pass: %d", cc, phase_err, phase_pass); diff --git a/dsp/phaset.gtkw b/dsp/phaset.gtkw new file mode 100644 index 000000000..12212e5d3 --- /dev/null +++ b/dsp/phaset.gtkw @@ -0,0 +1,30 @@ +[timestart] 0 +[size] 1000 600 +[pos] 0 0 +*-25.448893 12500000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +[treeopen] phaset_tb. +[sst_width] 213 +[signals_width] 211 +[sst_expanded] 1 +[sst_vpaned_height] 154 +@28 +phaset_tb.track.div +phaset_tb.track.msb +phaset_tb.track.nsb +phaset_tb.track.move +phaset_tb.track.dn +phaset_tb.track.up +@8024 +phaset_tb.track.phase[13:0] +@20000 +- +@28 +phaset_tb.fault +@8420 +phaset_tb.phase_unw +@20000 +- +@28 +phaset_tb.fail +[pattern_trace] 1 +[pattern_trace] 0 diff --git a/dsp/phaset.v b/dsp/phaset.v index 8ed93c7a1..49fc57420 100644 --- a/dsp/phaset.v +++ b/dsp/phaset.v @@ -11,12 +11,11 @@ module phaset #( parameter order=1, parameter dw=14, parameter adv=3861, - parameter delta=264, // 8*33 - parameter ext_div_en=0 + parameter delta=16 ) ( input uclk, + input uclkg, input sclk, - input ext_div, output [dw-1:0] phase, output fault // single cycle ); @@ -24,14 +23,12 @@ module phaset #( // _Still_ draw analogy to the AD9901 // Generalize to a Johnson counter reg [order-1:0] ishr=0; -always @(posedge uclk) ishr <= (ishr << 1) | {{order-1{1'b0}},~ishr[order-1]}; -wire div = ishr[0]; -//reg div=0; always @(posedge uclk) div <= ~div; +always @(posedge uclk) if (uclkg) ishr <= (ishr << 1) | {{order-1{1'b0}},~ishr[order-1]}; +wire capture; reg_tech_cdc capture_cdc(.I(ishr[0]), .C(sclk), .O(capture)); // Test bench fails for some initial phase_r values between 14900 and 15050. // In that case the fault output signals the problem. reg [dw-1:0] osc=0, acc=0, phase_r=0; -reg capture=0; reg fault_r=0; wire msb = acc[dw-1]; wire nsb = acc[dw-2]; @@ -41,7 +38,6 @@ wire dir = ~nsb; wire dn = move & dir; wire up = move & ~dir; always @(posedge sclk) begin - capture <= ext_div_en ? ext_div : div; if (move) phase_r <= phase_r + (dir ? -delta : delta); fault_r <= move & peak; osc <= osc + adv; diff --git a/dsp/phaset_tb.v b/dsp/phaset_tb.v new file mode 100644 index 000000000..5b3cfd698 --- /dev/null +++ b/dsp/phaset_tb.v @@ -0,0 +1,80 @@ +`timescale 1ns / 1ps + +module phaset_tb; + +// In real life, this clock is not coherent with the unknown clock +reg sclk; // 200 MHz +integer cc; +reg glitch; +reg fail=0; +initial begin + if ($test$plusargs("vcd")) begin + $dumpfile("phaset.vcd"); + $dumpvars(5,phaset_tb); + end + glitch = $test$plusargs("glitch"); + for (cc=0; cc<24000; cc=cc+1) begin + sclk=0; #2.5; + sclk=1; #2.5; + end + $display("%s", fail ? "FAIL" : "PASS"); + if (fail) $stop(0); + $finish(0); +end + +// 94.286 MHz + epsilon +// divide by 33 +// 174.9 +reg uclk1; +always begin + uclk1=0; #5.301; + uclk1=1; #5.301; +end + +// Device under test +wire [13:0] phaset_out; +wire fault; +// round(2**14*1320/14/2/200) = 3862 is the DDS frequency +// delta kinda sets the gain and resolution of the phase tracking loop +phaset #(.dw(14), .adv(3862), .delta(16)) track( + .uclk(uclk1), .uclkg(1'b1), .sclk(sclk), + .phase(phaset_out), .fault(fault)); + +// Demonstration that changing internal divider state (not the uclk1 phase +// itself) will also toggle the msb of phaset_out. That bit should therefore +// be ignored. To exercise this feature, +// make phaset_view VCD_ARGS_phaset.vcd=+glitch +initial @(cc==3000) if (glitch) track.ishr[0] = ~track.ishr[0]; + +// Unwrapped phase +integer phase_unw=0, phase_diff, phase0; +reg [13:0] phaset_d=0; +reg first=1, rate_ok; +real rate, rate_want=1.42199585; // see below +integer t0=3000, tlen=20000; +always @(posedge sclk) if (cc>1000) begin + phaset_d <= phaset_out; + phase_diff = phaset_out - phaset_d; + if (phase_diff < -8192) phase_diff = phase_diff + 16384; + if (~first && (phase_diff > 16) || (phase_diff < -16)) fail = 1; + if (first) phase_unw = phaset_out; + else phase_unw <= phase_unw + phase_diff; + if (fault & ~glitch) fail = 1; + if (cc==t0) phase0 = phase_unw; + if (cc==(t0+tlen+1)) begin + $display("Delta phase %d bits / %d cycles", + phase_unw - phase0, tlen); + rate = (phase_unw - phase0) * 1.0 / tlen; + rate_ok = $abs(rate - rate_want) < 0.001*rate_want; + $display("Rate %.5f bits/cycle vs. theory %.5f %s", + rate, rate_want, rate_ok ? " OK" : "BAD"); + if (!glitch && !rate_ok) fail = 1; + end + first = 0; +end +// 3862/2**14*200 MHz = 47.143555 MHz DDS "local oscillator" +// 1/(2*5.301 ns)/2 = 47.160913 MHz input to be measured +// 1/(2*5.301e-9)/2 - 3862/2**14*200e6 = 17358.35 Hz offset +// 17358.35 Hz * 16384 / 200 MHz = 1.42199585 bits/cycle + +endmodule diff --git a/dsp/phasex.gtkw b/dsp/phasex.gtkw deleted file mode 100644 index 4916c3813..000000000 --- a/dsp/phasex.gtkw +++ /dev/null @@ -1,59 +0,0 @@ -[timestart] 0 -[size] 1150 707 -[pos] -1 -1 -*-23.233957 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -[treeopen] phasex_tb. -[treeopen] phasex_tb.track. -[sst_width] 210 -[signals_width] 219 -[sst_expanded] 1 -[sst_vpaned_height] 191 -@28 -phasex_tb.trig -phasex_tb.ready -phasex_tb.done -phasex_tb.f -@24 -phasex_tb.raddr[5:0] -@22 -phasex_tb.dout[15:0] -@8024 -phasex_tb.phase_diff[12:0] -@20000 -- -@420 -phasex_tb.vfreq_out[13:0] -@200 --dut -@28 -phasex_tb.dut.invalid -phasex_tb.dut.run -phasex_tb.dut.ready_r -@22 -phasex_tb.dut.count[8:0] -@28 -phasex_tb.dut.div2 -phasex_tb.dut.div1 -@22 -phasex_tb.dut.shiftr[15:0] -@28 -phasex_tb.dut.wen -@22 -phasex_tb.dut.waddr[5:0] -@200 --trackers -@8024 -phasex_tb.track.phaset_out1[13:0] -@20000 -- -@28 -phasex_tb.track.fault1 -@8024 -phasex_tb.track.phaset_out2[13:0] -@20000 -- -@28 -phasex_tb.track.fault2 -phasex_tb.track.tick -[pattern_trace] 1 -[pattern_trace] 0 diff --git a/dsp/phasex.v b/dsp/phasex.v index e5ecfdf2b..6efc3084a 100644 --- a/dsp/phasex.v +++ b/dsp/phasex.v @@ -1,7 +1,7 @@ `timescale 1ns / 1ns // DMTD-inspired investigation into clock phasing -// No on-chip analysis, that could be added later once we see the captured patterns +// No on-chip analysis, but that could be added later once we see the captured patterns module phasex #( parameter aw=10 ) ( @@ -40,7 +40,7 @@ wire [aw-1:0] waddr = count[aw+2:3]; // Data flow logic, also in sclk domain reg [15:0] shiftr=0; -reg [1:0] snap=0; +(* ASYNC_REG = "TRUE" *) reg [1:0] snap=0; always @(posedge sclk) begin snap <= {div2, div1}; // safely crosses clock domain if (run) shiftr <= {shiftr[13:0], snap}; diff --git a/dsp/rules.mk b/dsp/rules.mk index bd6b21c8f..3bd71f498 100644 --- a/dsp/rules.mk +++ b/dsp/rules.mk @@ -5,7 +5,7 @@ include $(CORDIC_DIR)/rules.mk VFLAGS_DEP += -I. -y . -y$(DSP_DIR) -y$(CORDIC_DIR) VFLAGS += -I. -y . -y$(DSP_DIR) -y$(CORDIC_DIR) -I$(AUTOGEN_DIR) -TEST_BENCH = data_xdomain_tb upconv_tb half_filt_tb complex_mul_tb tt800_tb rot_dds_tb mon_12_tb xy_pi_clip_tb iq_chain4_tb cordic_mux_tb timestamp_tb afterburner_tb ssb_out_tb banyan_tb banyan_mem_tb biquad_tb iirFilter_tb circle_buf_tb cic_multichannel_tb cic_wave_recorder_tb circle_buf_serial_tb iq_deinterleaver_tb serializer_multichannel_tb complex_freq_tb iq_trace_tb second_if_out_tb cpxmul_fullspeed_tb dpram_tb host_averager_tb cic_simple_us_tb phasex_tb complex_mul_flat_tb fwashout_tb lpass1_tb slew_xarray_tb isqrt_tb freq_count_tb +TEST_BENCH = data_xdomain_tb upconv_tb half_filt_tb complex_mul_tb tt800_tb rot_dds_tb mon_12_tb xy_pi_clip_tb iq_chain4_tb cordic_mux_tb timestamp_tb afterburner_tb ssb_out_tb banyan_tb banyan_mem_tb biquad_tb iirFilter_tb circle_buf_tb cic_multichannel_tb cic_wave_recorder_tb circle_buf_serial_tb iq_deinterleaver_tb serializer_multichannel_tb complex_freq_tb iq_trace_tb second_if_out_tb cpxmul_fullspeed_tb dpram_tb host_averager_tb cic_simple_us_tb phase_diff_tb phaset_tb complex_mul_flat_tb fwashout_tb lpass1_tb slew_xarray_tb isqrt_tb freq_count_tb TGT_ := $(TEST_BENCH) diff --git a/fpga_family/iserdes/lvds_dco.v b/fpga_family/iserdes/lvds_dco.v index b921d51cf..a248dd038 100644 --- a/fpga_family/iserdes/lvds_dco.v +++ b/fpga_family/iserdes/lvds_dco.v @@ -49,5 +49,11 @@ assign clk_div_to_bufg = clk_div_bufr; `endif BUFG bufg_i(.I(clk_div_to_bufg), .O(clk_div_bufg)); +`else +// Does almost nothing except establish some causality, +// and keep yosys from thinking this module is a white box. +assign clk_div_bufg = dco_p; +assign clk_div_bufr = dco_p; +assign dco_clk_out = dco_p; `endif endmodule diff --git a/fpga_family/iserdes/lvds_frame.v b/fpga_family/iserdes/lvds_frame.v index 126bc9925..c49c17792 100644 --- a/fpga_family/iserdes/lvds_frame.v +++ b/fpga_family/iserdes/lvds_frame.v @@ -6,5 +6,9 @@ module lvds_frame #(parameter flip_frame=0) ( `ifndef SIMULATE IBUFDS #(.DIFF_TERM("TRUE")) ibufds_frame(.I(flip_frame ? frame_n : frame_p), .IB(flip_frame ? frame_p : frame_n), .O(frame)); +`else +// Does almost nothing except establish some causality, +// and keep yosys from thinking this module is a white box. +assign frame = frame_p ^ flip_frame; `endif endmodule diff --git a/fpga_family/iserdes/lvds_iophy.v b/fpga_family/iserdes/lvds_iophy.v index 87a268882..2fdbe1b09 100644 --- a/fpga_family/iserdes/lvds_iophy.v +++ b/fpga_family/iserdes/lvds_iophy.v @@ -90,6 +90,11 @@ always @ (posedge clk_div) begin dout[7]<=flip_d?~Q8:Q8; end +`else +// Does almost nothing except establish some causality, +// and keep yosys from thinking this module is a white box. +always @ (posedge clk_div) dout <= {8{d_p}}; // horribly stupid +assign idelay_value_out = 0; // theoretically in clk_div domain, also `endif // SIMULATE endmodule diff --git a/fpga_family/xilinx/MMCME2_BASE.v b/fpga_family/xilinx/MMCME2_BASE.v index 8af0a748c..28055ee55 100644 --- a/fpga_family/xilinx/MMCME2_BASE.v +++ b/fpga_family/xilinx/MMCME2_BASE.v @@ -56,6 +56,7 @@ module MMCME2_BASE #( assign CLKOUT0 = CLKIN1; assign CLKOUT1 = CLKIN1; +assign LOCKED = 1; // verilator lint_restore endmodule // MMCME2_BASE diff --git a/fpga_family/xilinx/ODDR.v b/fpga_family/xilinx/ODDR.v index 4d25db75c..8062451ce 100644 --- a/fpga_family/xilinx/ODDR.v +++ b/fpga_family/xilinx/ODDR.v @@ -1,5 +1,5 @@ // pathetic model of Xilinx DDR output cell -// ignores set and reset inputs +// ignores set and reset inputs, and the SRTYPE and DDR_CLK_EDGE parameters module ODDR ( input S, input R, @@ -14,13 +14,11 @@ parameter DDR_CLK_EDGE = "SAME_EDGE"; parameter INIT = 0; parameter SRTYPE = "SYNC"; -// verilator lint_save -// verilator lint_off MULTIDRIVEN -reg qx=INIT, hold=INIT; -// verilator lint_restore -always @(negedge C) qx <= hold; -always @(posedge C) if (CE) qx <= D1; -always @(posedge C) if (CE) hold <= D2; -assign Q = qx; +reg hold1=INIT, hold2=INIT; +always @(posedge C) if (CE) begin + hold1 <= D1; + hold2 <= D2; +end +assign Q = C ? hold1 : hold2; endmodule diff --git a/projects/comms_top/gige_eth/Makefile b/projects/comms_top/gige_eth/Makefile index 88d8fa574..f7c187235 100644 --- a/projects/comms_top/gige_eth/Makefile +++ b/projects/comms_top/gige_eth/Makefile @@ -22,7 +22,7 @@ all: gen $(APP_NAME).bit $(APP_NAME).bit: $(IP_TCL) hwload_ac701: - xc3sprog -c jtaghs1_fast $(BITFILE) + xc3sprog -c jtaghs1_fast $(SERIAL_NUM_OPT) $(BITFILE) hwtest_ac701: ping -c2 $(SFP_IP) && cd ../test && python3 comms_top_test.py -t $(SFP_IP) -cf mem_test.cf diff --git a/projects/oscope/common/application_top.sv b/projects/oscope/common/application_top.sv index 444dd136d..b98d7ac26 100644 --- a/projects/oscope/common/application_top.sv +++ b/projects/oscope/common/application_top.sv @@ -55,11 +55,11 @@ module application_top( // Needs placing before usage of any top-level registers wire clk1x_clk, clk2x_clk, lb4_clk; -(* external, signal_type="single-cycle" *) reg [0:0] lamp_test_trig = 0; // top-level single-cycle -(* external, signal_type="single-cycle" *) reg [0:0] ctrace_start = 0; // top-level single-cycle +// Note: the syntax for these top-level registers is not quite compatible with "old" newad (* external *) reg [31:0] icc_cfg = 0; // top-level -(* external *) reg [7:0] tag_now = 0; // top-level (* external *) reg [1:0] domain_jump_realign = 0; // top-level +// newad-force clk1x domain +(* external, cd="clk1x" *) reg [7:0] tag_now = 0; // top-level `AUTOMATIC_decode @@ -157,10 +157,8 @@ wire [27:0] frequency_adc; wire [27:0] frequency_4xout; wire [27:0] frequency_clkout3; wire [27:0] frequency_dac_dco; -wire [27:0] frequency_gtx_tx; -wire [27:0] frequency_gtx_rx; -wire [15:0] hist_dout; -wire [1:0] hist_status; +wire [15:0] hist_dout=0; +wire [1:0] hist_status=0; wire [15:0] phasex_dout; wire phasex_ready; wire phasex_present; @@ -173,12 +171,14 @@ wire [7:0] llspi_result; wire wave1_available, wave0_available; wire [7:0] rawadc_avail; wire [31:0] banyan_data; -wire [31:0] banyan_status; -wire [31:0] trace_data; -wire [31:0] trace_status1; -wire [31:0] trace_status2; -wire [7:0] slow_data; -wire [0:0] slow_data_ready; +// banyan status register was constructed without regard to clock domains - please revisit +wire [31:0] banyan_status_x; +reg [31:0] banyan_status; always @(posedge lb_clk) banyan_status <= banyan_status_x; +wire [31:0] trace_data=0; +wire [31:0] trace_status1=0; +wire [31:0] trace_status2=0; +wire [7:0] slow_data=0; +wire [0:0] slow_data_ready=0; wire [31:0] phase_status_U2; wire [31:0] phase_status_U3; reg [15:0] crc_errors=0; @@ -187,31 +187,8 @@ wire [7:0] scanner_result_val; wire [7:0] slow_chain_out; wire [19:0] icc_data_U50, icc_data_U32; wire [8:0] qsfp_result; -wire [31:0] ctrace_out; -wire [0:0] ctrace_running; -parameter ctrace_aw=12; -wire [ctrace_aw-1:0] ctrace_pc; -wire [ctrace_aw-0:0] ctrace_status = {ctrace_pc, ctrace_running}; -wire [31:0] ccr1_summary; -wire [31:0] ccr1_counts; -wire [31:0] ccr1_cavity0_status; -wire [31:0] ccr1_cavity1_status; -wire [31:0] ccr1_rev_id; -reg [15:0] cc1_latency=0; -wire [15:0] cct1_local_frame_counter; // output of chitchat_tx -wire signed [17:0] cavity0_detune; -wire signed [17:0] cavity1_detune; -reg [0:0] cct1_cavity0_detune_valid=0; -reg [0:0] cct1_cavity1_detune_valid=0; -wire cavity0_detune_stb; -wire cavity1_detune_stb; -wire [6:0] cavity0_sat_count; -wire [6:0] cavity1_sat_count; -wire [2:0] dtrace_status; -wire [21:0] telem_monitor; wire signed [13:0] fdbk_drive_lb_out; wire [25:0] freq_multi_count_out; -wire [1:0] dac_enabled; wire [31:0] U15_spi_addr_rdbk = {zif_cfg.U15_sdo_addr, zif_cfg.U15_spi_rdbk}; wire [1:0] U15_spi_status = {zif_cfg.U15_spi_ready, zif_cfg.U15_sdio_as_sdo}; wire [31:0] U18_spi_addr_rdbk = {zif_cfg.U18_sdo_addr, zif_cfg.U18_spi_rdbk}; @@ -231,15 +208,25 @@ wire [31:0] hello_1 = "o wo"; wire [31:0] hello_2 = "rld!"; wire [31:0] hello_3 = 32'h0d0a0d0a; wire [31:0] ffffffff = 32'hffffffff; -wire [31:0] U2dout_lsb = zif_cfg.U2_dout[31:0]; -wire [31:0] U2dout_msb = zif_cfg.U2_dout[63:32]; -wire [31:0] U3dout_lsb = zif_cfg.U3_dout[31:0]; -wire [31:0] U3dout_msb = zif_cfg.U3_dout[63:32]; wire [19:0] idelay_value_out_U2_lsb = zif_cfg.U2_idelay_value_out[19:0]; wire [19:0] idelay_value_out_U2_msb = zif_cfg.U2_idelay_value_out[39:20]; wire [19:0] idelay_value_out_U3_lsb = zif_cfg.U3_idelay_value_out[19:0]; wire [19:0] idelay_value_out_U3_msb = zif_cfg.U3_idelay_value_out[39:20]; +// Only useful if the ADC data is static, which is the plan when +// configured to emit a test pattern during initial setup. +// Maybe just get rid of this, and use the real data capture in banyan memory. +reg [31:0] U2dout_lsb = 0; +reg [31:0] U2dout_msb = 0; +reg [31:0] U3dout_lsb = 0; +reg [31:0] U3dout_msb = 0; +always @(posedge lb_clk) begin + U2dout_lsb <= zif_cfg.U2_dout[31:0]; + U2dout_msb <= zif_cfg.U2_dout[63:32]; + U3dout_lsb <= zif_cfg.U3_dout[31:0]; + U3dout_msb <= zif_cfg.U3_dout[63:32]; +end + // Very basic pipelining of read process reg [23:0] lb_addr_r=0; always @ (posedge lb_clk) begin @@ -281,10 +268,6 @@ always @(posedge lb_clk) begin 4'h1: reg_bank_1 <= U3dout_msb; 4'h2: reg_bank_1 <= idelay_value_out_U3_lsb; 4'h3: reg_bank_1 <= idelay_value_out_U3_msb; - 4'ha: reg_bank_1 <= dtrace_status; - 4'hc: reg_bank_1 <= ctrace_status; // alias: ctrace_running - 4'hd: reg_bank_1 <= frequency_gtx_tx; - 4'he: reg_bank_1 <= frequency_gtx_rx; 4'hf: reg_bank_1 <= hist_status; default: reg_bank_1 <= 32'hfaceface; endcase @@ -310,16 +293,9 @@ always @(posedge lb_clk) begin case (lb_addr[3:0]) 4'h0: reg_bank_3 <= phase_status_U3; // alias: clk_phase_diff_out_U3 4'h1: reg_bank_3 <= crc_errors; - 4'h2: reg_bank_3 <= cavity0_detune; - 4'h3: reg_bank_3 <= cavity1_detune; - 4'h4: reg_bank_3 <= cavity0_sat_count; - 4'h5: reg_bank_3 <= cavity1_sat_count; - 4'h6: reg_bank_3 <= dac_enabled; // xxxx37 unused 4'h8: reg_bank_3 <= U15_spi_addr_rdbk; // alias: U15_spi_rdbk 4'h9: reg_bank_3 <= U15_spi_status; - 4'ha: reg_bank_3 <= cct1_cavity0_detune_valid; - 4'hb: reg_bank_3 <= cct1_cavity1_detune_valid; 4'hc: reg_bank_3 <= U18_spi_addr_rdbk; // alias: U18_spi_rdbk 4'hd: reg_bank_3 <= U18_spi_status; // xxxx3e unused @@ -332,18 +308,10 @@ always @(posedge lb_clk) begin 4'h4: reg_bank_4 <= trace_status1; 4'h5: reg_bank_4 <= trace_status2; 4'h7: reg_bank_4 <= slow_data_ready; - 4'h8: reg_bank_4 <= telem_monitor; default: reg_bank_4 <= 32'hfaceface; endcase case (lb_addr[3:0]) - // Most of these are in the wrong clock domain - 4'h0: reg_bank_5 <= ccr1_summary; - 4'h1: reg_bank_5 <= ccr1_counts; - 4'h2: reg_bank_5 <= ccr1_cavity0_status; - 4'h3: reg_bank_5 <= ccr1_cavity1_status; - 4'h4: reg_bank_5 <= ccr1_rev_id; - 4'h5: reg_bank_5 <= cc1_latency; - 4'h6: reg_bank_5 <= cct1_local_frame_counter; + 4'h1: reg_bank_5 <= 1; default: reg_bank_5 <= 32'hfaceface; endcase // All of the following rhs have had one stage of decode pipeline; @@ -370,8 +338,8 @@ always @(posedge lb_clk) begin end wire rawadc_trig_x; -(* lb_automatic *) -digitizer_config digitizer_config // auto +(* lb_automatic, cd="clk1x" *) +digitizer_config digitizer_config // auto clk1x ( .lb_clk(lb_clk), .lb_strobe(lb_strobe), @@ -383,7 +351,7 @@ digitizer_config digitizer_config // auto .rawadc_trig_x(rawadc_trig_x), .adc_clk(adc_clk), .adc_data(adc_data), - .banyan_status(banyan_status), + .banyan_status(banyan_status_x), .phasex_dout(phasex_dout), .phase_status_U2(phase_status_U2), .phase_status_U3(phase_status_U3), diff --git a/projects/oscope/common/digitizer_config.sv b/projects/oscope/common/digitizer_config.sv index 1a64aa964..c2e6153ee 100644 --- a/projects/oscope/common/digitizer_config.sv +++ b/projects/oscope/common/digitizer_config.sv @@ -45,22 +45,15 @@ module digitizer_config( output [1:0] clk_status, // software-settable + // adc_clk domain (* external *) input [31:0] periph_config, // external (* external *) input [15:0] bitslip, // external (* external *) - input [1:0] U15_spi_read_and_start_r, // external - //input U15_spi_read_r, // external - (* external *) input [31:0] U15_spi_data_addr_r, // external - //input [15:0] U15_spi_addr_r, // external - (* external *) - input [1:0] U18_spi_read_and_start_r, // external - //input U18_spi_read_r, // external (* external *) input [31:0] U18_spi_data_addr_r, // external - //input [7:0] U18_spi_addr_r, // external (* external *) input U2_clk_reset_r, // external (* external *) @@ -77,29 +70,36 @@ module digitizer_config( input mmcm_reset_r, // external (* external *) input idelayctrl_reset_r, // external + // lb_clk domain - (* external *) + // newad-force lb domain + (* external, cd="lb" *) + input [1:0] U15_spi_read_and_start_r, // external + (* external, cd="lb" *) + input [1:0] U18_spi_read_and_start_r, // external + (* external, cd="lb" *) input [7:0] banyan_mask, // external - (* external, signal_type="single-cycle" *) + (* external, signal_type="single-cycle", cd="lb" *) input phasex_trig, // external single-cycle - (* external, signal_type="we-strobe" *) + (* external, signal_type="we-strobe", cd="lb" *) input llspi_we, // external we-strobe input llspi_re, // -- external strobe - (* external, signal_type="we-strobe" *) + (* external, signal_type="we-strobe", cd="lb" *) input clk_status_we, // external we-strobe - (* external *) + (* external, cd="lb" *) input [4:0] scanner_debug, // external input autoset_enable, // -- external input scan_trigger, // -- external single-cycle - (* external, signal_type="we-strobe" *) + (* external, signal_type="we-strobe", cd="lb" *) input scan_trigger_we, // external we-strobe // lb_clk domain, but only because I flag_xdomain to adc_clk - (* external, signal_type="single-cycle" *) + (* external, signal_type="single-cycle", cd="lb" *) input rawadc_trig, // external single-cycle - (* external *) - input [9:0] adc_downsample_ratio, // external // adc_clk domain + // newad-force clk1x domain + (* external *) + input [9:0] adc_downsample_ratio, // external (* external *) input [9:0] sync_ad7794_cset, // external (* external *) @@ -219,6 +219,12 @@ assign clk_status = clk_status_r; flag_xdomain rawadc_trig_xdomain (.clk1(lb_clk), .flagin_clk1(rawadc_trig), .clk2(adc_clk), .flagout_clk2(rawadc_trig_x)); +// One more clock-domain change, so idelay_scanner can run in pure lb_clk domain +wire [127:0] permuted_data; // from banyan_mem +wire [15:0] scanner_adc_val = permuted_data[15:0]; +reg [15:0] scanner_adc_val_r=0; +always @(posedge lb_clk) scanner_adc_val_r <= scanner_adc_val; + // 16 idelay registers mapped to lb_addr 112-127 // See idelay_base in static_oscope_regmap.json wire scan_running; @@ -227,8 +233,6 @@ wire [4:0] hw_data; wire hw_strobe; wire [7:0] scanner_banyan_mask; wire [2:0] scanner_adc_num; // not used -wire [127:0] permuted_data; // from banyan_mem -wire [15:0] scanner_adc_val = permuted_data[15:0]; wire lb_idelay_write = lb_strobe & ~lb_rd & (lb_addr[23:4] == 20'h19007); idelay_scanner #(.use_decider(1)) scanner( .lb_clk(lb_clk), .lb_addr(lb_addr[3:0]), .lb_data(lb_dout[4:0]), @@ -240,7 +244,7 @@ idelay_scanner #(.use_decider(1)) scanner( .debug_sel(scanner_debug[4]), .debug_addr(scanner_debug[3:0]), .hw_addr(hw_addr), .hw_data(hw_data), .hw_strobe(hw_strobe), .banyan_mask(scanner_banyan_mask), .adc_num(scanner_adc_num), - .adc_clk(adc_clk), .adc_val(scanner_adc_val) + .adc_clk(lb_clk), .adc_val(scanner_adc_val_r) ); // process the output hw_ bus from idelay_scanner, sending to IDELAYE2 @@ -315,20 +319,16 @@ assign zif_cfg.U2_dco_clk_in = zif_cfg.U2_dco_clk_out; `define CONFIG_PHASE_DIFF `ifdef CONFIG_PHASE_DIFF +wire err_ff_U2, err_ff_U3; +wire [12:0] phdiff_out_U2, phdiff_out_U3; +wire [13:0] vfreq_out_U2, vfreq_out_U3; // Measure the phases of the two BUFR outputs relative to adc_clk (U2's BUFR after MMCM and BUFG) -wire [12:0] clk_phase_diff_out_U2, clk_phase_diff_out_U3; -wire [13:0] clk_phase_diff_freq_U2, clk_phase_diff_freq_U3; -wire clk_phase_diff_locked_U2, clk_phase_diff_locked_U3; -phase_diff phase_diff_U2(.uclk1(zif_cfg.U2_clk_div_bufg), .uclk2(zif_cfg.U2_clk_div_bufr), .sclk(clk200), - .rclk(lb_clk), .phdiff_out(clk_phase_diff_out_U2), - .ext_div1(1'b0), .ext_div2(1'b0), - .vfreq_out(clk_phase_diff_freq_U2), .locked(clk_phase_diff_locked_U2)); -assign phase_status_U2 = {~clk_phase_diff_locked_U2, clk_phase_diff_freq_U2,4'b0, clk_phase_diff_out_U2}; -phase_diff phase_diff_U3(.uclk1(zif_cfg.U2_clk_div_bufg), .uclk2(zif_cfg.U3_clk_div_bufr), .sclk(clk200), - .rclk(lb_clk), .phdiff_out(clk_phase_diff_out_U3), - .ext_div1(1'b0), .ext_div2(1'b0), - .vfreq_out(clk_phase_diff_freq_U3), .locked(clk_phase_diff_locked_U3)); -assign phase_status_U3 = {~clk_phase_diff_locked_U3,clk_phase_diff_freq_U3,4'b0,clk_phase_diff_out_U3}; +phase_diff #(.delta(33)) phase_diff_U2(.uclk1(zif_cfg.U2_clk_div_bufg), .uclk2(zif_cfg.U2_clk_div_bufr), .uclk2g(1'b1), .sclk(clk200), + .rclk(lb_clk), .phdiff_out(phdiff_out_U2), .vfreq_out(vfreq_out_U2), .err_ff(err_ff_U2)); +phase_diff #(.delta(33)) phase_diff_U3(.uclk1(zif_cfg.U2_clk_div_bufg), .uclk2(zif_cfg.U3_clk_div_bufr), .uclk2g(1'b1), .sclk(clk200), + .rclk(lb_clk), .phdiff_out(phdiff_out_U3), .vfreq_out(vfreq_out_U3), .err_ff(err_ff_U3)); +assign phase_status_U2 = {err_ff_U2, vfreq_out_U2, 4'b0, phdiff_out_U2}; +assign phase_status_U3 = {err_ff_U3, vfreq_out_U3, 4'b0, phdiff_out_U3}; `else assign phase_status_U2 = 0; assign phase_status_U3 = 0; @@ -336,7 +336,9 @@ assign phase_status_U3 = 0; `define CONFIG_BANYAN `ifdef CONFIG_BANYAN -// Banyan-routed memory, simple one-shot fill for now +// Banyan-routed memory, that features a simple one-shot fill. +// Use rawadc_trig for a direct asynchronous fill, or rawadc_trig_req +// to start filling at the next external trigger (ext_trig). parameter banyan_aw = 14; // 8 blocks of RAM, each 16K x 16 reg banyan_run=0, banyan_run_d=0; wire rollover, full; diff --git a/projects/oscope/marble_family/Makefile b/projects/oscope/marble_family/Makefile index c0334cb4a..d31522b24 100644 --- a/projects/oscope/marble_family/Makefile +++ b/projects/oscope/marble_family/Makefile @@ -6,7 +6,8 @@ XILINX_TOOL := VIVADO include ../../../dir_list.mk -OSCOPE_COMMON_DIR=../common +OSCOPE_COMMON_DIR = ../common +MARBLE_FAMILY_DIR = ../../test_marble_family APP_NAME = oscope @@ -16,7 +17,7 @@ include $(BUILD_DIR)/newad_top_rules.mk include $(OSCOPE_COMMON_DIR)/rules.mk -VFLAGS_DEP += -y$(DSP_DIR) -y$(BOARD_SUPPORT_DIR)/marblemini -y$(BOARD_SUPPORT_DIR)/zest -y$(FPGA_FAMILY_DIR) -y$(FPGA_FAMILY_DIR)/xilinx -y$(FPGA_FAMILY_DIR)/iserdes -y$(ISERDES_DIR) -y$(XILINX_DIR) -y$(SERIAL_IO_DIR) -y. -y$(PERIPH_DRIVERS_DIR) -y$(PERIPH_DRIVERS_DIR)/idelay_scanner -y$(OSCOPE_COMMON_DIR) -y$(HOMELESS_DIR) -y$(BADGER_DIR) -y$(BADGER_DIR)/tests -y$(BADGER_DIR)/tests/kc705 -y../../test_marble_family/ -y../../test_marble_family/pps_lock -y$(PERIPH_DRIVERS_DIR)/i2cbridge -y$(HOMELESS_DIR)/freq_demo -DSIMULATE +VFLAGS_DEP += -y$(DSP_DIR) -y$(BOARD_SUPPORT_DIR)/marblemini -y$(BOARD_SUPPORT_DIR)/zest -y$(FPGA_FAMILY_DIR) -y$(FPGA_FAMILY_DIR)/xilinx -y$(FPGA_FAMILY_DIR)/iserdes -y$(SERIAL_IO_DIR) -y. -y$(PERIPH_DRIVERS_DIR) -y$(PERIPH_DRIVERS_DIR)/idelay_scanner -y$(OSCOPE_COMMON_DIR) -y$(HOMELESS_DIR) -y$(BADGER_DIR) -y$(BADGER_DIR)/tests -y$(BADGER_DIR)/tests/kc705 -y$(MARBLE_FAMILY_DIR) -y$(MARBLE_FAMILY_DIR)/pps_lock -y$(PERIPH_DRIVERS_DIR)/i2cbridge -y$(HOMELESS_DIR)/freq_demo -DSIMULATE LB_AW = 23 NEWAD_DIRS += $(OSCOPE_COMMON_DIR) @@ -26,7 +27,7 @@ RTEFI_EXTRA_V = spi_flash_engine.v include $(BADGER_DIR)/rules.mk $(AUTOGEN_DIR)/moving_average.v: $(DSP_DIR)/moving_average/moving_average.py - $(PYTHON) $(DSP_DIR)/moving_average/moving_average.py > $(AUTOGEN_DIR)/moving_average.v + $(PYTHON) $(DSP_DIR)/moving_average/moving_average.py | grep -v '(* top' > $@ oscope_features: $(BUILD_DIR)/gen_features.py oscope_features.yaml $(PYTHON) $< -i $(filter %.yaml, $^) -c marble_v2 --split @@ -47,10 +48,36 @@ zest_connector.csv: remap_gen.py system_top.xdc: $(BOARD_SUPPORT_DIR)/$(HARDWARE)/Marble.xdc $(BOARD_SUPPORT_DIR)/$(HARDWARE)/pin_map.csv zest_connector.csv oscope_rules.csv $(PYTHON) $(BADGER_DIR)/tests/meta-xdc.py $^ > $@ -oscope_top.sv: $(AUTOGEN_DIR)/config_romx.v $(RTEFI_V) application_top_auto $(AUTOGEN_DIR)/moving_average.v oscope_marble2_features +oscope_top.sv: $(AUTOGEN_DIR)/config_romx.v $(RTEFI_V) $(AUTOGEN_DIR)/application_top_auto.vh $(AUTOGEN_DIR)/addr_map_application_top.vh $(AUTOGEN_DIR)/moving_average.v oscope_marble2_features oscope_top.bit: $(AUTOGEN_DIR)/config_romx.v +# ===== +# highly experimental and still somewhat messy +# sv2v not supplied; see https://github.com/zachjs/sv2v +UPPER_SV = oscope_top.sv $(OSCOPE_COMMON_DIR)/application_top.sv $(BOARD_SUPPORT_DIR)/zest/zest_cfg_if.sv $(BOARD_SUPPORT_DIR)/zest/zest_if.sv $(BOARD_SUPPORT_DIR)/zest/zest_wrap.sv $(OSCOPE_COMMON_DIR)/digitizer_config.sv +oscope_prep.v: $(AUTOGEN_DIR)/application_top_auto.vh $(AUTOGEN_DIR)/addr_map_application_top.vh oscope_marble2_features + sv2v -DSIMULATE -DVERILATOR -I $(AUTOGEN_DIR) $(UPPER_SV) > $@ + wc -l $@ +oscope_pure_v.d: oscope_prep.v $(AUTOGEN_DIR)/config_romx.v $(RTEFI_V) $(AUTOGEN_DIR)/moving_average.v + $(VERILOG) -Wno-timescale -o /dev/null $< -y$(AUTOGEN_DIR) $(VFLAGS_DEP) -M$@.$$$$ && sort -u < $@.$$$$ | tr '\n' ' ' | sed -e 's/^/oscope_pure_v_check oscope_prep_yosys.json: /' -e 's/ $$//' > $@ && rm $@.$$$$ +# make this dependency file first, explicitly, if you are doing sv2v/cdc_snitch work +dep: oscope_pure_v.d +-include oscope_pure_v.d +.PHONY: oscope_pure_v_check dep +# dependencies from oscope_pure_v.d +# sv2v tends to make a lot of VARHIDDEN +# I don't like the 33 x UNDRIVEN +VLATOR_LINT_IGNORE += -Wno-UNUSED -Wno-VARHIDDEN -Wno-DECLFILENAME -Wno-CASEINCOMPLETE +VLATORFLAGS += -DSIMULATE +oscope_pure_v_check: + $(VERILATOR_LINT) +YOSYS_JSON_OPTION += -DSIMULATE +# most dependencies from oscope_pure_v.d +oscope_prep_yosys.json: $(FPGA_FAMILY_DIR)/xilinx/IBUFGDS.v +# exercise with make dep && make oscope_prep_cdc.txt +# ===== + $(AUTOGEN_DIR)/config_romx.v: $(BUILD_DIR)/build_rom.py $(APP_NAME)_regmap.json $(PYTHON) $< -v $@ -j $(APP_NAME)_regmap.json @@ -71,12 +98,13 @@ $(APP_NAME)_regmap.json: $(AUTOGEN_DIR)/regmap_application_top.json scalar_$(APP $(PYTHON) $(OSCOPE_COMMON_DIR)/shorten_names.py -o $@ -i $(APP_NAME)_regmap_long.json download: - openocd -f ../../test_marble_family/marble.cfg -c "transport select jtag; init; xc7_program xc7.tap; pld load 0 oscope_top.bit; exit" + openocd -f $(MARBLE_FAMILY_DIR)/marble.cfg -c "transport select jtag; init; xc7_program xc7.tap; pld load 0 oscope_top.bit; exit" include $(BUILD_DIR)/bottom_rules.mk CLEAN += *.bit *.bin *.prm $(APP_NAME)_regmap*.json scalar_$(APP_NAME)_regmap.json *_features*.json *_features*.vh oscope_marble*_features -CLEAN += system_top.xdc zest_connector.csv $(RTEFI_CLEAN) +CLEAN += system_top.xdc zest_connector.csv $(RTEFI_CLEAN) foo.gtkw foo.vcd +CLEAN += oscope_prep.v oscope_prep_yosys.json oscope_prep_cdc.txt oscope_pure_v.d CLEAN_DIRS += _xilinx .Xil ifneq (,$(findstring bit,$(MAKECMDGOALS))) diff --git a/projects/oscope/marble_family/oscope_top.sv b/projects/oscope/marble_family/oscope_top.sv index b865e6c27..65b8dc170 100644 --- a/projects/oscope/marble_family/oscope_top.sv +++ b/projects/oscope/marble_family/oscope_top.sv @@ -149,9 +149,12 @@ gmii_to_rgmii #(.in_phase_tx_clk(in_phase_tx_clk)) gmii_to_rgmii_i( ); wire BOOT_CCLK; +wire cfg_clk; // Just for fun, so we can measure its frequency `ifndef SIMULATE -STARTUPE2 set_cclk(.USRCCLKO(BOOT_CCLK), .USRCCLKTS(1'b0)); -`endif // `ifndef SIMULATE +STARTUPE2 set_cclk(.USRCCLKO(BOOT_CCLK), .USRCCLKTS(1'b0), .CFGMCLK(cfg_clk)); +`else +assign cfg_clk = 0; +`endif // Placeholders wire ZEST_PWR_EN; @@ -181,6 +184,25 @@ wire [1:0] FMC2_CK_N; wire [23:0] FMC2_HA_P; wire [23:0] FMC2_HA_N; +wire si570; +`ifdef USE_SI570 +// Single-ended clock derived from programmable xtal oscillator +ds_clk_buf #( + .GTX (1)) +i_ds_gtrefclk1 ( + .clk_p (GTREFCLK_P), + .clk_n (GTREFCLK_N), + .clk_out (si570) +); +`else +assign si570 = 0; +`endif + +// Works +reg bad_slow_clock=0; +always @(posedge tx_clk) bad_slow_clock <= ~bad_slow_clock; +wire clk62 = bad_slow_clock; + // Real, portable implementation // Consider pulling 3-state drivers out of this marble_base #( @@ -192,11 +214,12 @@ marble_base #( .vgmii_tx_en(vgmii_tx_en), .vgmii_tx_er(vgmii_tx_er), .vgmii_rx_clk(vgmii_rx_clk), .vgmii_rxd(vgmii_rxd), .vgmii_rx_dv(vgmii_rx_dv), .vgmii_rx_er(vgmii_rx_er), - .phy_rstn(PHY_RSTN), .clk_locked(clk_locked), + .phy_rstn(PHY_RSTN), .clk_locked(clk_locked), .si570(si570), .boot_clk(BOOT_CCLK), .boot_cs(BOOT_CS_B), .boot_mosi(BOOT_MOSI), .boot_miso(BOOT_MISO), .cfg_d02(CFG_D02), .mmc_int(MMC_INT), .ZEST_PWR_EN(ZEST_PWR_EN), - .aux_clk(SYSCLK_P), .GPS(4'b0), + .aux_clk(SYSCLK_P), .clk62(clk62), .cfg_clk(cfg_clk), + .GPS(4'b0), .SCLK(SCLK), .CSB(CSB), .MOSI(MOSI), .MISO(MISO), .FPGA_RxD(FPGA_RxD), .FPGA_TxD(FPGA_TxD), .twi_scl({dum_scl, old_scl1, old_scl2, TWI_SCL}), diff --git a/projects/test_marble_family/Makefile b/projects/test_marble_family/Makefile index 602e2189b..9791dd4bb 100644 --- a/projects/test_marble_family/Makefile +++ b/projects/test_marble_family/Makefile @@ -41,7 +41,7 @@ vpath %.c $(BADGER_DIR)/tests $(BUILD_DIR) include $(HOMELESS_DIR)/freq_demo/freq_demo_rules.mk # This must go in front of include $(BADGER_DIR)/rules.mk -all: lb_marble_slave_tb marble_base_tb no_multiple_drivers_check marble_base_lint gps_test_tb ltm_sync_tb Vmarble_base dna_check +all: lb_marble_slave_tb marble_base_tb no_multiple_drivers_check marble_base_lint gps_test_tb ltm_sync_tb Vmarble_base dna_check mmc_mailbox_check # ===== # gps_test, too simple to need testing ... right diff --git a/projects/test_marble_family/first_readout.sh b/projects/test_marble_family/first_readout.sh index 8288ce30b..bf607bf9f 100644 --- a/projects/test_marble_family/first_readout.sh +++ b/projects/test_marble_family/first_readout.sh @@ -9,7 +9,7 @@ echo "Reading kintex 7 internal temperature for $IP using XADC" python3 -m xadctemp -a $IP -p 803 echo "Reading kintex 7 DNA for $IP" python3 -m leep.cli leep://$IP:803 reg dna_high dna_low -echo "Connect Digilent 8 LED board to PMOD J12 and check if all them blink at different rate" +echo "Connect Digilent 8 LED board to Pmod J12 and check if all them blink at different rate" python3 -m leep.cli leep://$IP:803 reg led_user_mode=2 tt=$(mktemp /tmp/quick_XXXXXX) python3 -m spi_test --ip $IP --udp 804 --otp --pages=1 --dump $tt diff --git a/selfclean.sh b/selfclean.sh index f353a7eee..642accd82 100644 --- a/selfclean.sh +++ b/selfclean.sh @@ -27,3 +27,4 @@ make -C serial_io/chitchat clean make -C serial_io/EVG_EVR clean make -C soc/picorv32/test clean make -C fpga_family/xilinx clean +rm -r $(find * -name "__pycache__") diff --git a/soc/picorv32/gateware/uart_fifo_pack.v b/soc/picorv32/gateware/uart_fifo_pack.v index eb942b3dc..e1922df63 100644 --- a/soc/picorv32/gateware/uart_fifo_pack.v +++ b/soc/picorv32/gateware/uart_fifo_pack.v @@ -137,7 +137,9 @@ always @(posedge clk) begin if (|mem_wstrb && (mem_short_addr==UART_BAUDRATE)) begin if (mem_wstrb[0]) uprescale[ 7:0] <= mem_wdata[ 7:0]; if (mem_wstrb[1]) uprescale[15:8] <= mem_wdata[15:8]; +`ifndef YOSYS $display("new UART prescale value = 0x%04x", mem_wdata); +`endif end // ------------- // --- Reads ---