我正在尝试用 VHDL 创建一个 VGA 驱动程序。
我要 640x480 @ 60 Hz,所以我需要 25 MHz 和 31.5 KHz 时钟。divider_h
过程由 50 MHz 时钟驱动,产生 25 MHz 时钟。在 25 MHz 时钟h_counter
的每个刻度上,进程递增h_sync
,当它达到某个值 ( H_FRONT + H_SYNC - 1
) 时,divider_v
进程被触发并clock_v
在短时间内设置为 1。
Quartus II 的时序分析失败并出现警告:Can't meet minimum setup and hold requirements clock along 1 path(s)。编译报告中的时钟保持部分指出,MSBv_counter
是罪魁祸首,最小松弛时间为 -0.050 ns。第二低的松弛时间是 0.218 ns,这很好。
我尝试将 long 1 状态用于clock_v
短暂的 0 状态,并且最小松弛时间已增加到 -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
和三个门控时钟Equal0
:Equal0~1
和Equal0~0
.