| `define MAXQ 2 |
| module uut ( |
| input clk, |
| input d, r, e, |
| output [`MAXQ:0] q |
| ); |
| reg q0; |
| always @(posedge clk) begin |
| if (r) |
| q0 <= 0; |
| else if (e) |
| q0 <= d; |
| end |
| |
| reg q1; |
| always @(posedge clk, posedge r) begin |
| if (r) |
| q1 <= 0; |
| else if (e) |
| q1 <= d; |
| end |
| |
| reg q2; |
| always @(posedge clk, negedge r) begin |
| if (!r) |
| q2 <= 0; |
| else if (!e) |
| q2 <= d; |
| end |
| |
| assign q = {q2, q1, q0}; |
| endmodule |
| |
| `ifdef TESTBENCH |
| module \$ff #( |
| parameter integer WIDTH = 1 |
| ) ( |
| input [WIDTH-1:0] D, |
| output reg [WIDTH-1:0] Q |
| ); |
| wire sysclk = testbench.sysclk; |
| always @(posedge sysclk) |
| Q <= D; |
| endmodule |
| |
| module testbench; |
| reg sysclk; |
| always #5 sysclk = (sysclk === 1'b0); |
| |
| reg clk; |
| always @(posedge sysclk) clk = (clk === 1'b0); |
| |
| reg d, r, e; |
| |
| wire [`MAXQ:0] q_uut; |
| uut uut (.clk(clk), .d(d), .r(r), .e(e), .q(q_uut)); |
| |
| wire [`MAXQ:0] q_syn; |
| syn syn (.clk(clk), .d(d), .r(r), .e(e), .q(q_syn)); |
| |
| wire [`MAXQ:0] q_prp; |
| prp prp (.clk(clk), .d(d), .r(r), .e(e), .q(q_prp)); |
| |
| wire [`MAXQ:0] q_a2s; |
| a2s a2s (.clk(clk), .d(d), .r(r), .e(e), .q(q_a2s)); |
| |
| wire [`MAXQ:0] q_ffl; |
| ffl ffl (.clk(clk), .d(d), .r(r), .e(e), .q(q_ffl)); |
| |
| task printq; |
| reg [5*8-1:0] msg; |
| begin |
| msg = "OK"; |
| if (q_uut !== q_syn) msg = "SYN"; |
| if (q_uut !== q_prp) msg = "PRP"; |
| if (q_uut !== q_a2s) msg = "A2S"; |
| if (q_uut !== q_ffl) msg = "FFL"; |
| $display("%6t %b %b %b %b %b %s", $time, q_uut, q_syn, q_prp, q_a2s, q_ffl, msg); |
| if (msg != "OK") $finish; |
| end |
| endtask |
| |
| initial if(0) begin |
| $dumpfile("async.vcd"); |
| $dumpvars(0, testbench); |
| end |
| |
| initial begin |
| @(posedge clk); |
| d <= 0; |
| r <= 0; |
| e <= 0; |
| @(posedge clk); |
| e <= 1; |
| @(posedge clk); |
| e <= 0; |
| repeat (10000) begin |
| @(posedge clk); |
| printq; |
| d <= $random; |
| r <= $random; |
| e <= $random; |
| end |
| $display("PASS"); |
| $finish; |
| end |
| endmodule |
| `endif |