VHDL で VGA ドライバを作成しようとしています。
640x480 @ 60 Hz を使用するので、25 MHz と 31.5 KHz のクロックが必要です。divider_h
プロセスは 50 MHz クロックで駆動され、結果として 25 MHz クロックになります。25 MHz クロックの各ティックでh_counter
、プロセスによってインクリメントされ、ある値 ( )h_sync
に達すると、プロセスが開始され、短時間の間 1 に設定されます。H_FRONT + H_SYNC - 1
divider_v
clock_v
Quartus II のタイミング解析が失敗し、次の警告が表示されます。1 つのパスに沿って最小セットアップおよびホールド要件クロックを達成できません。コンパイル レポートのクロック ホールドv_counter
セクションは、最小スラック タイムが -0.050 ns のMSB が原因であると指摘しています。2 番目に低いスラック タイムは 0.218 ns で、問題ありません。
短い 0 状態に対して長い 1 状態を使用しようとしましたがclock_v
、最小スラック時間が -0.019 ns に増加しましたが、これはまだ許容できません。
私が理解しているように、ホールドクロックの問題は、入力が正しく処理される前に変更されることを意味するため、1と0の両方をほぼ同じ期間表示しようとしました。驚いたことに、40 以上のパスが同じエラーで赤くなりました。
v_clock
プロセスをコメントアウトすると、問題が解決します。
MSB のスラック タイムが他のビットよりもはるかに長いのはなぜですか? この問題を解決するにはどうすればよいですか?
これが私のコードです:
library ieee;
use ieee.std_logic_1164.all;
library Famikon;
use Famikon.Types.all;
use Famikon.VgaNames.all;
entity VgaDriver is
port (
-- inputs
clock_50: in STD_LOGIC; -- 50 MHz
reset: in bit; -- '1' resets
r, g, b: in screen_pixel; -- bit_vector subtype
-- outputs
vga_x, vga_y: out hw_coord; -- integer subtype
vga_drawing: out bit;
hw_r, hw_g, hw_b: out hw_pixel; -- bit_vector subtype
vga_hsync, vga_vsync: out bit;
vga_blank, vga_clock: out bit
);
end entity;
architecture Arch of VgaDriver is
signal clock_h, clock_v: std_logic;
signal h_counter, v_counter: vga_counter; -- integer subtype
signal h_coord, v_coord: hw_coord; -- integer subtype
signal h_active, v_active: bit;
begin
-- some irrelevant code --
h_active <= '1' when (h_counter >= H_BLANK) else '0';
v_active <= '1' when (v_counter >= V_BLANK) else '0';
divider_h: process (clock_50) begin
if (rising_edge(clock_50)) then
clock_h <= not clock_h;
end if;
end process;
divider_v: process (h_counter) begin
if (h_counter /= H_FRONT + H_SYNC - 1) then
clock_v <= '0';
else
clock_v <= '1';
end if;
end process;
h_clock: process (clock_h, reset) begin
if (rising_edge(clock_h)) then
if (reset = '1') then
h_counter <= 0;
elsif (h_counter = H_TOTAL - 1) then
h_counter <= 0;
else
h_counter <= h_counter + 1;
end if;
end if;
end process;
v_clock: process (clock_v, reset) begin
if (rising_edge(clock_v)) then
if (reset = '1') then
v_counter <= 0;
elsif (v_counter = V_TOTAL - 1) then
v_counter <= 0;
else
v_counter <= v_counter + 1;
end if;
end if;
end process;
end architecture;
失敗したパスの詳細:
- から:
v_counter[9]
- に:
v_counter[9]
- クロックから:
clock
- クロックするには:
clock
- 必要なホールド関係: 0.000 ns
- 必要な最短 P2P 時間: 0.618 ns
- 実際のショート P2P 時間: 0.568 ns
- 最小スラック: -0.050 ns
v_counter
ですbit_vector(9 downto 0)
。このパスでLocate in Designを使用すると、Quartus はv_clock
プロセスの最初の行 ( のある行) を指しrising_edge(clock_v)
ます。
また、すべてのh_counter
ビットに言及するリップル クロックに関する警告clock_h
と、3 つのゲート クロック: Equal0
、Equal0~1
およびEqual0~0
.