简体   繁体   中英

How to make such a clock counter in Verilog HDL?

I want to make a counter which can start counting at posedge of a specific signal. And once it counts to 256, stop counting, set the counter to 0 and output something.

I wrote the following code, but apparently it'll cause a "multiple driver" error.

But I can't think of another way. Can someone provide an idea?

always@(posedge a_specific_signal)
begin
    counter_switch <= 1;
end

always@(posedge clk)
begin
if (counter_switch  == 1)
    counter <= counter + 1;
if (counter == 256)  
    begin   
        counter <= 0;  
        counter_switch <= 0; 
        something <= 1; 
    end
end

You can't change the value of counter_switch in two different always statements. You need to do that within the same always block.

I'd do something like this: (didn't test the code could contain bugs)

input clock, reset;

reg counter_switch, ready;
reg [7:0] counter;

always@(posedge clock) begin
    if (reset) begin
        counter_switch <= 0;
    end else begin 
        if (a_specific_signal) begin 
            counter_switch <= 1;
        end else if (ready) begin
            counter_switch <= 0;
        end 
    end 
end

always@(posedge clock) begin
    if (reset) begin 
        ready <= 0;
        counter <= 0;
    end else begin
        if (counter_switch) begin 
            if (counter == 255) begin   
                counter <= 0;  
                ready <= 1; 
            end else begin 
                counter <= counter + 1;
            end
        end else begin 
            ready <= 0;
        end
    end
end

Here is your counter, for 0 to 256 count.

module counter (clk, reset, op);
  input logic clk, reset;
  output logic [16:0] op;

  logic [16:0] current_cnt, next_cnt;

  assign next_cnt = (current_cnt[16]) ? 17'd0 : (current_cnt + 17'd1);
  assign op = current_cnt;

  always @ (posedge clk, negedge reset)
  begin
    if (~reset)
      current_cnt <= 17'd0;
    else 
      current_cnt <= next_cnt;
  end
endmodule

So whenever you reach to 256, then your 17th bit of current_cnt will be 1, which means that your next_cnt should be 0. In all other cases, your next count should be +1.

The "multiple driver" error arises from trying to modify a signal from different processes / always blocks. You shouldn't do this.

I'm used to working with fully synchronic systems, so I should ask you what "a_specific_signal" is like, and what the relationship to your main clock is.

Hence my approach would be: 1. synchronizing "a_specific_signal" to my current clock, 2. detecting its positive edges, 3. using this as a drive for a flag for my counter

reg a_spec_signal_reg0 = 1'b0, a_spec_signal_reg1 = 1'b0, a_spec_signal_reg2 = 1'b0;

always @(posedge clk) begin --synchronizer with 3 FFs
  a_spec_signal_reg0 <= a_specific_signal;
  a_spec_signal_reg1 <= a_spec_signal_reg0;
  a_spec_signal_reg2 <= a_spec_signal_reg1;
end

wire a_spec_signal_posedge;
assign a_spec_signal_posedge = a_spec_signal_reg1 & ~(a_spec_signal_reg2);

reg counter_switch = 1'b0;

always @(posedge clk) begin
  something <= 1'b0;
  if (a_spec_signal_posedge)
      counter_switch <= 1'b1;
  if (counter_switch) begin
      counter <= counter + 1;
      if (counter == 255) begin   
          counter <= 0;  
          counter_switch <= 0;
          something <= 1'b1;
      end
  end
end

A few notes: I assumed you wanted to count 256 events, so that means using a counter from 0 to 255 (8 bits). And also the something signal is set as 0 in its default state, so when the condition "counter == 255" arrives, it outputs a tick for just a clock cycle, which is what's usually used.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM