FDCP: D flip-flop with asynchronous Clear/Preset

FDCP is a D-type flip-flop with active-high asynchronous clear (CLR) and preset (PRE) inputs. The CLR input takes precedence over the PRE input.

If CLR is asserted, the Q output is set to 0. If CLR is not asserted, and PRE is asserted, the Q output is set to 1. The data on the D input is otherwise loaded to the Q output on the low-to-high transition of the clock (C) input.

This Verilog code will correctly synthesise into a D flip-flop with an asynchronous clear and an asynchronous preset (assuming, of course, that your technology library has such a device). However, the code simulates incorrectly, and fails the testbench. The error messages from the testbench output log are:
(Error)      (D100) 'fdcp.tv', line 10, 24 ns: 'Q': expected 'b1; got 'b0
(Error)      (D100) 'fdcp.tv', line 11, 34 ns: 'Q': expected 'b1; got 'b0
(Log)        (60 ns) 6 vectors executed (4 passes, 2 fails)
In other words, the model simulates incorrectly when both the CLR and PRE inputs are asserted, and the CLR input is then released (at line 10 of the testbench). The testbench expects the output to preset to 1 at this point, but it instead holds at 0, and remains at 0 when the preset input is also released (line 11).
The fundamental problem here is that Verilog's event controls cannot, by themselves, handle this situation. There is no mechanism to tell whether or not a particular edge triggered an event control (the equivalent of VHDL's 'event attribute), and no combination or edge- or level-sensitive controls gives the required behaviour. The simulation model can be fixed, but this requires the addition of some fairly complex code; see FDCP-FixedVerilog. Note that the VHDL model does not have this problem, because the process triggers on the falling edge of CLR, and can then detect than PRE is set (this works because the rising_edge function can detect whether or not a clock edge has occurred).
module FDCP(
  input CLR, PRE, D, C, 
  output reg Q);

  always @(posedge C or posedge CLR or posedge PRE)
      Q <= 0;
    else if(PRE)
      Q <= 1;
      Q <= D;
library IEEE;
use IEEE.std_logic_1164.all;

entity FDCP is
  port (
    CLR, PRE, D, C : in  std_logic;
    Q              : out std_logic);
end entity FDCP;

architecture A of FDCP is
  process (C, CLR, PRE) is
    if CLR = '1' then
      Q <= '0';
    elsif PRE = '1' then
      Q <= '1';
    elsif rising_edge(C) then
      Q <= D;
    end if;
  end process;

end architecture A;
1   DUT {
2      module FDCP(input CLR, PRE, D, C; output Q)
3      create_clock C
4      [CLR, PRE]       -> [Q]    // test async clear/preset
5      [CLR, PRE, D, C] -> [Q]    // test sync operation
6   }
8   [1, .X] -> [0]                // async clear, takes precedence over preset
9   [1,  1] -> [0]                // assert preset, output unchanged
10  [0,  1] -> [1]                // release clear, output sets to 1
11  [0,  0] -> [1]                // release preset, output holds at 1
13  [0, 0, 0, .C] -> [0]          // clock to 0
14  [0, 0, 1, .C] -> [1]          // clock to 1