6

I was wondering how can i write a verilog program for a tick counter. When the fast input is low, the output tick is high for one cycle every 150 ms (every 7500000 cycles) The clk period is 20ns. If the fast input is high, tick should go high for one cycle every other clock cycle.

I'm thinking that I should count the clk cycles and use the count to output tick as high when the number of cycles are met but I can't seem to get it to work.

heres my code:

module tick_counter(
  input  clk,
  input  reset,
  input  fast,
  output reg tick
);

reg count;

always @(posedge clk) begin
  count <= count + 1;
  if((fast == 1)&&(count == 2)) begin
    tick <= 1;
  end
  else if(fast == 0)&&(count == 7500000)) begin
    tick <= 1;
  end
end
endmodule
Infinite Recursion
  • 6,511
  • 28
  • 39
  • 51
intensified
  • 159
  • 3
  • 4
  • 10

2 Answers2

4

Your counter is only 1 bit wide, you have not included a reset, You also do not zero the counter when required. The ==2 would just be a phase shift of == 7500000. Try :

module tick_counter(
  input  clk,
  input  reset,
  input  fast,
  output reg tick
);

reg [22:0] count;

always @(posedge clk or negedge reset) begin
  if (~reset) begin
    count <= 'd0;
    tick  <=   0;
  end
  else begin
    if((fast == 1)&&(count == 2)) begin
      tick  <= 1;
      count <= 'd0;
    end
    else if(fast == 0)&&(count == 7500000)) begin
      tick  <= 1;
      count <= 'd0;
    end
    else begin
      tick  <= 0;
      count <= count + 1;
    end
  end
end
endmodule

Or something like the following might synthesise smaller:

reg  [22:0] count;

wire [22:0] comp = (fast) ? 23'd2: 23'd7500000 ;
wire        done = count >= comp               ;

always @(posedge clk or negedge reset) begin
  if (~reset) begin
    count <= 'd0;
    tick  <=   0;
  end
  else begin
    if(done) begin
      tick  <= 1;
      count <= 'd0;
    end
    else begin
      tick  <= 0;
      count <= count + 1;
    end
  end
end
Morgan
  • 19,934
  • 8
  • 58
  • 84
  • 1
    You'd probably want `if((fast == 1)&&(count >= 2)) begin`, since if `fast` goes to 1 somewhere between 3 and 749999, and stays 1 until 750001, no condition would trigger. – Dax Fohl Sep 06 '12 at 13:25
  • Or else you could store a `reg previous_fast`, and just set `count` to zero whenever `fast != previous_fast`. That would probably synthesize smaller, and wouldn't trigger a `tick` in the reset condition of my above comment; depends on your requirement. – Dax Fohl Sep 06 '12 at 13:29
  • @DaxFohl, you are correct. I have added another example with a shared comparator, and using >= which also help protect against glitches. – Morgan Sep 06 '12 at 17:18
0

Fewer gates - no comparator - just use down-counter:

module tick_counter(  
  input  wire clk,  
  input  wire resetn,  
  input  wire fast,  
  output reg  tick);  

  reg  [22:0] count;  

  wire [22:0] load = (fast) ? 23'd2: 23'd7500000;  
  wire        done = !count;  

  always @(posedge clk or negedge resetn) begin  
    if (!resetn) begin  
      count <= 23'd0;  
      tick  <= 1'b0;  
    end else begin  
      tick  <= 1'b0;  
      count <= count - 23'd1;  
      if(done) begin  
        tick  <= 1'b1;  
        count <= load;  
      end  
    end  
  end  
endmodule//tick_counter  

Otherwise, if you prefer an up-counter invert the literal.

SysTom
  • 21
  • 3