Ich habe einen Taktteiler wie folgt implementiert:
module sync_out(
input clk, // This is the FPGA system clock
output reg sync // This is the generated sync signal to be tested
);
localparam
SYNC_OUT_CLOCK_RATIO = 20;
reg [10:0] counter; // Clock counter reset when reaching CLOCK_RATIO
initial begin
counter <= 0;
sync <= 0;
end
always @(posedge clk) begin
counter <= counter + 1;
if(counter == SYNC_OUT_CLOCK_RATIO) begin
counter <= 0;
sync <= ~sync;
end
end
endmodule
Hier clk
ist der Haupttakt und sync
der geteilte Takt, der direkt aus der Platine ausgegeben wird. Jetzt gibt mir ISE den folgenden Fehler:
Place:1136 - This design contains a global buffer instance,
<clock_deskew_0/BUFG_inst>, driving the net, <clk>, that is driving the
following (first 30) non-clock load pins.
< PIN: sync_apbinterface_0/pclk_test_select[15]_AND_253_o4.A4; >
This is not a recommended design practice in Spartan-6 due to limitations in
the global routing that may cause excessive delay, skew or unroutable
situations. It is recommended to only use a BUFG resource to drive clock
loads. If you wish to override this recommendation, you may use the
CLOCK_DEDICATED_ROUTE constraint (given below) in the .ucf file to demote
this message to a WARNING and allow your design to continue.
< PIN "clock_deskew_0/BUFG_inst.O" CLOCK_DEDICATED_ROUTE = FALSE; >
Was genau ist hier das Problem und wie kann ich es beheben?
Ihr clk
Pin treibt einige Nicht-Takt-Pins an (LUT-Eingänge, wie es aussieht). Das ist fast immer eine schlechte Idee.
Öffnen Sie Ihr Design im Technologie-Viewer und sehen Sie sich die in der Protokolldatei (ist die erste) aufgeführten "Nicht-Takt-Ladestifte" an < PIN: sync_apbinterface_0/pclk_test_select[15]_AND_253_o4.A4; >
und sehen Sie, ob Sie herausfinden können, warum eine LUT den CLK-Eingang verwendet.
Wenn sich herausstellt, dass alles in Ordnung ist und Sie dies aus irgendeinem Grund wirklich tun möchten, und Sie dies gerne vor einer bellenden Meute von Ingenieuren rechtfertigen, wenn alles schief geht, können Sie den Fehler wie unter beschrieben ausschalten Ende der Fehlermeldung.
Im Allgemeinen sollten Sie solche Trennlinien nicht schreiben. Sie erstellen ein Taktsignal aus Logik, was, wie ISE Ihnen sagt, keine empfohlene Designpraxis ist. Sie verbrauchen nicht nur (oft knappe) Clock-Routing-Netze, sondern können auch mit zittrigen, fehlerhaften Clocks enden, wenn die Logikblöcke in ihren nächsten Zustand übergehen.
Beispiele (in VHDL ziehe ich es Verilog vor, aber es ist ein einfaches Beispiel)
zB 1: wie man es NICHT macht (eine Uhr aus logischen Ausgängen erstellen):
signal counter: integer range 0 to 999;
signal slowclk: std_logic;
gen_slowclk: process(clk, rst)
begin
if rising_edge(clk) then
if counter = 0 then
slow_clk <= not slow_clk;
counter <= counter'high
else
counter <= counter - 1;
end if;
end if;
if rst = '1' then
slow_clk <= '0';
counter = counter'high;
end if;
end process;
use_slow_clk: process(slow_clk, rst)
begin
if rising_edge(slow_clk) then
-- ...
end if;
if reset = '1' then
-- ...
end if;
end process;
Dies erzeugt einen slow_clk, der 1000-mal langsamer als der Haupttakt ist, und verwendet dann dieses slow_clk-Signal als Takteingang in einem anderen Prozess. Es ist ein Beispiel dafür, wie man Dinge nicht tun sollte. Wenn Sie Ihre RTL untersuchen, sehen Sie, dass die Ausgabe der Logik in die Takteingänge der FFs im Prozess use_slow_clk geht, was schlecht ist.
Was Sie stattdessen tun sollten, ist das Erstellen von Taktfreigaben. Sie steuern Ihre gesamte Logik mit dem ursprünglichen (schnellen) Takt und erzeugen dann ein Taktaktivierungssignal. Die meisten FPGAs haben Flip-Flop-Grundelemente mit Taktaktivierungseingängen, und genau deshalb würden Sie auf diese Weise entwerfen.
zB 2: Taktfreigaben verwenden (empfohlener Weg):
signal counter: integer range 0 to 999;
signal slow_ce: std_logic;
gen_slow_ce: process(clk, rst)
begin
if rising_edge(clk) then
if counter = 0 then
slow_ce <= '1';
counter <= counter'high
else
slow_ce <= '0';
counter <= counter - 1;
end if;
end if;
if rst = '1' then
slow_ce <= '0';
counter = counter'high;
end if;
end process;
use_slow_ce: process(clk, rst)
begin
if rising_edge(clk) then
if slow_ce = '1' then
-- ...
end if;
end if;
if reset = '1' then
-- ...
end if;
end process;
Wenn Sie die RTL dieser Art von Konstruktion untersuchen, werden Sie sehen, dass alle FFs dasselbe Taktsignal verwenden, und das auf einem Taktnetz bereitgestellt wird. Das hinzugefügte @if slow_ce = '1'@ wird vom Synthesizer erkannt und instanziiert ein FF mit einer Taktfreigabe; dies ist ein Signal, das dafür ausgelegt ist, mit Logik gesteuert zu werden und das FF sauber zu gaten.
In beiden Beispielen wird die Logik in @use_slow_*@ mit derselben Frequenz ausgeführt (1/1000 des Haupttakts), aber im zweiten Fall haben Sie nur ein Taktnetzwerk und nutzen die in Ihrem FPGA vorhandenen Taktfreigaben , was zu besserer Synthese, besseren Uhren und einfacherem Timing-Closure führt. Dies führt zu gesünderen FPGA-Designs, was zu zufriedenen FPGA-Designern führt. :-)
Vielleicht gibt es ein Problem mit den beiden gleichzeitigen Zuweisungen an counter
. Sehen Sie, ob das Ändern Ihres always
Blocks hier hilft:
always @(posedge clk) begin
if(counter == SYNC_OUT_CLOCK_RATIO) begin
counter <= 0;
sync <= ~sync;
end else begin
counter <= counter + 1;
end
end
Das Photon