Как написать синтезируемый RTL, который может считать рост и падение сигнала
Я хочу измерить количество переходов по нарастанию и падению сигнала. Я использую сигнал в качестве часов и реализовал 2 счетчика. Один счетчик увеличивается на каждом переднем фронте, а другой - на каждом переднем. Я добавляю результат этих 2 счетчиков, чтобы получить окончательное значение счетчика.
Есть ли лучший способ реализовать эту логику? Какой самый надежный метод?
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
1 ответ
В этом методе нет ничего плохого теоретически, но не принято использовать сигналы в качестве часов. Это вводит логику в генерацию ваших часов, что является громоздким (не невозможным) для физического дизайна или внутреннего потока и инструментов для работы.
[Есть по крайней мере дополнительный инвертор вместе с логикой, которую принесет входной сигнал]
пример в ссылке ниже - Правильный способ обнаружения края сигнала в Verilog
Если сигнал асинхронный и генерируется внешним модулем, вы можете синхронизировать его, тогда используйте логику детектора фронта. Затем используйте этот выход для запуска счета. https://www.doulos.com/knowhow/fpga/synchronisation/
Если есть доступ к часам, то лучше включить часы, чтобы обнаружить падающий и нарастающий фронт сигнала и использовать их для подсчета. Пример кода ниже.
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
Также в конце использование выхода (счетчика) будет в синхронном блоке, поэтому лучше использовать часы результирующего блока в clock_edge_counter.