|
Login |
HDL_Resources
A hardware description language (HDL) describes the functionality of logic circuits. Given such a description, the design can be simulated or synthesized into a network of elementary gates, like AND, OR, NOT, flip - flops, up to more complex units defined in libraries.
VerilogThe OGP will use Verilog for all HDL programming, at least that's the plan for now. Web ResourcesTutorials
Verilog Lessons - By Tim
Getting Started - A Beginners Tutorial.Here is an example of writing a simple design in verilog: The chip we are looking at implementing is the 3line to 8line decoder, 74S138. For those wondering, the Integrated Chip or IC 74138 has three inputs, 3 chip enables. 8 Outputs. Depending upon the inputs and gates, only ONE output may go low. Here is a datasheet with a truth table (a table explaining when what works) another with the package symbols 74138 Truth Table
L = Low voltage. H= High Voltage. X means 'dont care', in that it is not defined as it could be either High OR Low. # refers to Active Low in that the signal will be inverted. For example Output Enable pin #E1 is inverted, an active low. A programmer may be understand it as !E1. Lets examine the table above. Inputs Enable E1:E3 The three enable pins allow the output to change. All outputs are held high until these three are set. Only when #E1 is Low, #E2 is low and E3 is high does the output change. This can be handy in that you can take your time setting up the output settings and only when you are ready, do you allow the output to show. Binary weighted Inputs A0:A2 These three binary inputs affect the output. It is essentially a binary counter - you can see it when the enable pins are set, look at the Low output that cascades through the outputs #o0:#o7. Mutually Exclusive Outputs #O1:#O7 These outputs are active low. They change, in that the output goes low when set. But only One output goes low at any time. Now lets get to writing some verilog. Open your favourite editor. Set the language to Verilog and lets get started. Because the filename or module cannot start with a number, calling it 74318 is not permitted. Instead, lets call the module IC74318 To begin with, here is a version of the IC 74138 as a Verilog module: module IC74138( input[0:2] in, input[0:7] out, input Gbar2A_n, input Gbar2B_n, input G1, ); assign out = (!Gbar2A_n & !Gbar2B_n & G1)?(255 - (1<<in)):255; endmodule Not much typing, was there? Now this relies on the synthesis software to work out the details, and when you leave it up to the synthesizer to infer what you want, you take the risk of having it infer something inefficient. When optimizing to meet timing or area constraints, a designer may be forced to do some things that hide the true semantics behind what's going on (Just compare the simulation and synthesis models of the OGP PCI controller), but this is not such a case. Rather, the above is an example of how NOT to code Verilog. In other words, we don't want to try to play cute tricks with the language syntax. When you're designing something in the first place, you should strive to make your code as explicit and readable as possible. More code in Verilog does not necessarily translate to more gates. In fact, quite the opposite is true in many cases. Lets try again, and this time we will add some comments and use standard naming methods: module IC74138( // 3-to-8 demultiplexer input [2:0] CBA, // Select which output to pull low output [7:0] Y, // Output input Gbar2A_n, // Pull low to enable - shown by the suffix _n input Gbar2B_n, // Pull low to enable input G1, // Pull high to enable ); // First, combine the enables together. When the disable signal is high, // all outputs are forced high. wire disable = Gbar2A_n || Gbar2B_n || !G1; // Now, compute each of the individual outputs assign Y[0] = (CBA != 0) || disable; assign Y[1] = (CBA != 1) || disable; assign Y[2] = (CBA != 2) || disable; assign Y[3] = (CBA != 3) || disable; assign Y[4] = (CBA != 4) || disable; assign Y[5] = (CBA != 5) || disable; assign Y[6] = (CBA != 6) || disable; assign Y[7] = (CBA != 7) || disable; endmodule You may be able to come up with a form of this that uses less logic or is faster, but there is not much value in optimizing too early. Maintainability is more important than confusing yourself. However, it is also the case that repeating yourself a lot in code can cause you to make errors. What if we renamed all the Y subscripts but forgot to change one or more of what CBA is being compared to? That can be a problem. So here's a more terse representation that, for an experienced designer, can have some readability and error-proneness advantages: module IC74138( // 3-to-8 demultiplexer input [2:0] CBA, // Select which output to pull low output reg [7:0] Y, // Output (marked reg for behavioral block) input Gbar2A_n, // Pull low to enable input Gbar2B_n, // Pull low to enable input G1, // Pull high to enable ); // First, combine the enables together. When the disable signal is high, // all outputs are forced high. wire disable = Gbar2A_n || Gbar2B_n || !G1; // Now, compute each of the outputs integer i; // Loop variable always @(CBA or disable) begin for (i=0; i<8; i=i+1) begin Y[i] = (CBA != i) || disable; end end endmodule Those who never make mistakes never need to test. If you are wondering, their number may be counted on your fingers with one hand behind your back. For the rest of us, developing a good test makes the difference between something that can reliably work first time, and something that mostly works. Be wary of a design that mostly works - it apparently causes baldness. For those who wish to keep their good looks, here is a test module, which is admittedly a rather good idea: module test(); reg[0:2] in = 0; wire[0:7] out; reg[0:2] en = 4; always begin #2 in <= in + 1; end initial begin $monitor("%d in, %d out",in,out); end IC74138 U0(in,out,en[2],en[1],en[0]); endmodule This just instantiates the module and runs through a simple test. The next step is to actually compile and run the module. Save the first code block as IC74138.v and the second one as IC74138_test.v - - in general, this is the format of a verilog module and test suite. Save them both in /home/USER/verilog - logic. After that, download Icarus Verilog using apt - get, yum, port, emerge, or whatever other command you need to get it (see SimulationAndSynthesisTools for how to install Icarus) This allows you to run the model and see if it works without having to physically program an FPGA. It also allows you, in conjunction with gtkWave or a similar program, to view all the signals in a model (but that logging must be enabled - - for another time). Now you have all the tools that you need. cd ~/verilog - logic so you can compile the program, and then run a straightforward command which looks an awful lot like gcc: iverilog IC74138_test.v IC74138.v - o IC74138_run This will then produce an executable that uses the vvp environment to run verilog code. It can be executed on the command line using: ./IC74138 The output is printed; it loops over the following: 0 in, 254 out 1 in, 253 out 2 in, 251 out 3 in, 247 out 4 in, 239 out 5 in, 223 out 6 in, 191 out 7 in, 127 out Converted to binary, this is the output it should have. You can print it as binary by replacing the %d above with %b. Then it is more obvious that it works: 000 in, 11111110 out 001 in, 11111101 out 010 in, 11111011 out 011 in, 11110111 out 100 in, 11101111 out 101 in, 11011111 out 110 in, 10111111 out 111 in, 01111111 out This is a good test for the times when the 74S138 is enabled, but it is also important to make sure that other functionality works just as well, e.g. the output is 11111111 when the correct enable is not present. To this end, here is another version of the test bench which deals with enable testing: module test(); reg[0:2] in = 0; wire[0:7] out; reg[0:2] en = 0; always begin #2 in <= in + 1; end initial begin $monitor("%d %b in, %b en -> %b out",$time,in,en,out); #8 en <= en + 1; // Now it is 1 after 8 ticks #8 en <= en + 1; // Now 2 after 8 ticks #8 en <= en + 1; // Now 3 after 8 ticks #8 en <= en + 1; // Now 4 after 8 ticks #50 en <= en + 1; // Now 5 _after_ 50 ticks — for these 50 ticks, en = 4 #8 en <= en + 1; // Now 6 #8 en <= en + 1; // Now 7 #8 en <= 0; // Now 0 - en is 3 bits, equivalent to en <= en + 1. $finish; end SN741S138 U0(in,out,en[2],en[1],en[0]); // instantiate the tested module endmodule This introduces two new benchmark commands: $time, which just gives the current execution tick, and $finish, which stops the benchmark. The output is much longer for this one and has not been added. This is a nice idea of what some Verilog might look like, but why not try a harder example? Here is a more complicated example - - try writing a test bench for it! It is the same idea as above, except that there are internal NAND gates that are separate, so they are each treated as a different Verilog module. It also uses explicit inputs and outputs - - as another challenge, try converting them to the array format. See other people's solutions when you are done at 7408. module GATE2INAND(a,b,x); input a, b; output x; assign x=a&b; endmodule module IC7408(a0, b0, a1, b1, a2, b2, a3, b3, x1, x2, x3); input a0, b0, a1, b1, a2, b2, a3, b3; output x1, x2, x3; GATE2INAND AND0( .a(a0), .b(b0), .x(x0)); //The period shows we are using a hierarchical name GATE2INAND AND1( .a(a1), .b(b1), .x(x1)); // The format is .<the net's name>(<the port name>) GATE2INAND AND2( .a(a2), .b(b2), .x(x2)); GATE2INAND AND3( .a(a3), .b(b3), .x(x3)); endmodule Other
BooksVerilog and VHDLhttp://www.jmlzone.com/ Verilog Quickstart Third Edition. (Jb) This book provides a CD and quickly introduces you to simulation and synthesis. The author has been supportive of OGP.A slightly cheaper book I've (Hamish) found is Fundamentals of Digital Logic with Verilog Design. The book comes bundled with a copy of Max - II software. "HDL Chip Design" by Douglas J. Smith. (Timothy) This book that has VHDL and Verilog side - by - side "Verilog HDL Synthesis: A Practical Primer" by J. Bhasker. (Timothy) "Digital Design and Synthesis with Verilog HDL" by Sternheim, Singh, Madhavan, and Trivedi. (Timothy) LibrariesP. Mc Namara Nov 07: if we put together a library of gates and chips like this, the you could take a gschem netlist and generate Verilog RTL for the circuit (assuming it's all digital of course). Also for someone just learning Verilog and potentially digital logic, building simple blocks first, then layering it all together may make more sense. In the end the result (and I would hope synthesis) would be the same. Obviously, not all the 74xx chips make sense to be broken down this way, but many do. In fact you can even find the logic diagrams for many on their data sheets. T. Miller: pick some interesting ones from this list and try your hands at it
JB. Search for the datasheet using google - especially those that provide the gate logic, and implement that. Please add a truth table in the comments section of verilog. Terry: drop the numbers into this search engine: http://www.datasheetcatalog.com E.g. "74138" turns up several, including this one: http://www.tranzistoare.ro/datasheets/90/232315_DS.pdf Formatting Hints - Because we are looking for code to be used in a public library: Each Pin must be a separate input or output - or as Timothy said: for the basic logic gates, every signal is single-bit. When making a truth table, make a space on the left - this will make the text mono space and easier to work with. Use two spaces instead of Tabs for indentation. Dont use a leading underscore ie: _ before names, as this will not be VHDL friendly - we want a library for all. The license must be as open as possible, or Public Domain. When the wiki turns your code into a link, disable wiki formatting by using this ~np~ ((7400|link)) ~/np~
Created by: urkedal last modification: Monday 16 of August, 2010 [10:49:09 UTC] by smalltux |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||