diff --git a/source-7400/74112-tb.v b/source-7400/74112-tb.v index b6b8496..bf00aa6 100644 --- a/source-7400/74112-tb.v +++ b/source-7400/74112-tb.v @@ -1,5 +1,8 @@ // Test: Dual J-K flip-flop with set and clear; negative-edge-triggered +// Note: Preset_bar is synchronous, not asynchronous as specified in datasheet for this device, +// in order to meet requirements for FPGA circuit design (see IceChips Technical Notes) + module test; `TBASSERT_METHOD(tbassert) @@ -516,11 +519,21 @@ begin // the following set of tests are for: preset - // preset from 000, not enough time for output to rise/fall + //-------- begin workaround: preset is not actually asynchronous, have to use a clock --------// + // preset from 000, wait for clock edge Preset_bar = 3'b000; +#15 + tbassert(Q == 3'b000, "Test 39"); + tbassert(Q_bar == 3'b111, "Test 39"); +#0 + // preset from 000, not enough time for output to rise/fall + Clk = 3'b000; #2 tbassert(Q == 3'b000, "Test 39"); tbassert(Q_bar == 3'b111, "Test 39"); +#13 + Clk = 3'b111; + //-------- end workaround --------------------------------------------------------------------// #5 // preset from 000 -> output 1s tbassert(Q == 3'b111, "Test 39"); @@ -547,20 +560,37 @@ begin J = 3'b111; K = 3'b111; #15 - // preset from 011 in contention with toggle (at clock edge in + //-------- begin workaround: preset is not actually asynchronous, have to use a clock --------// + //-------- and have to use setup and hold times --------// + // cannot preset from 011 in contention with toggle (after clock edge in // second and third blocks) - Preset_bar = 3'b000; Clk = 3'b001; #2 tbassert(Q == 3'b011, "Test 41"); tbassert(Q_bar == 3'b100, "Test 41"); #5 - // preset from 011 in contention with toggle -> output 1s - tbassert(Q == 3'b111, "Test 41"); - tbassert(Q_bar == 3'b000, "Test 41"); + // cannot preset from 011 in contention with toggle (after clock edge in + // second and third blocks) -> output in second block is 0 + tbassert(Q == 3'b101, "Test 41"); + tbassert(Q_bar == 3'b010, "Test 41"); +#0 + Preset_bar = 3'b000; +#10 + tbassert(Q == 3'b101, "Test 41"); + tbassert(Q_bar == 3'b010, "Test 41"); #10 // preset, apply clock edge in first block separately with null effect on output Clk[0] = 1'b0; +#10 + tbassert(Q == 3'b101, "Test 41"); + tbassert(Q_bar == 3'b010, "Test 41"); +#5 + // preset, end clock pulse in second block + Clk[1] = 1'b1; +#15 + // preset, apply clock edge in second block separately -> output in second block is 1 + Clk[1] = 1'b0; + //-------- end workaround --------------------------------------------------------------------// #7 tbassert(Q == 3'b111, "Test 41"); tbassert(Q_bar == 3'b000, "Test 41"); @@ -606,8 +636,14 @@ begin J = 3'b010; K = 3'b011; #15 + //-------- begin workaround: preset is not actually asynchronous, have to use a clock --------// // preset third block separately -> output 101 Preset_bar[2] = 1'b0; +#10 + Clk[2] = 1'b0; +#15 + Clk[2] = 1'b1; + //-------- end workaround --------------------------------------------------------------------// #20 tbassert(Q == 3'b101, "Test 43"); tbassert(Q_bar == 3'b010, "Test 43"); @@ -629,20 +665,37 @@ begin J = 3'b110; K = 3'b011; #40 - // preset from 010 in contention with load and toggle (at clock edge in + //-------- begin workaround: preset is not actually asynchronous, have to use a clock --------// + //-------- and have to use setup and hold times --------// + // cannot preset from 010 in contention with load and toggle (after clock edge in // second and third blocks) - Preset_bar = 3'b000; Clk = 3'b001; #2 tbassert(Q == 3'b010, "Test 44"); tbassert(Q_bar == 3'b101, "Test 44"); #5 - // preset from 010 in contention with load and toggle -> output 1s - tbassert(Q == 3'b111, "Test 44"); - tbassert(Q_bar == 3'b000, "Test 44"); + // cannot preset from 010 in contention with load and toggle (after clock edge in + // second and third blocks) -> output in second block is 0 + tbassert(Q == 3'b100, "Test 44"); + tbassert(Q_bar == 3'b011, "Test 44"); +#0 + Preset_bar = 3'b000; #10 - // preset from 010, apply clock edge in first block separately with null effect on output + tbassert(Q == 3'b100, "Test 44"); + tbassert(Q_bar == 3'b011, "Test 44"); +#10 + // preset, apply clock edge in first block separately -> output in first block is 1 Clk[0] = 1'b0; +#10 + tbassert(Q == 3'b101, "Test 44"); + tbassert(Q_bar == 3'b010, "Test 44"); +#5 + // preset, end clock pulse in second block + Clk[1] = 1'b1; +#15 + // preset, apply clock edge in second block separately -> output in second block is 1 + Clk[1] = 1'b0; + //-------- end workaround --------------------------------------------------------------------// #7 tbassert(Q == 3'b111, "Test 45"); tbassert(Q_bar == 3'b000, "Test 45"); diff --git a/source-7400/74112.v b/source-7400/74112.v index 68ebf58..a0c9474 100644 --- a/source-7400/74112.v +++ b/source-7400/74112.v @@ -1,5 +1,8 @@ // Dual J-K flip-flop with set and clear; negative-edge-triggered +// Note: Preset_bar is synchronous, not asynchronous as specified in datasheet for this device, +// in order to meet requirements for FPGA circuit design (see IceChips Technical Notes) + module ttl_74112 #(parameter BLOCKS = 2, DELAY_RISE = 0, DELAY_FALL = 0) ( input [BLOCKS-1:0] Preset_bar, @@ -13,16 +16,17 @@ module ttl_74112 #(parameter BLOCKS = 2, DELAY_RISE = 0, DELAY_FALL = 0) //------------------------------------------------// reg [BLOCKS-1:0] Q_current; +reg [BLOCKS-1:0] Preset_bar_previous; generate genvar i; for (i = 0; i < BLOCKS; i = i + 1) begin: gen_blocks - always @(negedge Clk[i] or negedge Clear_bar[i] or negedge Preset_bar[i]) + always @(negedge Clk[i] or negedge Clear_bar[i]) begin if (!Clear_bar[i]) Q_current[i] <= 1'b0; - else if (!Preset_bar[i]) + else if (!Preset_bar[i] && Preset_bar_previous[i]) // falling edge has occurred Q_current[i] <= 1'b1; else begin @@ -32,6 +36,8 @@ generate Q_current[i] <= !Q_current[i]; else Q_current[i] <= Q_current[i]; + + Preset_bar_previous[i] <= Preset_bar[i]; end end end diff --git a/source-7400/7474-tb.v b/source-7400/7474-tb.v index b3a2625..dcf54c4 100644 --- a/source-7400/7474-tb.v +++ b/source-7400/7474-tb.v @@ -1,5 +1,8 @@ // Test: Dual D flip-flop with set and clear; positive-edge-triggered +// Note: Preset_bar is synchronous, not asynchronous as specified in datasheet for this device, +// in order to meet requirements for FPGA circuit design (see IceChips Technical Notes) + module test; `TBASSERT_METHOD(tbassert) @@ -363,11 +366,23 @@ begin Clear_bar = 3'bxxx; Clk = 3'bxxx; #15 - // preset from initial state, not enough time for output to rise/fall + //-------- begin workaround: preset is not actually asynchronous, have to use a clock --------// + // preset from initial state, with clock + Preset_bar = 3'b111; + Clk = 3'b111; +#15 + // preset from initial state, wait for clock edge Preset_bar = 3'b000; + Clk = 3'b000; +#15 + // preset from initial state, not enough time for output to rise/fall + Clk = 3'b111; #2 tbassert(Q === 3'bxxx, "Test 17"); tbassert(Q_bar === 3'bxxx, "Test 17"); +#15 + Clk = 3'bxxx; + //-------- end workaround --------------------------------------------------------------------// #5 // preset from initial state -> output 1s tbassert(Q == 3'b111, "Test 17"); @@ -429,16 +444,19 @@ begin // set up different data input value D = 3'b010; #15 - // preset third block separately -> output 100 + //-------- begin workaround: preset is not actually asynchronous, have to use a clock --------// + //-------- and have to use setup and hold times --------// + // preset third block separately, wait for clock edge Preset_bar[2] = 1'b0; +#15 + // preset third block separately -> output 100 + Clk[2] = 1'b1; #20 tbassert(Q == 3'b100, "Test 19"); tbassert(Q_bar == 3'b011, "Test 19"); #0 - // preset first and second blocks separately in contention with load (at clock edge in + // cannot preset first and second blocks in contention with load (after clock edge in // first and second blocks) - Preset_bar[0] = 1'b0; - Preset_bar[1] = 1'b0; // D = 3'b010; Clk[0] = 1'b1; Clk[1] = 1'b1; @@ -446,12 +464,26 @@ begin tbassert(Q == 3'b100, "Test 20"); tbassert(Q_bar == 3'b011, "Test 20"); #5 - // preset first and second blocks separately in contention with load (at clock edge in - // first and second blocks) -> output 1s - tbassert(Q == 3'b111, "Test 20"); - tbassert(Q_bar == 3'b000, "Test 20"); + // cannot preset first and second blocks in contention with load (after clock edge in + // first and second blocks) -> output in first block is 0 + tbassert(Q == 3'b110, "Test 20"); + tbassert(Q_bar == 3'b001, "Test 20"); +#0 + Preset_bar[0] = 1'b0; + Preset_bar[1] = 1'b0; #15 + Clk = 3'b000; +#7 Preset_bar = 3'b111; +#15 + tbassert(Q == 3'b110, "Test 20"); + tbassert(Q_bar == 3'b001, "Test 20"); +#0 + // load new value + D = 3'b111; +#15 + Clk = 3'b111; + //-------- end workaround --------------------------------------------------------------------// #25 Clk = 3'b000; #15 diff --git a/source-7400/7474.v b/source-7400/7474.v index 3c40104..899da52 100644 --- a/source-7400/7474.v +++ b/source-7400/7474.v @@ -1,5 +1,8 @@ // Dual D flip-flop with set and clear; positive-edge-triggered +// Note: Preset_bar is synchronous, not asynchronous as specified in datasheet for this device, +// in order to meet requirements for FPGA circuit design (see IceChips Technical Notes) + module ttl_7474 #(parameter BLOCKS = 2, DELAY_RISE = 0, DELAY_FALL = 0) ( input [BLOCKS-1:0] Preset_bar, @@ -12,19 +15,23 @@ module ttl_7474 #(parameter BLOCKS = 2, DELAY_RISE = 0, DELAY_FALL = 0) //------------------------------------------------// reg [BLOCKS-1:0] Q_current; +reg [BLOCKS-1:0] Preset_bar_previous; generate genvar i; for (i = 0; i < BLOCKS; i = i + 1) begin: gen_blocks - always @(posedge Clk[i] or negedge Clear_bar[i] or negedge Preset_bar[i]) + always @(posedge Clk[i] or negedge Clear_bar[i]) begin if (!Clear_bar[i]) Q_current[i] <= 1'b0; - else if (!Preset_bar[i]) + else if (!Preset_bar[i] && Preset_bar_previous[i]) // falling edge has occurred Q_current[i] <= 1'b1; else + begin Q_current[i] <= D[i]; + Preset_bar_previous[i] <= Preset_bar[i]; + end end end endgenerate