Reputation: 21
I want to measure the number of rise transitions and fall transitions of a signal. I am using the signal as a clock and implemented 2 counters. One counter increments on every rising edge and another increments on every falling edge. I am adding the result of these 2 counters to get the final count value.
Is there a better way to implement this logic ? What is the most robust method ?
module clock_edge_counter (
clock_edge_count, // Output of the counter ,
clk , // clock Input
stop ,
reset
);
parameter CNTR_WIDTH = 16;
input clk ;
input stop ;
input reset ;
output [CNTR_WIDTH:0] clock_edge_count;
wire [CNTR_WIDTH:0] clock_edge_count;
reg [CNTR_WIDTH-1:0] clock_negedge_edge_count;
reg [CNTR_WIDTH-1:0] clock_posedge_edge_count;
always @(posedge clk or posedge reset)
if (reset) begin
clock_posedge_edge_count <= 0;
end
else if (!stop) begin
clock_posedge_edge_count <= clock_posedge_edge_count + 1;
end
always @(negedge clk or posedge reset)
if (reset) begin
clock_negedge_edge_count <= 0;
end
else if (!stop) begin
clock_negedge_edge_count <= clock_negedge_edge_count + 1;
end
assign clock_edge_count = clock_negedge_edge_count + clock_posedge_edge_count;
endmodule
Upvotes: 1
Views: 2371
Reputation: 792
There is nothing wrong theoritically with this method, but it is not a standard practice to use signals as clocks. This introduces logic into your clock generation which is cumbersome (not impossible) for the physical design or backend flow and tools to deal with.
[There is at least an extra inverter together with the logic the input signal will bring]
example in the link below - Proper way for signal edge detection in Verilog
If the signal is asynchronous and being generated from an external module you can synchronize it , then use edge detector logic. Then use that output to trigger the count. https://www.doulos.com/knowhow/fpga/synchronisation/
If there is access to the clock then it better to get the clock in to detect the falling and rising edge of the signal and use it to count. Example code below.
module clock_edge_counter (
clock_edge_count, // Output of the counter ,
clk , // clock
detect , // signal to be checked
stop ,
reset
);
parameter CNTR_WIDTH = 16;
input clk ;
input detect;
input stop ;
input reset ;
output [CNTR_WIDTH:0] clock_edge_count;
reg [CNTR_WIDTH:0] clock_edge_count;
reg detect_d;
always @(posedge clk or posedge reset)
begin
if (reset)
detect_d <= 0 ;
else
detect_d <= detect; // delay signal by one cycle
end
always @(posedge clk or posedge reset)
if (reset) begin
clock_edge_count <= 0;
end
// rising edge or falling edge ( xor logic )
else if (!stop && ( (!detect && detect_d ) || (detect && !detect_d ) ) )
begin
clock_edge_count <= clock_edge_count + 1;
end
endmodule
Also at the end the use of the output ( counter ) would be in a synchronous block , so its better to use the clock of the resulting block in the clock_edge_counter.
Upvotes: 3