Skip to content

Latest commit

 

History

History
269 lines (210 loc) · 16.3 KB

mmcm.md

File metadata and controls

269 lines (210 loc) · 16.3 KB

Clocking and Metastability

In this assignment you will learn how to use the MMCM primitive to create a deskewed clock, clocks of various frequency, and phase, and to induce metastability. You will use the switches, buttons, seven segment display, and LEDs to interact with your clocking circuit.

Top-Level Design

This assignment will involve the creation of a single top-level design. Create your top-level design with the name mmcm_top.sv and with following ports and parameters.

Port Name Direction Width Function
CLK100MHZ Input 1 Clock
CPU_RESETN Input 1 Reset (low asserted)
SW Input 4 Switches (Determine which counter to display)
LED Output 4 Board LEDs (display the switches)
AN Output 8 Anode signals for the seven segment display
CA, CB, CC, CD, CE, CF, CG 1 each Output Seven segment display cathode signals
DP Output 1 Seven segment display digit point signal
Parameter Name Default Value Purpose
CLK_FREQUENCY 100_000_000 Specify the clock frequency
SEGMENT_DISPLAY_US 1_000 The amount of time in microseconds to display each digit (1 ms)

Main MMCM

The first step in this assignment is to create your "Main" MMCM that is used to deskew the input clock and generate a variety of clocks. Instance the "MMCME2_BASE" primitive into your design and hook it up as described below. You can learn more about primitives that can be instantiated at the following library guide. Note that you can look at the text for the module definition of this primitive in the following file: <Xilinx>/Vivado/<version>/data/verilog/src/unisim_comp.v

  • Use the board RST to reset this MMCM
    • Although the reset button signal doesn't really need to be synchronized for this situation, it is a good idea to add a synchronizer to clean up the signal a bit (avoid lots of high frequency glitches). These synchronizers should be clocked by the free running 100 MHz board clock (not any of the generated clocks from the MMCM).
  • Configure the MMCM and instance BUFGs so that the MMCM performs a "deskew" function (Figure 3-11) on the input 100 MHz clock. The CLKOUT0 should be in phase with the input clock and have a 50% duty cycle
  • Make sure all inputs to the MMCM have a value (use a constant if it is not used)
  • Create additional clock outputs with the following requirements:
    • CLKOUT1: Same clock frequency as input, phase shifted 180 degrees, 25% duty cycle
    • CLKOUT2: Same clock frequency as input, phase shifted 90 degrees, 75% duty cycle
    • CLKOUT3: Lower clock frequency than input, out of phase with input. Do not use power of 2 divide and make this at least 6x lower frequency than the input.
    • CLKOUT4: Higher clock frequency than input, out of phase with input. Do not use power of 2 multiply and make this at least 2.5x greater than input clock.
    • CLKOUT5: Lower clock frequency than input (but different from CLKOUT3), in phase with input
    • CLKOUT6: Higher clock frequency than input (but different from CLKOUT4), in phase with input

Clock Domain Reset signals

You will need to create a separate reset signal for each of the clock domains you created. This reset signal will be used by the logic in each of the clock domains. The purpose of this reset signal is to provide a power up reset that is synchronous with the given clock domain.

A good example on how to do this can be found in Figure 4 of the following URL. This approach involves the following principles:

  • Provide several flip-flops in a chain for the reset signal (at least two as a synchronizer and a few more if you want more time for the reset)
  • The last flip-flop of this chain is your clock domain reset signal, the first flip-flop should have a '0' as its input (so that the 0 can propagate through the flip-flop chain)
  • These flip-flops should be asynchronously "Preset" when the MMCM Locked signal is low. This way, the reset signal going to the clock domain will be asserted immediacy when Locked goes low (i.e., when you lose a good clock)
  • These flip-flops should be clocked by clock signal generated by the MMCM that corresponds to the clock domain of interest.

Clock Domain Counters

Create 48-bit counters for each of the 7 clock domains. Each of these counters should be reset using the appropriate reset circuit created above. These counters will be referred to later in the description as CNT0, CNT1, ... CNT6.

Clock Domain Crossing Signals

For this part you will create enable signals in various clock domains and "count" these enable pulses in a different clock domain.

  • Create a single pulse in the CLKOUT3 domain that is asserted for one clock cycle every 4 clock cycles (PULSE3). Make sure this pulse is glitch free.
  • Create a single pulse in the CLKOUT4 domain that is asserted for one clock cycle every 100 clock cycles (PULSE4). Make sure this pulse is glitch free.
  • Create a 32-bit counter in the CLKOUT0 domain that counts the PULSE3 pulses. Note that you should only count once for each unique PULSE3 signal. This counter will be referred to as PULSE3CNT.
  • Create a 32-bit counter in the CLKOUT0 domain that counts the PULSE4 pulses. Note that you should only count once for each unique PULSE4 signal. This counter will be referred to as PULSE4CNT.

When synchronizing the pulse signal that crosses clock domains, you will want to use the ASYNC_REG attribute to instruct the synthesis tool that these signals are asynchronous. This attribute specifices that (1) A register can receive asynchronous data on the D input pin relative to its source clock and (2) a register is a synchronizing register within a synchronization chain. From the documentation Vivado Synthesis Guide, page 40:

Specifying ASYNC_REG also affects optimization, placement, and routing to improve mean time between failure (MTBF) for registers that can go metastable. If ASYNC_REG is applied, the placer will ensure the flip-flops on a synchronization chain are placed closely together to maximize MTBF. Registers that have this property that are directly connected will be grouped and placed together into a single SLICE/CLB, assuming they have a compatible control set and the number of registers does not exceed the available resources of the SLICE/CLB.

    (* ASYNC_REG = "TRUE" *) logic pulse3_clk0_d, pulse3_clk0_dd, pulse3_clk0_ddd;

Secondary MMCM

Instance a second MMCM that uses CLK0 as the input clock. Create a new clock from this MMCM that is a fractional value of the frequency of CLK0 (using prime numbers for M and D). Your resulting frequency should be between 50 MHz and 100 MHz. Do NOT use deskewing in this configuration (i.e., do not align the input CLK0 with this MMCM - see Figure 3-13). The goal here is to make a second MMCM that is not necessarily synchronous with the input clock (in most cases you would just make them synchronous). This MMCM should be reset when the first MMCM is not locked (i.e., the output of the first locked signal should drive the input of the second reset with an inverter so that the second MMCM doesn't start to operate until the first one has locked). Create a counter for this new clock domain named CNTB_0. This counter should be reset using an appropriate reset signal (i.e., a reset signal that is synchronous with the clock domain of CNTB_0).

Metastability Circuit

Create a signal in this new clock domain that toggles every clock cycle. This signal will be the "input" signal used for inducing metastability. Create a metastability detection circuit (see resources below)

The f_data signal is your toggling circuit created in the CNTB_0 clock domain. Use CLKOUT4 as the f_clk. Every time FF 'D' goes high, a metastability event has been detected. Create a counter in the CLKOUT4 clock domain that counts metastability events. This counter will be referred to as CNT_META.

Seven Segment Display

Instance the seven segment display in your design. Note that you should drive the seven segment display with the top-level clock that comes into the FPGA. If you use a clock generated by one of the MMCMs then your seven segment display will be disabled when you press the reset button. Make sure that your seven segment display does NOT display the digit points. Also, make sure the seven segment display still displays when the reset button is pressed (it should not blank during the rest process).

Create a mux that selects one of the counters you generated based on the value of the switches. Note that for the 48-bit counters, display only the top 32 bits of the counter. Place a register after this mux to synchronize the various counters in their different clock domains to the top-level clock (i.e., the same clock used by the seven segment display). You don't need two levels of synchronizers - just one to prepare the data for the seven segment display controller. It is possible you will get metastability, but this is not an issue for the seven segment display controller - you will never see it.

SW[3:0] Display
0x0 CNT0[47:16]
0x1 CNT1[47:16]
0x2 CNT2[47:16]
0x3 CNT3[47:16]
0x4 CNT4[47:16]
0x5 CNT5[47:16]
0x6 CNT6[47:16]
0x7 PULSE3CNT
0x8 PULSE4CNT
0x9 CNTB_0[47:16]
0xA CNT_META

Timing Constraints

In addition to the (* ASYNC_REG = "TRUE" *) attribute that you add to your HDL, you will need to add a number of additional timing constraints for this design. For every clock domain crossing signal, you will need to add a set_false_path constraint to your .xdc file. set_false_path -from [ get_cells clk0_cntr_reg[*] ] -to [get_cells ssd_sync_reg[*] ] Without this constraint, the timing analysis tool will try to resolve timing for two signals of different clock domains. The following situations provide examples of when you will need to add a set_false_path constraint: * The synchronizer for the pulse3 and pulse4 signals that are crossing clock domains * The synchronizer register used to synchronize the various counters to the top-level clock domain (for the seven-segment display) * The input to the "metastability A" FF used to detect metastability. The following example demonstrates this constraint:

# Sets a false path from counter0 to the ssd_sync register (all 32 bits)
# Note that Vivado adds the "_reg" name to your HDL name
set_false_path -from [ get_cells clk0_cntr_reg[*] ] -to [ get_cells ssd_sync_reg[*] ]
# Sets a false path from the pulse3_reg signal to the synchronizer signal in another clock
# domain.
set_false_path -from [ get_cells pulse3_reg ] -to [ get_cells pulse3_clk0_d_reg ]

Testbench

Create a top-level testbench named mmcm_top_tb.sv that simulates your design. This testbench should demonstrate e your clocking, counter circuits, seven segment display and mux are all working properly. This testbench is relatively simple and should just issue a reset signal, wait for the MMCMs to lock, and run for long enough to demonstrate the proper operation of all the clocks and counters. Create a makefile rule sim_mmcm that performs this simulation from the command line.

Add a timescale directive to your testbench as follows (you will need picosecond resolution for this simulation):

`timescale 1ns / 1ps

Run your simulation in the GUI mode and create a waveform that demonstrates the proper operation of each of your 7 clocks. Take a screenshot of each waveform. Use markers to measure the frequency/period, the phase offset, and the duty cycle.

Implementation and Download

Create a makefile rule gen_bit that generates a bitstream for your top-level design named mmcm.bit. Make sure your design meets the timing constraint and doesn't have any errors or warnings. Download your design and make sure it operates as expected.

Design Timing Analysis

Carefully review the timing analysis file for your design. From this file, answer the following questions in your report:

  • Determine the worst case negative slack
    • What are the source and destination of this signal?
    • What is the clock skew between the source and destination clocks of this signal?
  • Determine the worst hold time constraint
    • What are the source and destination of this signal?
    • What is the clock skew between the source and destination clocks of this signal?
  • How many design endpoints are there in your design?

Submission

The assignment submission steps are described in the assignment mechanics checklist page. Carefully review these steps as you submit your assignment.

The following assignment specific items should be included in your repository:

  1. Required Makefile rules:
  • sim_mmcm
  • gen_bit
  1. You need to have at least 3 "Error" commits in your repository
  2. Assignment specific Questions:
  • Provide a summary of the number of resources your design uses (see the output from the utilization report).
  • Provide an inline image of each of your waveforms demonstrating the proper operation of each of your 7 clocks (don't forget to add the appropriate markers as described above)
  • Provide your timing analysis results