If you are from a software background coming into digital design using CPLD/FPGAs (complex programmable logic devices/field programmable gate arrays) then you need to adopt a different way of thinking for designing logic. While Verilog and VHDL look like a conventional programming language, the way it is interpreted is different. With software for a microprocessor the operation of software is strictly sequential. Ten instructions in a row will be executed one at a time, one after the other. However, in Verilog and VHDL the code is compiled into something which will satisfy the entirety of the code simultaneously. That does not mean that things won’t be sequential if that is how you have written it, but something as simple as
A = B;
B = A + 1;
will cause confusion. With conventional software, if B had a value of 10 then A would also become the value 10 and B would then become 11. However, for a CPLD the code will try to find some logic which will satisfy both statements simultaneously, which is tricky, so you will most likely get an error.
So, you need to remember that you are designing some logic and what you describe will ultimately end up as a mass of logic gates and flip-flops that will all work together to satisfy your description. The benefit is speed. A complex operation that takes dozens of operations in software will take a significant time to complete whereas it could be done in a single clock cycle if it can be represented as a chunk of digital logic.
That is not to say that you won’t use sequential operations in a CPLD. For example, if you want a multiply function for two 8 bit numbers with a 16 bit result, you could simply do all that with a lot of logic and it could be completed very quickly. However, space or CPLD size may be more important than speed for that operation for a particular application, so you could implement the multiplication by a shift and add approach which will take longer but a lot less logic.
If you are from a digital electronics background then describing logic with software like statements could still seem strange. In the past, programmable logic devices (PLDs) were small and could be coded manually or with a fairly low level language where you are directly controlling D-type flip-flops for example. The size and complexity of current devices mean that approach is rarely used and a higher level approach is taken. Unfortunately the tools for working with CPLDs has become a bit fragmented and you will often find you are working in one tool for the design and then another for synthesis and yet another for simulation. These pieces of software can often be from different vendors with different user interfaces.
As an example, take the very simple half adder above. That can simply be described in Verilog as
module half_adder(A, B, S, C);
input A, B;
output S, C;
assign S = A ^ B;
assign C = A & B;
endmodule
You will probably notice that it is not unlike microcontroller software. However, as already mentioned, statements written sequentially don’t necessarily produce a sequential results. For example, S and C above will both be implemented with parallel logic in the same way as the logic diagram. S will not be assigned before C, even thought the statements are in that order. If you reordered the statements the resulting logic would be the identical.
In order to test your code you need a “testbench”. While some software allows you to interactively generate a stimulus graphically, the increasing complexity of devices and designs means that it is normally done with yet more Verilog code. Also, looking through a huge number of waveforms would not necessarily be very efficient and you may not spot errors so a typical testbench would include not only the stimulus for the logic, but also check the results. This means that the testbench will often taken longer to write than the initial code, take more lines of code and longer to debug. This is in addition to debugging the code you wrote in the first place!
Anyway, for this simple example I will show a simple stimulus with no output checking.
`timescale 1 ns / 100 ps
module half_adder_tb ( );
wire S_test, C_test;
reg A_test, B_test;
half_adder dut(.A(A_test) , .B(B_test) , .C(C_test), .S(S_test));
initial
begin
#5 A_test = 0;
B_test = 0;
#5 A_test = 1;
B_test = 0;
#5 A_test = 0;
B_test = 1;
#5 A_test = 1;
B_test = 1;
end
endmodule
The “timescale” directive defines the time unit and precision. Note that it is preceded by a “grave accent” NOT an apostrophe! The module “half_adder_tb” is the testbench module which contains the actual logic using the “half_adder dut” statement which requires the half_adder module to be included in the project. After that, from the “initial” statement, is the actual stimulus. Note that now the statements are actually sequential with #5 representing a delay of 5 time units – 5ns in this case. The resulting waveforms are:
That was a simple combinatorial logic example but you are more likely to be writing registered code. A simple example of an 8 bit counter with asynchronous reset is shown below:
module cntr ( clk, count, rst );
input clk;
input rst;
output [7:0] count;
reg [7:0] count;
always @( posedge clk or negedge rst )
begin
if(!rst) count <= 8’h00;
else count <= count + 8’h01;
end
endmodule
Here the variable “count” consists of 8 bits and is defined as type “reg” as well as being an output from the module. The code after the @ symbol is the sensitivity list and defines when changes happen within the block. In this case the reset is active low and asynchronous. A small change would make it synchronous:
always @( posedge clk)
begin
if(!rst) count <= 8’h00;
else count <= count + 8’h01;
end
Now the counter will only change on the positive edge of the clock.
The best way to learn Verilog is to have a “real” project to do, but start with a tutorial first. If you have a particular CPLD vendor you plan to use then download their free software (most vendors supply free versions as they want to encourage you to use their devices) and look for demo code and tutorials. These will be tutorials on how to use their software really, but that is essential anyway.
A search for tutorials on the Internet will produce a lot of results, some good, some bad. Some Verilog books are huge reference tomes and while these may be useful when you progress, they can be a bit daunting to start with. One “quickstart” book is over 350 pages long. A more concise (and cheaper) starting book is probably “Verilog By Example” by Blaine Readler. At just over 100 pages it is a more manageable starter book.
Leave a Reply
You must be logged in to post a comment.