Adding the Hard Way

I’ve been talking about how to design hardware logic circuits using Verilog. There was a time when doing programmable logic like FPGAs cost a fortune. You needed an expensive workstation and even more expensive tools.

Today, your PC is probably far better than most – or all – of the engineering workstations I ever had. You can get open source software, and most of the vendors (like Xilinx and Altera) have very capable free versions of their software.

I don’t want to get locked into Xilinx or Altera, both because I want to focus on basic ideas and because I don’t want to deal with the learning curve. The tools can do a lot, but that means you should expect to spend a little time getting comfortable with them. Instead, I want to get started with an open source Verilog simulator called Icarus Verilog. If you use Linux you can probably install it from your package manager. You can install or build it on any Linux, and it also works with Windows, Solaris, and Mac. There are other similar simulators, but I’m using this one.

The simulator will convert your Verilog code into a make-believe digital circuit and then simulate its behavior. The output will be a waveform file that you need a special viewer to see. I personally use GTKWave although there are others out there (search for VCD viewer).

Last time, I showed you some simple logic gates in Verilog. In retrospect, maybe they are too simple to be interesting to simulate, so consider this full adder:

// Truth table
// a   b    cyin    y   cyout
// 0   0     0      0    0
// 0   0     1      1    0
// 0   1     0      1    0
// 0   1     1      0    1
// 1   0     0      1    0
// 1   0     1      0    1
// 1   1     0      0    1
// 1   1     1      1    1

module fulladd(output y, output cyout, input a, input b, input cyin);
   assign y=a+b+cyin;
   assign cyout=(a&b)|(b&cyin)|(a&cyin);
endmodule // fulladd

There are other ways to accomplish this, of course, but this is a start. The idea is to do a single bit addition, outputting a sum and a carry. The circuit has an input carry so you can easily build multibit adders. Remember, though, in a real system I wouldn’t do that. I’d just describe the multibit add in Verilog and let the simulator or compiler figure it out. But – going back a few weeks – this is the crystal radio project you can use to get started.

I’ll assume the above is in a file named fulladd.v. The Verilog is synthesizable – a compiler could generate a bit stream that would program an FPGA to perform this function. I’ll talk later about what else you’d need to make that practical. For now, I just want to verify that it works as I expect through simulation.

To do that, I need to write a test bench. This is just a Verilog module that may be too complex to synthesize, but will exercise the adder module. You could make it fancy, but here’s a simple version to get started:

module test();
   wire out;
   wire carry;
   reg 	in1;
   reg 	in2;
   reg 	in3;
   fulladd dut(out,carry,in1,in2,in3);  // device under test
   #5 in1=1;
   #5 in2=1;
   #5 in3=1;
   #5 $finish;
  end // initial begin
endmodule // test