Ok, I'm doing this from memory.  The electricity is out, so I'm
writing this on the notebook and hoping that the UPS on the networking
hardware doesn't go out before I finish.  :)

Anyhow, here are some gates that should be posted on the wiki.
Actually, they need some editing first, and people should decide on a
"standard" way of expressing these things.


// Hex inverter
module IC7404(i0, i1, i2, i3, i4, i5, o0, o1, o2, o3, o4, o5)
input i0, i1, i2, i3, i4, i5;
output o0, o1, o2, o3, o4, o5;
assign o0 = !i0;
assign o1 = !i1;
assign o2 = !i2;
assign o3 = !i3;
assign o4 = !i4;
assign o5 = !i5;
endmodule

Actually, there are lots of ways to do this, for instance:

module IC7404(
    input [5:0] i,
    output [5:0] o);
assign o = ~i;
endmodule


// Quad 2-input AND gate
module IC7408(
    a0, b0, a1, b1, a2, b2, a3, b3,
    c0, c1, c2, c3);
input a0, b0, a1, b1, a2, b2, a3, b3;
output c0, c1, c2, c3;
// Since these are single bits, the && operator would work, but we're
using & for
// the semantic consistency with what we're doing.  I.e. this is bit-wise.
assign c0 = a0 & b0;
assign c1 = a1 & b1;
assign c2 = a2 & b2;
assign c3 = a3 & b3;
endmodule

For OR gates, just replace & with |.  Also, if you want a bus version
(a[3:0], b[3:0], c[3:0]), that is an exercise for the reader.

If you want to make something tristage, there are a couple ways to do
it.  But I think we should stick to the idiom that synthesizers like
to see when you're tristating an output buffer connected to a pin.
(Chips don't typically do tristate internally!)

module some_octal_tristate_buffer(
    input [7:0] in,
    input enable_bar,  // Arbitratily, I choose to make it low-assertion
    output [7:0] out);
assign out = enable_bar ? 8'bzzzzzzzz : in;
endmodule


module IC7400(
    input a[3:0],
    input b[3:0],
    output c[3:0])
assign c = ~(a & b);
endmodule

If you're wiring individual signals to this one, just use {} to group
them.  For instance:

wire x, y, z, w;  // these are some of the inputs
IC7400 my_7400_instance(.a({x, y, z, w}), .b(more_inputs), .c(the_outputs));


7401 is open-collector quad NAND gates.  That means, IIRC, that the
outputs will only pull down.  If the output is high for 7400, then it
floats (z) for 7401.  We normally wouldn't bother doing such a think
internally in an FPGA, semantically, it corresponds to this:

module IC7401(
    a0, a1, a2, a3, b0, b1, b2, b3,
    c0, c1, c2, c3);
input a0, a1, a2, a3, b0, b1, b2, b3;
output c0, c1, c2, c3;
assign c0 = (~(a0 & b0)) ? 1'bz : 0;
assign c1 = (~(a1 & b1)) ? 1'bz : 0;
assign c2 = (~(a2 & b2)) ? 1'bz : 0;
assign c3 = (~(a3 & b3)) ? 1'bz : 0;
endmodule


A 3-input AND would need this:
assign d0 = a0 & b0 & c0;


I don't actually know what they mean by "buffer" and "driver".  I
usually think of a buffer as being a register, and a driver as
something that drives an output pin.

Here, pick some interesting ones from this list and try your hands at
it or ask me, and I'll write some:

http://en.wikipedia.org/wiki/List_of_7400_series_integrated_circuits

And this:

http://www.baltissen.org/newhtm/ttl.htm


// This is only half a 7474
module IC7474(preset, clear, clock, data, Q, Q_bar);
input preset, clear, clock, data;
output Q, Q_bar;
reg Q;
assign Q_bar = ~Q;
// You cannot synthesize this design!
always @(preset) if (preset) Q <= 1;
always @(clear) if (clear) Q <= 0;
always @(posedge clock) Q <= data;
endmodule


module IC74138(
    input [3:0] select,
    input G1_bar,
    input G2_bar,
    input G,
    output reg [7:0] out);
always @(select, G1_bar, G2_bar, G) begin
    if (G1_bar==1 || G2_bar==1 || G==0) begin
        out = 8'b11111111;
    end else begin
        case (select)
            0: out = 8'b11111110;
            1: out = 8'b11111101;
            2: out = 8'b11111011;
            3: out = 8'b11110111;
            4: out = 8'b11101111;
            5: out = 8'b11011111;
            6: out = 8'b10111111;
            7: out = 8'b01111111;
        endcase
    end
end
endmodule

Here's another way to do it.  This one is shorter, which isn't really
a good thing for HDL.  Explicit is better.  A good synthesizer will
make the above give you very good results.  However, for the sake of
interest, here's a more concise way:

module unpreferably_IC74138(
    input [3:0] select,
    input G1_bar,
    input G2_bar,
    input G,
    output reg [7:0] out);
wire [7:0] intermediate = (!G1_bar && !G2_bar && G) << sel;
assign out = ~intermediate;
endmodule

Verilog has this concept of "natural size", which is a set of rules
that dictate the number of bits in an expression.  Sometimes, the
expressions don't fully specify the width.  Using the intermediate
above forces the left-shift of a 1-bit quantity to come out as an
8-bit number.




-- 
Timothy Normand Miller
http://www.cse.ohio-state.edu/~millerti
Open Graphics Project
_______________________________________________
Open-graphics mailing list
[email protected]
http://lists.duskglow.com/mailman/listinfo/open-graphics
List service provided by Duskglow Consulting, LLC (www.duskglow.com)

Reply via email to