VerilogとHDLを初めて使用しています。
クロッククロック(正と負)をカウントし、入力clkの最初の立ち上がりエッジからカウント機構を開始するN分周器
を実装したいと思います。
さらに、clk分周器は同期rst_nをサポートしなければなりません。fsmを使用してfrequecny dividerのラッチを避ける - Verilog
私はCNTレジスタに使用ラッチについての警告を取得し、アルテラのQuartusし、次のコードの合成後
module clk_divider_fsm
(
\t in_clk,
\t rst_n,
\t out_clk
);
input in_clk, rst_n;
output out_clk;
parameter prescaler = 10;
parameter BIT_DEPTH = `CLOG2(prescaler);
parameter S0 = 2'b00, S1 = 2'b01, S2 = 2'b10;
parameter CNT_RESET = {BIT_DEPTH{1'b0}};
//parameter CNT_FIRST = {BIT_DEPTH-1{1'b0}, 1'b1};
reg [1:0] ps, ns;
reg out_change;
reg out;
reg [BIT_DEPTH:0] cnt;
initial
begin
\t ps = S0;
\t ns = S0;
\t cnt = CNT_RESET;
\t out_change = 1'b0;
\t out = 1'b0;
end
always @ (in_clk)
begin
\t if(!rst_n)
\t \t ps = S0;
\t else
\t \t ps = ns;
// \t begin
// \t \t if(ns != ps)
// \t \t \t ps = ns;
// \t end
end
always @ (in_clk)
begin
\t case(ps)
\t \t S0: begin
\t \t \t if(in_clk === 1'b1)
\t \t \t begin
\t \t \t \t out_change <= 1'b1;
\t \t \t \t ns <= S1;
\t \t \t \t cnt <= CNT_RESET + 1'b1;
\t \t \t end
\t \t \t else
\t \t \t begin
\t \t \t \t out_change <= 1'b0;
\t \t \t \t cnt <= CNT_RESET;
\t \t \t \t ns <= S0;
\t \t \t end
\t \t end
\t \t S1: begin
\t \t \t if(in_clk === 1'b0)
\t \t \t begin
\t \t \t \t if(cnt == prescaler)
\t \t \t \t begin
\t \t \t \t \t cnt <= CNT_RESET + 1'b1;
\t \t \t \t \t out_change <= 1'b1;
\t \t \t \t \t ns <= S2;
\t \t \t \t end
\t \t \t \t else
\t \t \t \t begin
\t \t \t \t \t cnt <= cnt + 1'b1;
\t \t \t \t \t out_change <= 1'b0;
\t \t \t \t \t ns <= S2;
\t \t \t \t end
\t \t \t end
\t \t \t else
\t \t \t begin
\t \t \t \t out_change = 1'b0;
\t \t \t \t ns = S1;
\t \t \t \t cnt <= cnt;
\t \t \t end
\t \t end
\t \t
\t \t S2: begin
\t \t \t if(in_clk == 1'b1)
\t \t \t begin
\t \t \t \t if(cnt == prescaler)
\t \t \t \t begin
\t \t \t \t \t cnt <= CNT_RESET + 1'b1;
\t \t \t \t \t out_change <= 1'b1;
\t \t \t \t \t ns <= S1;
\t \t \t \t end
\t \t \t \t else
\t \t \t \t begin
\t \t \t \t \t cnt <= cnt + 1'b1;
\t \t \t \t \t out_change <= 1'b0;
\t \t \t \t \t ns <= S1;
\t \t \t \t end
\t \t \t end
\t \t \t else
\t \t \t begin
\t \t \t \t out_change = 1'b0;
\t \t \t \t ns = S2;
\t \t \t \t cnt <= cnt;
\t \t \t end
\t \t end
\t \t default: begin
\t \t \t out_change <= 1'b0;
\t \t \t cnt <= CNT_RESET;
\t \t \t ns <= S0;
\t \t end
\t endcase
\t
\t if(!rst_n)
\t begin
\t \t ns <= S0;
\t \t cnt <= CNT_RESET;
\t end
end
always @ (posedge out_change or negedge rst_n)
begin
\t if(!rst_n)
\t \t out <= 1'b0;
\t else
\t \t out <= ~out;
end
assign out_clk = (prescaler == 1) ? (in_clk & rst_n) : out;
endmodule
を使用しています。
何が間違っていますか?
このようなケースを避けるための良い練習のヒントや、これらの種類のRTLを実装するより洗練された方法を教えてもらえますか?
おかげ
を参照してくださいあなたの答えをありがとうございました。私は学習目的のための簡単なクロック分周器を実装しようとしています。上記のデザインを使用しているラッチはなぜですか? – vintox
完全に同期していないため、ラッチがあります。 – FabienM
ラッチはoutレジスタとout_changeレジスタではなくcntレジスタに使用されます。なぜout_changeメカニズムがステートマシンカウンタに影響を与えているのですか? – vintox