#counter #verilog
#счетчик #verilog
Вопрос:
Я новичок в Verilog, и, возможно, это глупый вопрос, но какой предпочтительный поток кода в Verilog для решения этой проблемы:
Простой счетчик, подсчитывающий внешний clk (INP) до определенного значения. Если счетчик соответствует значению, он увеличивает выходной провод (DRDY) на один период clk, а затем понижает его до 0. Существует внешний вход (SR), где я хотел бы установить значение сравнения, поэтому, если SR = 0, то подсчет составляет до 500000, если SR = 1, то до 1000000. Я могу сделать это с одним значением, но я хотел бы расширить функциональность моего модуля.
Заранее благодарю вас.
Мой код до сих пор с одним сравнением значений:
module ec(INP, RST, SR, DRDY, DRDY2);
input INP, RST, SR;
output reg DRDY, DRDY2;
reg [23:0] Q;
always @(posedge INP or negedge RST)
begin
if(!RST)
begin
Q <= 24'd0;
DRDY <= 1'b0;
end
else if( Q == 24'd1000000)
begin
Q <= 24'd0;
DRDY <= 1'b1;
DRDY2 <=~DRDY2;
end
else
begin
Q <= Q 1;
DRDY <= 1'b0;
end
end
endmodule
Ответ №1:
Простым способом обработки 2 вариантов было бы развернуть оператор if:
always @(posedge INP or negedge RST) begin
if(!RST) begin
Q <= 24'd0;
DRDY <= 1'b0;
end
else if(
( (SR ==1'b0) amp;amp; (Q == 24'd1000000) ||
(SR ==1'b1) amp;amp; (Q == 24'd500000)
) begin
//...
end
else begin
//..
end
Это может выглядеть довольно беспорядочно в коде, поэтому может быть выделено в целевую логику подсчета, если необходимо поддерживать дополнительные параметры, а затем переключиться на оператор case вместо if .
reg [23:0] cnt_target ;
always @* begin
if (SR == 1'b1) begin
cnt_target = 24'd1000000 ;
else begin
cnt_target = 24'd500000 ;
end
end
always @(posedge INP or negedge RST) begin
if(!RST) begin
Q <= 24'd0;
DRDY <= 1'b0;
end
else if( Q == cnt_target) begin
//...
end
else begin
//..
end
ПРИМЕЧАНИЕ: возможно, вы захотите рассмотреть возможность использования Q >= cnt_target
этого способа, если SR изменился на лету, вам не нужно ждать переполнения Q . Плюс >=
для меня имеет тенденцию к синтезу меньше, чем ==
.