Sequential Logic Design

Async reset should be asserted asynchronously, de-asserted synchronously (reset synchronizer, §27).

13.1 D flip-flop

process (clk)
begin
  if rising_edge(clk) then
    q <= d;
  end if;
end process;

13.2 Resets

Async reset should be asserted asynchronously, de-asserted synchronously (reset synchronizer, §27).

-- Synchronous reset (recommended for most FPGA designs)
process (clk)
begin
  if rising_edge(clk) then
    if rst = '1' then
      q <= '0';
    else
      q <= d;
    end if;
  end if;
end process;

-- Asynchronous reset
process (clk, rst_n)
begin
  if rst_n = '0' then          -- active-low async reset
    q <= '0';
  elsif rising_edge(clk) then
    q <= d;
  end if;
end process;

13.3 Register with clock enable

Never gate the clock with logic (clk and en) in FPGAs — use clock enables.

process (clk)
begin
  if rising_edge(clk) then
    if rst = '1' then
      reg <= (others => '0');
    elsif en = '1' then
      reg <= d;
    end if;
  end if;
end process;

13.4 Counters

Variants: up/down counter, loadable counter, BCD counter, ring counter, Johnson counter, LFSR (pseudo-random):

-- Up counter with terminal count
process (clk)
begin
  if rising_edge(clk) then
    if rst = '1' then
      cnt <= (others => '0');
    elsif en = '1' then
      if cnt = MAX then
        cnt <= (others => '0');
        tc  <= '1';
      else
        cnt <= cnt + 1;
        tc  <= '0';
      end if;
    end if;
  end if;
end process;
-- 8-bit Fibonacci LFSR, taps 8,6,5,4
lfsr <= lfsr(6 downto 0) & (lfsr(7) xor lfsr(5) xor lfsr(4) xor lfsr(3));

13.5 Shift registers

process (clk)
begin
  if rising_edge(clk) then
    if load = '1' then
      sr <= parallel_in;
    else
      sr <= sr(sr'high-1 downto 0) & serial_in;   -- shift left
    end if;
  end if;
end process;
serial_out <= sr(sr'high);

13.6 Clock divider / tick generator

-- Generate a 1-cycle tick at 1 Hz from a 100 MHz clock (use as an enable, NOT as a clock)
process (clk)
begin
  if rising_edge(clk) then
    tick <= '0';
    if cnt = 100_000_000 - 1 then
      cnt  <= 0;
      tick <= '1';
    else
      cnt <= cnt + 1;
    end if;
  end if;
end process;

13.7 Edge detection & debouncing

Debouncer: wait until the (synchronized) input is stable for N ms before accepting it.

process (clk)
begin
  if rising_edge(clk) then
    btn_d <= btn_sync;
  end if;
end process;
btn_rise <= btn_sync and not btn_d;     -- one-cycle pulse on rising edge

13.8 Latches (usually unintended!)

Latches cause timing problems in FPGAs; synthesis tools warn "inferred latch". Fix with defaults or complete if/else.

process (en, d)          -- level-sensitive: latch
begin
  if en = '1' then q <= d; end if;     -- no else → q holds its value → latch
end process;