Как написать синтезируемый 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.

Другие вопросы по тегам