Search code examples
vhdlclock

Generate clocks with ratio for testbench


I want to generate a test stimulus for my I2S demux module. The stimulus contains values from an ADC measurement. The I2S standard provides two clocks: LRCLOCK and BITCLOCK. In my case LRCLOCK has a frequency of 48kHz (which is also the sample rate) and BITCLOCK is 64*LRCLOCK which results in a clock of 3.072MHz.

When creating the clocks in the testbench, there is always a offset between the LRCLOCK and the BITLCOCK. And I can't explain where this offset is coming from.

I tried to create a clock generation procedure according to this post: VHDL - How should I create a clock in a testbench?

Both suggested solutions show the same behaviour. I work with VIVADO 2016.4, the simulator has a resolution of 1ps

Procedure:

procedure clk_gen(signal clk : out std_logic; constant FREQ : real) is
    constant PERIOD    : time := 1 sec / FREQ;        -- Full period
    constant HIGH_TIME : time := PERIOD / 2;          -- High time
    constant LOW_TIME  : time := PERIOD - HIGH_TIME;  -- Low time; always >= HIGH_TIME
  begin
    -- Check the arguments
    assert (HIGH_TIME /= 0 fs) report "clk_plain: High time is zero; time resolution to large for frequency" severity FAILURE;
    -- Generate a clock cycle
    loop
      clk <= '1';
      wait for HIGH_TIME;
      clk <= '0';
      wait for LOW_TIME;
    end loop;
  end procedure;

Clock assignment:

process
    begin
        i2s_lrclock <= '1';
        wait until reset /= '1';
        clk_gen(i2s_lrclock,48.0e3);
   end process;

 process
   begin
       i2s_bitclock <= '1';
       wait until reset /= '1';
       clk_gen(i2s_bitclock,48.0e3*64);
  end process;

I expect the edges of both clocks to be synchronous but there is an offset of 26ps from the i2s_bitclock to i2s_lrclock.


Solution

  • A 3.072MHz clock has a period of 325.5208333... ns, the simulator has to trunk the period somewhere, and it's probably not on the same digit for your other clock.

    Try something like that :

    signal i2s_lrclock   : std_logic := '0';
    signal i2s_bitclock  : std_logic := '0';
    
    begin
    
      i2s_lrclock   <= not(i2s_lrclock) after 10416640 ps;  -- 64 * 325.520 ns / 2
      i2s_bitclock  <= not(i2s_bitclock) after 162760 ps ;  -- 325.520 ns / 2
    

    Real value of clocks in simulation is not very important. Ratio between them is.