Gate level Description: Binary Counter

Basic Code

        // 4-bit binary counter

        module counter4_bit(q, d, increment, load_data, global_reset, clock);
           output [3:0]     q;
           input [3:0] d;
           input  load_data, global_reset, clock, increment;
           wire        t1, t2, t3; // internal wires
           wire        see12, reset; // internal wires

           // internal wires are used to move information around the module,
           // they can be imagined  to be temporary variables, storing the ouput
           // from one gate and feeding it into another.

           et_ff etff0(q[0], d[0], increment, load_data, reset, clock);
           et_ff etff1(q[1], d[1], t1, load_data, reset, clock);
           et_ff etff2(q[2], d[2], t2, load_data, reset, clock);
           et_ff etff3(q[3], d[3], t3, load_data, reset, clock);

           and a1(t1, increment, q[0]);  // increment signals are derived from the
           and a2(t2, t1, q[1]);      // the previous increment signal by and-ing
           and a3(t3, t2, q[2]);      // with the output form the previous
                                      //ET-type

           recog12 r1(see12, q);      // everytime the output changed this
                                      // checks if it is a 12, if so 'see12' is
                                      // set to 1.
           or or1(reset, see12, global_reset); // reset to 0 if 'global_reset'
                                               // or 'see12' is high

        endmodule // counter4_bit

        module et_ff(q, data, toggle, load_data, reset, clock);
           output q;
           input  data, toggle, load_data, reset, clock;
           wire     m1, m2;

           mux mux0(m1, ~q, q, toggle);
           mux mux1(m2, data, m1, load_data);
           dff dff0(q, m2, reset, clock);

        endmodule // et_ff

        module mux(out, in1, in2, cntrl);
           output out;
           input  in1, in2, cntrl;

           assign out = cntrl ? in1 : in2;
           // this is a continuous assignment so it is renewed everytime an
           // operand changed. if (cntrl==1) out = in1, else out = in2.

        endmodule // mux

        module dff(q, data, reset, clock);
           output q;
           input  data, reset, clock;
           reg      q;

           always @(posedge clock) // at every clock edge, if reset is 1, q is
              if (reset == 1)       // reset to 0, else it is set to data, which
              q = 0;          // as we said earlier can be either data, q or ~q
              else q = data;

        endmodule

        module recog12(flag, in);
           input [3:0] in;
           output      flag;

           assign flag = (in == 4'b1100) ? 1 : 0;
           // here we see that if the input is 12 the flag will be set to 1,
           // otherwise it will be set to 0.

        endmodule // recog12

        module stumulus;
           wire [3:0] q;
           reg [3:0]  d;
           reg          load_data, global_reset, clk, increment;

           counter4_bit mod1 (q, d, increment, load_data, global_reset, clk);

           initial begin
              global_reset = 0;
              clk = 0;
              increment = 0;
              load_data = 0;
              d = 4'b0100;

              #10 global_reset = 1;
              #20 global_reset = 0;
              #20 load_data = 1;
              #20 load_data = 0;
              #20 increment = 1;
              #200 global_reset = 1;
              #20 global_reset = 0;
              #50 load_data = 1;
              #20 load_data = 0;
              #10 increment = 0;
              #20 $finish;
           end // initial begin

           always #5 clk = ~clk;

           always #10 $display ($time,"  %b %b %b %d -> %b %d",
                           increment, load_data, global_reset, d, q, q);

        endmodule // stumulus

Break down

        module counter4_bit(q, d, increment, load_data, global_reset, clock);
           output [3:0]     q;
           input [3:0] d;
           input  load_data, global_reset, clock, increment;
           wire        t1, t2, t3; // internal wires
           wire        see12, reset; // internal wires


The first line is the start of the module, declaring the name and the port list. The output is q and there other signals are all inputs. t1, t2, t3, see12 and reset are all declared as internal wires which connect the various gates/sub-modules within the module.

           et_ff etff0(q[0], d[0], increment, load_data, reset, clock);
           et_ff etff1(q[1], d[1], t1, load_data, reset, clock);
           et_ff etff2(q[2], d[2], t2, load_data, reset, clock);
           et_ff etff3(q[3], d[3], t3, load_data, reset, clock);

There are 4 Enable/Toggle flip flops in the logic diagram, each of which is instatiated here. Note each instantiation has a name. q.
           and a1(t1, increment, q[0]);
           and a2(t2, t1, q[1]);
           and a3(t3, t2, q[2]);

The increment signal is anded with the output from the last E-T flipflop to assert the toggle signal for the next E-T flipflop; this can be seen in logic diagram.
           recog12 r1(see12, q);
           or or1(reset, see12, global_reset);

Everytime q changes the value of see12 is updated; when it reaches 12, the internal reset signal is raised by the or gate and the flipflops will all be reset on the next rising clock edge


previous next contents