Coding Standards

Cse141L is not a course on Verilog programming, but you did need to understand a subset of Verilog in order to complete the labs.  To keep the Verilog learning curve as easy as possible, we restrict you to subset of Verilog that sufficient for this course.  We also place some additional rules on the code you write.  If you follow these rules, they will help you to avoid many common bugs, and it will make easier for the course staff to help you with problems that arise.

If you come to the course staff with questions about your code, the first thing we will do is look at it to check that you are following these rules.  If you aren't we'll ask you to go bring your code into compliance and see if that helps to eliminate your problem.  Often it will, so following these guidelines will save all of us some time and debugging headache.

The GCD example referred to below is attached to the bottom of this page, and should be available at <course home page>/Media/GCD.zip.  The PDF attached to this page discribes the example in detail, although it does not match the implementation in GCD.zip perfectly (it's very close) and the code in the PDF has some bugs (the GCD.zip code has no known bugs).

Unbreakable Rules

The coding guidelines in this document are pretty restrictive, and it's possible that you'll find your self with a burning desire to violate some of them.  In some cases, that may be ok (although you'll need to be able to justify your decision to the course staff if you ask them to debug your code).  However, there are some rules in Verilog that should never be broken.  If we see violations of these in your code, you'll have to fix it.  No exceptions.

  1. Only use "<=" in "always @(posedge clock)" blocks.
  2. Only use "=" in "always @(*)" blocks.
  3. In this class, these are the only kind of always blocks you should have.
  4. Do not assign to the same reg or wire in two always blocks.

General Guidelines

Here are some general guidelines you should follow in all your code:
  1. Use constants instead of literal constants (i.e., "magic numbers").  0 and 1 are not magic. (And bare constants are ok in test vectors).  There's a whole separate page about defining and using constants.
  2. Always declare your nets.  If you see "Warning (...):  Verilog HDL Implicit Net warning..." that means you've failed to declare a net.  Could be a capitalization problem.  Could be mis-typed name.  Get rid of these warnings, and you will eliminate bugs.
  3. Only use synthesizable constructs in non-testbench code.
    • No loops!
      • EXCEPTION: You may use a loop for a reset of your register file.
    • No complex math (no "integer" or floating point variables.  No division, no %)
    • These are ok:  if-then-else, case, assign, +,-, <<, >>, &, &&, ==, ||, {}, etc.
    • Anything we mention below or use in the GCD example is ok.
  4.  Always instantiate modules using named ports rather than positional ports (i.e, .clk(clk)).
  5. Use consistent and descriptive naming conventions.
    • e.g., A_mux -- the mux for variable A
    • e.g., A_in -- the input named A
    • e.g., A_mux_sel_in -- the input that will go to the select line on the mux for A.
    • See the GCD example for more.

Module Types

For the purposes of this class, there are five different types modules you will need to implement.
  1. Combinational modules.  These contain simple, unclocked, combinational logic.  Things like multiplexors, adders, sign-extenders, etc. all fall into this category.
  2. Register modules.  These implement (usually multi-bit) flip flops and registers.
  3. Structural modules.  These modules contain instantiations of the other module types (including other structural modules) and connect them to one another.
  4. State machine modules.  These modules implement a state machine.
  5. Register files.  These modules implement processor register files (i.e., a single module that contains multiple storage locations, and allows for accessing them).
  6. Test benches.  These are verilog modules that allow you to apply inputs to other modules for testing or otherwise drive the other modules.
THe first 5 module types above are "synthesizable."  This means that they correspond to real hardware, and that means they can only include a subset of verilog constructs (namely the synthesizable ones).  Test benches are not synthesizable, so they can include much more.

We describe each of these module types in detail below, and provide the coding guidelines for each type.  When you are coding, it should be very clear to you which type of module you are working on.  If it's not, or your module seems to belong in more than one category, you need to rethink your design and probably break the module into multiple parts.

Synthesizable Modules

Since synthesizable modules can only contain verilog that corresponds to real hardware, they cannot include the following:
  1. # directives (i.e., that insert delay)
  2. "initial" blocks.
  3. real, time, float, integer, or realtime variables
  4. Anything that starts with $ (e.g., $display or $monitor)

Combinational Modules

Combinational modules should contain logic that does not require a clock and does not hold any state.  Modules such as muxes, adders, ALUs, shifters, comparators, decoders, etc. should all be implemented as combinational modules.  Here are the rules for combinational modules:
  1. They may not contain any module instantiations.  I.e., they must be "leaf modules"
  2. They may contain exactly one "always@(*)" block and no other always blocks.
  3. They should not have a clk, reset, or enable input.
  4. All module output should be declared as regs.
  5. The always block must assign values to all outputs in all cases.  There are several ways to ensure this:
    • Assign all the outputs default values at the top of the always block.  This is the safest.
    • Ensure that all outputs are assigned in all options of an if-then-else constructs and that the there is a final "else" clause.
    • Ensure that all outputs are assigned in all options of a switch construct and that there is a final "default" clause.
  6. The always block may not contain any non-block assignment (i.e., it contain "<=" assignment operator)
  7. All inputs should have the "_in" suffix.  
  8. All outputs should have the "_out" suffix.

Example

For an example of a combinational model, take a look at Mux3.v in the GCD example.

Register Modules

Register modules implement flip flops and multi-bit registers.  In this course, we'll use positive edge-triggered flip flops, with synchronous reset, and an active-high enable line.  Here are the rules for register modules:
  1. They may not contain any module instantiations.  They must be leaf nodes.
  2. They may contain exactly one "always @(posedge clk)" block, and no other always blocks.
  3. They may not contain any "assign" statements.
  4. Outputs should be declared as regs.
  5. All input signal names should have the "_in" suffix.
  6. All output signal names should have the "_out" suffix.
  7. They must have a clk, reset, and enable input.
  8. The always block may only contain non-blocking assignments that use the "<=" assignment operator.   The "=" assignment operator is not allowed.

Example

For an example of a combinational model, take a look at FF.v in the GCD example.

Structural Modules

Structural modules connect other modules together, but they do not define any new state or implement any logic.  Registers, Register files, and combinational modules are leaf modules, but structural modules are always non-leaf modules and are, in fact, the only kind of non-leaf module we allow.  Here are the rules:
  1. If the structural module contains any clocked modules (i.e., register file, state machine, or register modules), the structural model should also have a clk and reset input.
  2. All input signal names should have the "_in" suffix.
  3. All output signal names should have the "_out" suffix.
  4. Output signals should not be declared as regs (i.e., they are wires) 
  5. The structural module can contain any number of module instantiations.
  6. It can also include declarations for wires to connect the instantiated modules together.
  7. You must declare the widths of all your wires.
  8. It may also include simple "assign" statements of the form "assign a = b".  No complex expressions (i.e., no math) is allowed on the right hand side of the assign.  YOu can "pad" narrow signals to match wider outputs if needed.  You can also assemble multiple single into a wider bus output if needed.
  9. All clocked modules should be connected to the structural module's clk, reset, and enable.
  10. It may not contain any always blocks.
  11. It may not declare any regs.

Example

For an example of a combinational model, take a look at GCDdatapath.v in the GCD example.

State Machine Modules

State machine modules implement state machines.  In this class, we will use them to implement the control path for our processors.  State machine models contain both combinational logic and state, so they combine some aspects of register modules and combinational modules.  In this classes, we'll be implementing state machines in a very structured way that makes them easy to debug and implement.

Here are the rules:
  1. The module should contain an "always@(*)" block that computes state transitions based on the modules inputs an the module's current state.
    • It should have a single "case" statement with one case for each state.  
    • The code in each case should compute the next state.
    • Don't forget "begin" and "end" around the code for each case.
    • It should include a default assignment "state_next = state" before the case statement.
  2. The module should contain an "always@(*)" block that computes the modules outputs from its inputs, and the current state.
    • It should have a single "case" statement with one case for each state.  
    • The code in each case should assign values to outputs of the module.
    • Every case should assign to every output or there needs to be default assignments for every output before the case statement.
  3. The module should contain an "always@(posedge clk)" block to hold the current state.
    • This always block should handle reseting the state to default when reset is asserted
    • It should also do state <= next_state
  4. Since the module contains state clocked, it must have a clk and reset input.

Example

For an example of a combinational model, take a look at GCDdatapath.v in the GCD example.

Test Bench Modules

Test bench modules are different from the other types described above because they do not define hardware.  In fact, the are "unsynthesizable" which means the tools cannot generate hardware that corresponds to them.  The purpose of the test bench is to apply stimuli (called "test vectors") to the module they are build to test (called the device under test or DUT).  You should have a test bench for almost every module you design.  You'll notice in the GCD example that are tests for everything except the GCDdatapath and GCDcontrol.  There are two types of test benches you'll need to write:  those for module with clocks and those without.

For modules with clocks, here are the guidelines:
  1. The test bench for module Foo should be called Foo_test.
  2. Test benches have no inputs or outputs, and they typically don't have any parameters.
  3. The test bench should instantiate exactly one module, named dut, of the type of module you are testing.
  4. You should declare one reg for every input to the module.
  5. You should declare one wire for every output of the module.
  6. Attach the inputs and outputs to the DUT when you instantiate it.
  7. You test bench should contain two "initial" blocks.  Initial blocks contain code that runs sequentially when simulation starts.  The key construct in an initial block is  "#x" which inserts a delay of x time steps at that point in the program.  The size of a time step is set by the `timescale directive.  For instance "`timescale 1ns / 1ps" specifies that each time step is 1ns.
    1. The first initial block defines the clock.  It uses a loop to make clk signal turn on and off forever.
    2. The second initial block applies the test vectors by assigning values to the inputs with appropriate delays in between.
For modules without clocks, the guidelines are mostly the same, except that you don't need the initial block that implements the clock.

Example

For an example of a test module see any of the *_test.v files in the GCD example.

Register Files

Register file modules implement arrays of registers that you'll need for implementing your processor.  They are similar to register modules, but they require some additional logic to make them work as we need them to.  The register files we will use in this class provide asynchronous reads (i.e., reads happen immediately rather than waiting fro the clock) and synchronous writes (i.e., writes only occur at positive clock edges).  The rules for register files are:
  1. They are clocked, so they have clk, reset, and enable.  They may have multiple enables if there are multiple ports.
  2. Outputs should be declared as regs.
  3. You should declare the registers themselves using a verilog array (i.e., reg [W-1:0] reg_file [3:0] defines a 4 element array with W bits each).
  4. The module should contain one always@(*) block to implement the logic for reads.
  5. The module should contain one always@(posedge clk) block to implement the write and reset.
  6. That's all it should contain.

Example

Check out RegFile.v and RegFile_test.v in the GCD example for sample reg file implementation.  The RegFile is not actually used in GCD.

"Forbidden" Language Features

For this class, you shouldn't use any of the following in non-test bench modules (and you probably won't need them in test benches either):
  1. real, time, float, integer, or realtime variables
  2. The builtin and/or/etc. modules.  Or the builtin transistor modules.
  3. wand nets
  4. tri nets
  5. trireg nets
  6. events
Ċ
Steven Swanson,
Jan 11, 2012, 11:10 PM
ċ
GCD.zip
(26k)
Steven Swanson,
Jan 13, 2012, 1:29 AM
Comments