Skip to content

Introduction to Verilog

boldport edited this page Apr 18, 2013 · 41 revisions

Introduction to Verilog

flip flop
[source: http://en.wikipedia.org/wiki/File:R-S_mk2.gif]

The flow

Development flow

Verilog is an HDL

Hardware

Description

Language

We use Verilog to describe hardware

(Other languages exist, like VHDL; no serious designer uses schematic entry)

Building blocks

Wires

Wires connect logic elements, have no memory, and their value is determined by what's driving them.

Edge triggered flip-flop / register

flip flop

Elementary single bit memory unit

(Latches are considered harmful)

Lookup table (LUT)

Elementary logic unit

RAM/ROM

"Large" memory blocks

What if I told you...

What if I told you... that there is no main()
[source: http://generatormeme.com/meme/atdmab#.UWHJ1cqbXAU]

That there is no main()?!

Everything runs concurrently

Think left to right, not top to bottom

The very basics

Declarations

`define ROUNDS 4 // global constants
parameter param1=<value>; // local parameters 
reg  [nn:mm] foo, bar;
wire [nn:mm] oof, rab;

Modules

Creating a module:

module <module_name> (
  input  [nn:mm] <port_name_1>,
  output [nn,mm] <port_name_2>
  ...
);

  ...

endmodule

or

module (<port_name_1>, <port_name_2> ...);

  input  [nn:mm] <port_name_1>;
  output [nn,mm] <port_name_2>;

  ...

endmodule

Instantiating modules

<module_name> <unique_instance_name> (.<port_name_1>(<wire_name_1>),
                                      .<port_name_2>(<wire_name_2>)); 

Blocking assignment:

b = a;
c = b;
r = `ROUNDS;

Non-blocking assignment:

b <= a;
c <= b;

Always use non-blocking assignments! (unless it's in a testbench)

Values

Think in bits!

In an FPGA every memory bit is either at a state of 0 or 1

Values can be expressed in several ways:

a = 10;
b = 4'b1010;
c = 4'd10;
d = 4'hA;
e = {2'b10, 2'b10};
f = {1'b1, 1'b0, 1'b1, 1'b0};

all represent the same bit sequence.

In simulation you'll get a value of X ('undetermined') if no initial value has been set. Again, in the FPGA it will be either a 0 or 1.

Be sync'd

FPGA code is almost always synchronous, which means that events only happen on clock edges.

Always think about the clock; nothing happens without it

Since everything runs all the time, we use 'states' to determine when to evaluate an input signal and when to change an output. All but the very basic HDL code has 'finite state machines' that control the behaviour of the design.

state machine
[source: http://en.wikipedia.org/wiki/File:Turnstile_state_machine_colored.svg]

module turnstile (
  input CLOCK,
  input PUSH,
  input COIN,
  output UNLOCKED
);

reg state

assign UNLOCKED = state;

parameter LOCKED_STATE=1'b0, UNLOCKED_STATE = 1'b1;

always @(posedge CLOCK) begin
  if (reset) state <= next_state;
  else state <= LOCKED;
end

always @(posedge CLOCK) begin
  if (reset) next_state <= LOCKED_STATE;
  else
    case (state)

      LOCKED_STATE:
      begin 
        if (coin == 1'b1)
          next_state <= UNLOCKED;
      end
    
      UNLOCKED_STATE: 
      begin
        if (push == 1'b1)
           next_state <= LOCKED;
      end

      default:  
      begin
        // ALWAYS have a default for a case statement,
        // even if all possible cases are covered
        next_state <= LOCKED;
      end
  endcase
end

* this snippet is a good start, but more is needed for a robust design

Finite state machines can have many, quite complicated, states, so it's good practice to draw a state diagram on paper before starting to code! A concise intro to FSMs in Verilog is here.

When things don't work

Ask yourself

  • Is it working in simulation?
  • Is the clock working and reaching the logic?
  • Is my logic still there?

Don't freak out if you get a gazillion warnings; it's perfectly normal in this world of FPGA tools!

Other than searching for the error message, http://electronics.stackexchange.com or http://stackoverflow.com are good places to find and ask questions.

Exercises

Fully hand-held examples

Example 1 -- hello world!

Create a lower frequency clock from the main 50 MHz clock and output a pattern on the LEDs

Example 2 -- interactive

Create a single pulse of a particular clock period from an incoming pushbutton signal

Edge detect circuit:

edge detect circuit

Semi hand-held example -- logic

Do one or both of the following

Example 3 -- Fibonacci

Output a Fibonacci number update on the LEDs (in binary) whenever KEY1 is pressed. Reset the pattern when KEY0 is pressed. When the Fibonacci number exceeds what can be displayed on the LEDs, display a unique pattern (such as blinking all LEDs multiple times) on the LEDs, then reset.

Example state diagram (can be done differently and more efficiently):

Fibonacci state diagram

Example 4 -- padlock

Using the switches, LEDs and pushbuttons, implement a 4-bit 4-gidit lock. Each combination digit is entered using the switches and a press of KEY1. A pattern should let the user know whether the combination succeeded or failed. (Watch out for insecure implementations!) Extra credit for locking the interface after three wrong attempts. Super extra credit for allowing the user to re-set the initial combination after a successful entry.

Hints:

  • Start by connecting each switch to an LED and see if it turns on/off when the switch is moved positions
  • Create a state diagram on paper before starting to coding
  • An example design can be found in the repo; use it if you're stuck, or as a starting point

On your own!

Create a 4-bit arithmetic logic unit (ALU) using the LEDs, pushbutton and switches. The ALU should support addition, subtraction, multiplication, and division of 4-bit numbers. Use the switches and pushbuttons as for digit and arithmetic operation choice. Use the LEDs for displaying status and results.

Advanced

Choose a DE0-nano peripheral of your choice and write a driver for it. UART may be simplest (implement transmit first), though implementing basic I2C and SPI functionality is also doable. Be creative!

Clone this wiki locally