CSCI 320 — More Verilog and a little VHDL

It is assumed that you have already completed the first lab where you implemented a full adder and its test bench. In this lab there are three activities.

You can find a pretty good overview of Verilog in the Verilog overview & references page at Texas A&M.

Using a state machine specification in Verilog

Getting ready

Start up ModelSim by typing vsim & at the command line prompt.

Open you project from the last lab. It should contain fulladder.v, a rather succinct implementation of a full adder, testbench.v, a testbench for your full adder.

Use the testbench to exercise the full adder to refresh your memory and to get ready for the next part.

A state machine in Verilog

In Verilog, a finite state machine specification is given as a user defined primitive (UDP). The UDP looks like a module with a truth table inside. The truth table is inconveniently confined to have only one output column. Also, in the header for the UDP, the single output must be the first parameter; and, in the table of the UDP, the single output must be the last column.

Open up fulladder.v and add, via cut-and-paste, a UDP called sumbit for computing the sum bit of the full adder.

// Compute the sum bit
primitive sumbit (
  output Sn,
  input An,
  input Bn,
  input Cn
) ;

  table
  // An Bn Cn -->   Sn
      0  0  0   :    0 ;
      0  0  1   :    1 ;
      0  1  0   :    1 ;
      0  1  1   :    0 ;
      1  0  0   :    1 ;
      1  0  1   :    0 ;
      1  1  0   :    0 ;
      1  1  1   :    1 ;
  
  endtable

endprimitive

Now it’s your turn. Within this same file, create a second UDP called carrybit for computing the carry bit of the full adder. It will look a lot like sumbit, so start with a copy.

Using your UDP’s

Now you must modify your fulladder module to use sumbit and carrybit. We do this by using a structural implementation, similar to our first implementation, the structural implementation with logic gates, of the full adder in last week’s lab.

The entire body of your fulladder consists of only two lines, one a “call” to carrybit and the other a “call” to sumbit. You don’t even need to introduce any new variables.

Try to complete this one on your own, but ask for help if you are stuck.

Running the testbench

You don’t need to change the testbench. Just use it.

Show the instructor a run of your testbench with the UDP implementation.

A very quick look at VHDL

VHDL and Verilog have shared the circuit specification market for years, although Verilog; with the help of SystemVerilog, may now be pulling ahead. The design philosophies of VHDL come from ADA, which is a bit like Pascal and C++. You may find them to be a little odd.

We won’t use VHDL in any significant way in this class, but you should see at least one VHDL program.

Creating the project

Close your Verilog full adder project and create a new project called lab2vhdl inside your csci/320/lab2 directory.

Adding an interface

Start by adding a single VHDL file called fulladder.vhd containing the following.

library IEEE ;
use IEEE.STD_LOGIC_1164.all ;

-- specification for the fulladder interface
-- PS:  Think Java abstract method
entity fulladder is
  port(
    An: in STD_LOGIC ;
    Bn: in STD_LOGIC ;
    Cn: in STD_LOGIC ;
    Cnp1: out STD_LOGIC ;
    Sn: out STD_LOGIC) ;
end fulladder ;

Study this for a little while. There is no real code. This file is a bit like the a Java interface or a C++ .h file. It does not implement the full adder, it just specifies the types of the ports. Go ahead and compile this file, just like you might compile a Java interface.

Also, notice the library and use statements. They should remind you of the import of Java. It should already be clear that VHDL is a wordy programming language.

Adding an implementation

Next add another VHDL program, this time stored in fulladderdf.vhd, to your project. (Right-click in the Project tab to add a file to the project.)

This program will be a dataflow implementation of the full adder. Start with the following almost-complete definition and then add the one missing line.

library IEEE ;
use IEEE.STD_LOGIC_1164.all ;

-- dataflow implementation of fulladder interface
architecture fulladderdataflow of fulladder is
  begin
    Sn <= An xor Bn xor Cn ;
  end ;

You really do have to spell out the logical operators as and and or. I told you VHDL was wordy.

Isn’t it odd you don’t even give the parameter names in the architecture. That’s one difference with the Java interface.

Simulating your VHDL full adder

You can simulate your VHDL full adder without a test bench, just like your simulated your Verilog full adder at the beginning of the first Verilog lab So start up the simulator, add input and output ports to the wave, and type commands like the following at the vsim prompt. Be sure to select fulladderdataflow, and not fulladder, for the simulation. You need to select the Architecture, not the Entity. This means expanding down two levels.

> force An 0
> force Bn 0
> force Cn 0
> run 100

Show off your simulation.

A VHDL test bench

Let’s include a VHDL test bench to the mix.

Call it testbench.vdh and just cut-and-paste this entire program. It would be too much to expect you to write it.

library IEEE ;
use IEEE.STD_LOGIC_1164.all ;
use IEEE.STD_LOGIC_UNSIGNED.all;

-- Neither input or output
entity testfulladder is
end testfulladder ;

-- actual test bench
architecture fulladdertester of testfulladder is
  component fulladder
      port(
        An: in STD_LOGIC ;
        Bn: in STD_LOGIC ;
        Cn: in STD_LOGIC ;
        Cnp1: out STD_LOGIC ;
        Sn: out STD_LOGIC) ;
  end component ;

  signal vin  : STD_LOGIC_VECTOR(2 DOWNTO 0) := "000" ;
  signal vout : STD_LOGIC_VECTOR(1 DOWNTO 0) ;
  
  begin
    dut: fulladder port map(
       An => Vin(2), 
       Bn => Vin(1),
       Cn => Vin(0),
       Cnp1 => Vout(1),
       Sn => Vout(0)) ;
    
    process begin
      wait for 100 ps ;
      vin <= vin + "1" ;
    end process ;
  end ;

Notice that this program has both the entity specification and the architecture implementation. Also, note how the fulladder component is connected to the testbench program.

We will talk a bit more about this program in class. For now, just simulate it.

Run the VHDL testbench and display its inputs and outputs within the wave simulator.

By the way, in the old days, the testing engineers ran the simulations as a ”batch“ job and looked at the wave forms later using programs. GTKWave, Some still do this. There are even YouTube tutorials to guide you through the experience.

Today large simulations may run for weeks. In this case, extensive testbench programs are created that thoroughly test the design and produce a report for the testers.

ModelSim on your own

It’s time for the first near-solo flight. Here are links to a couple of files from the textbook.

These files are neither Verilog or VHDL. They are in SystemVerilog, your third HDL dialect of the lab.

Create a new project with one of these programs. Be sure to add the file as a SystemVerilog.

Start up the simulator, but do not expect reasonable output until you have clock the circuit at least once. You may be a little problem using the force on vector values. Just type the bits.

Do a simulation that would illustrate if you are using the latch or the flip flop.