Ich bin neu in Verilog und HDL.
Ich möchte einen N-Frequenzteiler implementieren,
die zählen Tick-Ticks (pos und neg) und starten Sie den Zählmechanismus von der ersten steigenden Flanke des Eingangs clk.
Zusätzlich muss der clk-Teiler synchrone rst_n unterstützen.vermeiden Sperren in frequencny Teiler mit Fsm - Verilog
Ich bin mit Altera Quartus und dem folgenden Code
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
Nach der Synthese I erhalten Warnungen über Verriegelungen für cnt Register verwendet.
Was mache ich falsch?
Können Sie mir Tipps für gute Praktiken geben, um solche Fälle in der Zukunft zu vermeiden, oder elegantere Möglichkeiten, diese Art von RTL zu implementieren?
dank
vielen Dank für Ihre Antwort. Ich versuche, einen einfachen Taktteiler für Lernzwecke zu implementieren. Warum gibt es Verriegelungen mit dem obigen Design? – vintox
Es gibt Zwischenspeicher, weil Sie nicht vollständig synchron sind. – FabienM
Die Latches werden für Cnt-Register nicht für Out- oder Out_change-Register verwendet. Warum beeinflusst der Mechanismus out_change den Zähler des Zustandsautomaten? – vintox