Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
14 years ago

how to create low freq clock ?

Hi all, I'm a hobbyist, and I'm a bit puzzled with the following :

I have a 100 mhz, a 12 mhz and 20 mhz clock at my disposal on a

cyclone1

I try to sample a signal (<100Khz) for a few millisecs.

In order to fit this in the memory I need a low sample freq. It seemed

handy to me to make the clock run slow (at 200Khz) so I get

a long period sampled with just a few memory cells (200 samples per msec)

now I get the feeling that you need a PLL to generate other clock freq.

but it seems I can only generate higher frequencies with the ALTPLL.

is this correct or am I overlooking something ?

I also understand that you should not create a clock from plain logic,

e.g. the following should not be done :

always @(posedge fastclk) counter <= counter +1;

assign slowclock = counter[7];

how am I supposed/advised to go about creating a low clock freq ?

thanks for any advice you can offer. if there is a link to a beginners guide to clocks, I would be very grateful too.

6 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    That is a common problem. Solution is torun on fast clock but each register enabled by slow rate through clkenable signal.

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    should the code look like this then for a low frequency "clock" ?

    your code review much appreciated !

    I have not yet succeeded in testing it ( a steep learning curve..) nor in writing a test bench. (how does one execute a test bench ?)

    
    module listen(clk, reset, start, data_in, data_out, data_valid, data_count);
    input clk;
    input reset;
    input start;
    input  data_in; // from ADC @ 100 Mhz
    output  data_out; 
    output data_valid;
    output addr;
    reg  data_out;
    reg data_valid;
    reg data_count;
    ///////////////////////////////////////////////////////////////////
    // start of listener
    // ADC runs at 100 mhz
    // 100 Mhz domain assumed
    // signal is downsampled :one in every 256 samples is processed
    // LPF filtering not posible : will not fit chip
    // todo : make smaller LPF filter
    // busy goes high as soon as start is received
    // see data_count for de-asserting busy signal
    always @(posedge clk) 
        if (~busy) busy <= start;
    // get and LPF the datastream 
    // sample rate is 100 Mhz, 
    // filter is designed with -3db point at 500 khz
    // signal is between 10 and 100 khz 
    // decimation by 200 ; next steps need 500 khz clock
    // beware time-delay !!
    // 
    // no space on chip for this
    //
    //ownfir myLPFfir(.Clk(clk),
    //   .dataIn(data_flash_reg),
    //    .dataOut(data_flash_reg1)
    //    );
    // create slow signal for slow sampling
    reg  clockdivider;
    always @(posedge clk) clockdivider <= clockdivider + 8'd1;
    // creates a 1-clk pulse every 256 clk pulses
    reg slowtick
    always @(posedge clk) slowclk <= (clockdivider == 8'b00000000) ; // divides by 256; should give 390625/sec ticks on 100Mhz clock
          
    // decimation       
    // select sample when slowtick is asserted 
    // do this also when not busy to keep feeding the filter
    reg signed  data_flash_reg;
    always @(posedge clk)
       if (slowtick) data_flash_reg <= $signed(data_in - 8'd128);
        
    // do matched filtering 
    // this answers over the previous 76 slowticks
    // for 76 taps, that is    
    ownmatch mymatch(.Clk(clk),.slow(slowtick),
        .dataIn(data_flash_reg),
         .dataOut(data_flash_reg2)
         );
         
    // back to unsigned, 
    // report unsigned to the outside world    
    always @(posedge clk) 
          if (slowtick && busy) 
           begin 
             data_out <= $unsigned(data_flash_reg2 + 8'sd127 + 8'sd1);    
              data_valid <= 1'b1;
            end 
            else data_valid <= 1'b0;
            
    // process for address generation
    // reg  data_count;
    // disregard the first 76 samples !!
    // todo : manage data_count/ data_valid to compensate for this lag
    //
    always @(posedge clk) 
    if (slowtick && busy) 
      data_count <= data_count + 12'd1;
    else
      if (~busy) data_count <= 12'd0;  
      
    // done when address space has been filled
    always @(posedge clk)
      if (slowtick && data_count == 12'b111111111111) busy <= 1'd0;
    endmodule