/************************************************** VeriLab 2 STRUCTURAL DESCRIPTIONS OF COMBINATIONAL CIRCUITS ***************************************************/ /* The combinational circuits are no loop circuits, with the outputs continously changing according to the changes occured to the inputs. The elementary circuits involved in designing these kind of circuits are: ANDs, ORs, NANDs, NORs, XORs, NXORs, NOTs. The elementary combinational functions are performed by: adders, comparators, decoders, multiplexers, encoders, transcoders ... . Some of them are performed by simple circuits, but some involve complex circuits. A multiplexer is a simple one, but usualy a transcoder is a complex circuit. Any circuit will be a composition of some smaller or/and simpler circuits. But attention! We must avoid any loop in the design of any combinational circuit. */ /*************** PROBLEM NO.1: Equality comparator */ /* module comp_4(out, left, right); input[3:0] left, right; // the two 4-bit words to be compared output out; // takes the value 1 if the two inputs have the same value wire w0, w1, w2, w3; // internal connections xor xor_3(w3, left[3], right[3]), xor_2(w2, left[2], right[2]), xor_1(w1, left[1], right[1]), xor_0(w0, left[0], right[0]); // 4 XORs are instantiated nor gate(out, w0, w1, w2, w3); // one 4-input NOR gate compute the output endmodule module test_comp; reg[3:0] number_1, number_2; wire out; initial begin number_1 = 4'd5; number_2 = 4'd7; #1 number_1 = 4'd7; #2 number_2 = 4'd12; #3 number_1 = 4'd12; #4 number_1 = 4'd1; end comp_4 dut(out, number_1, number_2); initial $monitor("Time=%0d number_1=%b number_2=%d out", $time, number_1, number_2, dut.out); endmodule */ /*************** PROBLEM NO.2: Full adder */ /* module adder(sum, carry_out, a, b, carry_in); input a, // the first bit to be added b, // the second bit to be added carry_in; // the carry input received from the previous binary order; to be added output sum, // the sum output carry_out; // the carry generated toward the next binary order; to be added to the // next binarry level wire w1, w2, w3; xor #2 xor_1(sum, carry_in, w1), xor_2(w1, a, b); // the XOR gates have 2 time units delay nand #1 nand_1(carry_out, w2, w3), nand_2(w2, a, b), nand_3(w3, w1, carry_in); // the NAND gates have one time unit delay endmodule module test_adder; reg[2:0] signals; // having the following meaning {carry_in, a, b} wire sum, carry_out; // wires to be 'connected' to the 'monitor' initial begin signals = 3'b000; #10 signals = 3'b001; #10 signals = 3'b010; #10 signals = 3'b011; #10 signals = 3'b100; #10 signals = 3'b101; #10 signals = 3'b110; #10 signals = 3'b111; // all binary input configurations are generated end adder dut(sum, carry_out, signals[1], signals[0], signals[2]); initial $monitor("Time=%0d signals=%b sum=%b carry_out=%b", $time, signals, dut.sum, dut.carry_out); endmodule */ /*************** PROBLEM NO.3: 4-bit adder with ripple carry */ /* module four_bit_adder(sum, carry_out, a, b, carry_in); input carry_in; input[3:0] a, b; output carry_out; output[3:0] sum; wire carry_1, carry_2, carry_3; adder add_3(sum[3], carry_out, a[3], b[3], carry_3), add_2(sum[2], carry_3, a[2], b[2], carry_2), add_1(sum[1], carry_2, a[1], b[1], carry_1), add_0(sum[0], carry_1, a[0], b[0], carry_in); endmodule module adder(sum, carry_out, a, b, carry_in); // previously defined in Problem no. 2 input a, b, carry_in; output sum, carry_out; wire w1, w2, w3; xor #0 xor_1(sum, carry_in, w1), xor_2(w1, a, b); nand #0 nand_1(carry_out, w2, w3), nand_2(w2, a, b), nand_3(w3, w1, carry_in); endmodule module test_four_bit_adder; reg clock; // the clock who triggers the input changes reg[8:0] counter; // 9-bit counter which generates all the input binary configurations wire carry_out; wire[3:0] sum; initial #10000 $stop; initial begin clock = 0; counter = 9'b0; // initializing the counter forever #10 clock = ~clock; end always @(posedge clock) counter = counter + 1; // incrementing the counter four_bit_adder dut(sum, carry_out, counter[7:4], counter[3:0], counter[8]); initial $monitor("Time=%0d clock=%b carry_in=%b number_1=%b number_2=%b sum=%b carry_out=%b", $time, clock, counter[8], counter[7:4], counter[3:0], dut.sum, dut.carry_out); endmodule */ /*************** PROBLEM NO.4: 16-bit priority encoder */ /* module pr_enc_16(out, zero, in, enable); input enable; // enable the output of the circuit to correspond to the inputs; // if 'enable = 0' all the output of the circuit take the value 0. input[15:0] in; // inputs to be codded output zero; // 'zero = 1' means that all the inputs to be codded have the value 0 output[3:0] out; // if 'enable = 1' then indicates the position of the most significant 1 // on the inputs to be codded wire w3, w4; wire[2:0] w1, w0; pr_enc_8 enc_1(w1, w3, in[15:8], enable), enc_0(w0, zero, in[7:0], w3); // two 8-bit priority encoders serialy connected or or_2(out[2], w1[2], w0[2]), or_1(out[1], w1[1], w0[1]), or_0(out[0], w1[0], w0[0]); // generate the first three outputs not inv(w4, w3); and gate(out[3], w4, enable); // the most significant output endmodule module pr_enc_8(out, zero, in, enable); // defines an 8-bit priority encoder input enable; input[7:0] in; output zero; output[2:0] out; // Equations describing the four outputs of the circuit assign zero = enable & ~(| in), out[2] = enable & (| in[7:4]), out[1] = enable & (| in[7:6] | ~(| in[5:4]) & (| in[3:2])), out[0] = enable & (in[7] | ~in[6] & (in[5] | ~in[4] & (in[3] | ~in[2] & in[1]))); endmodule module test_pr_enc; reg enable; reg[15:0] in; wire zero; wire[3:0] out; initial begin enable = 0; in = 16'b1001000110110; #1 enable = 1; #1 in = 16'd0; #1 in = 16'd1; #1 in = 16'd3; #1 in = 16'd7; #1 in = 16'd15; #1 in = 16'd31; #1 in = 16'd63; #1 in = 16'd127; #1 in = 16'd255; #1 in = 16'd511; #1 in = 16'd1023; #1 in = 16'd2047; #1 in = 16'd4095; #1 in = 16'd8191; #1 in = 16'd16383; #1 in = 16'd32767; #1 in = 16'd65535; end pr_enc_16 dut(out, zero, in, enable); initial $monitor("Time=%0d enable=%b in=%b zero=%b out=%b", $time, enable, in, dut.zero, dut.out); endmodule */ /*************** PROBLEM NO.5: The behavioral description of a 16 to 1 multiplexer */ /* module mux16_1(out, in, sel); input[3:0] sel; // the selection inputs input[15:0] in; // the selected inputs output out; // the value selected by 'sel' from 'in' assign out = in[sel]; // multiplexing means to select endmodule module test_mux; reg[3:0] sel; reg[15:0] in; wire out; initial #33 $stop; initial begin sel = 4'b0; in = 16'b1100101011110000; //in = 16'b1111111100000000; // an alternative for the selected inputs forever #1 sel = sel + 1; // generates all the selection configurations end mux16_1 dut(out, in, sel); initial $monitor("Time=%0d out=%b", $time, dut.out); endmodule */ /*************** PROBLEM NO.6: The behavioral description of a 4-bit decoder */ /* module dec4_16(out, sel); input[3:0] sel; // the code to be decoded output[15:0] out; // any time only one of the 16 outputs has the value 1 assign out = 16'b1 << sel; // 1 shifted 'sel' positions to left // maybe a 'too behavioural' description to be sinthesisable endmodule module test_dec; reg[3:0] sel; wire[15:0] out; initial #20 $stop; initial begin sel = 0; forever #1 sel = sel + 1; end dec4_16 dut(out, sel); initial $monitor("Time=%0d sel=%b out=%b", $time, sel, dut.out); endmodule */ /*************** PROBLEM NO.7: The structural description of the same decoder */ /* module dec4_16(out, sel); input[3:0] sel; output[15:0] out; wire w0, w1, w2, w3, nw0, nw1, nw2, nw3; not not_3(nw3, sel[3]), not_2(nw2, sel[2]), not_1(nw1, sel[1]), not_0(nw0, sel[0]), buf_3(w3, nw3), buf_2(w2, nw2), buf_1(w1, nw1), buf_0(w0, nw0); and and_15(out[15], w3, w2, w1, w0), and_14(out[14], w3, w2, w1, nw0), and_13(out[13], w3, w2, nw1, w0), and_12(out[12], w3, w2, nw1, nw0), and_11(out[11], w3, nw2, w1, w0), and_10(out[10], w3, nw2, w1, nw0), and_09(out[09], w3, nw2, nw1, w0), and_08(out[08], w3, nw2, nw1, nw0), and_07(out[07], nw3, w2, w1, w0), and_06(out[06], nw3, w2, w1, nw0), and_05(out[05], nw3, w2, nw1, w0), and_04(out[04], nw3, w2, nw1, nw0), and_03(out[03], nw3, nw2, w1, w0), and_02(out[02], nw3, nw2, w1, nw0), and_01(out[01], nw3, nw2, nw1, w0), and_00(out[00], nw3, nw2, nw1, nw0); // Remember that the previous behavioural description has only one line instead of the // 23 line of this structural description. // The decoder is a simple circuit, but its size increases exponentialy with number of inputs. // The behavioural description offers the complexity and the structural description offers // the size of the decoder. endmodule module test_dec; // the same as for the behavioural description reg[3:0] sel; wire[15:0] out; initial #20 $stop; initial begin sel = 0; forever #1 sel = sel + 1; end dec4_16 dut(out, sel); initial $monitor("Time=%0d sel=%b out=%b", $time, sel, dut.out); endmodule */ /*************** PROBLEM NO.8: The structural description of the previously described multiplexer */ /* module mux16_1(out, in, sel); input[3:0] sel; input[15:0] in; output out; wire w0, w1, w2, w3, nw0, nw1, nw2, nw3; wire[15:0] dout; not not_3(nw3, sel[3]), not_2(nw2, sel[2]), not_1(nw1, sel[1]), not_0(nw0, sel[0]), buf_3(w3, nw3), buf_2(w2, nw2), buf_1(w1, nw1), buf_0(w0, nw0); and and_15(dout[15], w3, w2, w1, w0, in[15]), and_14(dout[14], w3, w2, w1, nw0, in[14]), and_13(dout[13], w3, w2, nw1, w0, in[13]), and_12(dout[12], w3, w2, nw1, nw0, in[12]), and_11(dout[11], w3, nw2, w1, w0, in[11]), and_10(dout[10], w3, nw2, w1, nw0, in[10]), and_09(dout[09], w3, nw2, nw1, w0, in[09]), and_08(dout[08], w3, nw2, nw1, nw0, in[08]), and_07(dout[07], nw3, w2, w1, w0, in[07]), and_06(dout[06], nw3, w2, w1, nw0, in[06]), and_05(dout[05], nw3, w2, nw1, w0, in[05]), and_04(dout[04], nw3, w2, nw1, nw0, in[04]), and_03(dout[03], nw3, nw2, w1, w0, in[03]), and_02(dout[02], nw3, nw2, w1, nw0, in[02]), and_01(dout[01], nw3, nw2, nw1, w0, in[01]), and_00(dout[00], nw3, nw2, nw1, nw0, in[00]); assign out = | dout; // The same coments as for the size and complexity of the decoder. // The most part of the multiplexor is made by a decoder; for this reason the size // the depth and the complexity are in the same order as for decoder. endmodule module test_mux; reg[3:0] sel; reg[15:0] in; wire out; initial #33 $stop; initial begin sel = 4'b0; //in = 16'b1100101011110000; in = 16'b1111111100000000; forever #1 sel = sel + 1; end mux16_1 dut(out, in, sel); initial $monitor("Time=%0d out=%b", $time, dut.out); endmodule */ /* Please explain the differences in the form of results displayed by the test performed with the same procedure on the same, but distinctly described, circuit. */ /*************** PROBLEM NO.9: The transcoder for 7-segment display The most significant bit corresponds to the top segment, continue circulating to the right, ending with the central segment */ /* module seven_seg(segments, number); input[3:0] number; output[6:0] segments; reg[6:0] segments; always @(number) case (number) 4'b0000: segments = 7'b1111110; 4'b0001: segments = 7'b0110000; 4'b0010: segments = 7'b1101101; 4'b0011: segments = 7'b1111001; 4'b0100: segments = 7'b0110011; 4'b0101: segments = 7'b1011011; 4'b0110: segments = 7'b1011111; 4'b0111: segments = 7'b1110000; 4'b1000: segments = 7'b1111111; 4'b1001: segments = 7'b1111011; endcase // There in not another more simple variant to describe the circuit than the previous truth // table with 10 inputs and 7 outputs. Therefore, the circuit is a complex one. endmodule module test_trans; reg[3:0] counter; wire[6:0] segments; initial #22 $stop; initial begin counter = 0; forever #1 counter = counter + 1; end seven_seg dut(segments, counter); initial $monitor("time=%0d input=%b output=%b", $time, counter, dut.segments); endmodule */