Synthesizeable Verilog Code Examples

This page gives FREE synthesizable verilog code examples, block diagrams and timing diagrams of typical digital circuit building blocks.
Last update August 2000


Topics:

The following topics are currently covered. (Finished topics have links).

  1. Failsafe Synthesis Methodology
  2. The .v file structure
  3. D type flip flops
    1. D type flip flop
      D type flip flop with asynchronous reset
      D type flip flop with synchronous reset
      D type flip flop with gated clock
      D type flip flop with data enabled
      Negative edge triggered D type flip flop
  4. Latches
  5. Multiplexers
    1. Two input multiplexer using if else
      Two input multiplexer using ternary operator (?:)
      Two input multiplexer using case
      Two input multiplexer using default assignment and if statement
      Three input priority encoded multiplexer using if else statement
      Three input priority encoded multiplexer using case statement
      Three input no priority encoded multiplexer using case statement
  6. Comparators
  7. Adders
  8. Subtractors
  9. Multipliers
  10. Dividers
  11. PLLs (if it is possible!)
  12. FIFOs
  13. Memories
  14. Tristate buffer modelling
  15. Counters
  16. Verilog Quick Reference 1
  17. Verilog Quick Reference 2
  18. Finite State Machines
  19. Blocking (=) versus non blocking (<=) signal assignment and their impact on synthesis
  20. Esperan Training

Synthesis Methodology:


The verilog File Structure

A good template for your verilog files is shown below with an example given afterwards.
This is not taken from the Language reference manual.

// timescale directive tells the simulator the base units and precision of the simulation
`timescale 1 ns / 10 ps
module <name> (<input and outputs>);

// parameter declarations
parameter <parameter_name> = <parameter value>;

// Input output declarations
input <in1>;
input <in2>;                // single bit inputs
input [<msb>:<lsb>] <in3>;  // a bus input

// internal signal register type declaration - register types (only assigned within always statements).
reg <register variable 1>;
reg [<msb>:<lsb>] <register variable 2>;

// internal signal. net type declaration - (only assigned outside always statements)
wire <net variable 1>;
 

// hierarchy - instantiating another module
<reference name> <instance name> (
   .pin1    (net1),
   .pin2    (net2),
   .
   .
   .
   .pinn    (netn)
   );

// synchronous procedures
always @ (posedge <clock>)
   begin
   .
   .
   .
   end

// combinatinal procedures
always @ (signal1 or signal2 or signal3)
   begin
   .
   .
   .
   end

assign <net variable> = <combinational logic>;

endmodule
 
 
 

D Type Flip Flops:

Two things to note about inferring flip flops:

D-type flip flop

reg q;

always @ (posedge clk)
  q <= d;




 
D type flip flop with asynchronous reset

reg q;

always @ (posedge clk or posedge reset)
  if (reset)
    q <= 1'b0;
  else
    q <= d;




 
 
D type flip flop with synchronous reset

reg q;

always @ (posedge clk)
  if (reset)
    q <= 1'b0;
  else
    q <= d;




 
 
D type flip flop with gated clock

reg q;
wire gtd_clk = enable && clk;

always @ (posedge gtd_clk)
  q <= d;




 
 
Data enbled D type flip flop

reg q;

always @ (posedge clk)
  if (enable)
    q <= d;




 
 
 
Negative edge triggered D type flip flop

reg q;

always @ (negedge clk)
  q <= d;


Latches
 
Latch

reg q;

always @ (q or enable)
   if (enable)
      q = d;



Multiplexers
 
Two input multiplexer (using if else)

reg y;

always @ (a or b or select)
   if (select)
      y = a;
   else
      y = b;



 
 
 
Two input multiplexer (using ternary operator ?:)

wire t = (select ? a : b);



 


 
 
Two input multiplexer (using case statement)

reg w;

// mux version 3
always @ (a or b or select)
   case (select)
      1'b1 : w = a;
      default : w = b;
   endcase




 
Two input multiplexer (using default assignment and if)

reg p;

// mux version 4
always @ (a or b or select)
   begin
   p = b;
   if (select)
      p = a;
   end




 
Three input priority encoded mux multiplexer (using if else)

reg q;

always @ (a or b or c or select2)
   if (select2 == 2'b00)
      q = a;
   else 
      if (select2 == 2'b01)
         q = b;
      else
         q = c;
 




 
Three input priority encoded mux multiplexer (using case)

reg r;

// Priority encoded mux, version 2
always @ (a or b or c or select2)
   begin
   r = c; 
   case (select2)
      2'b00: r = a;
      2'b01: r = b;
   endcase
   end
 




 
Three input multiplexer with no priority (using case)

reg s;

always @ (a or b or c or select2)
   begin
   case (select2) // synopsys parallel_case
      2'b00: s = a;
      2'b01: s = b;
      default: s = c; 
   endcase
   end




 
Comparator (using assign)

module comparator1 (a,b,c);
 
input  a;
input  b;
output c;
 
assign c = (a == b);
 
endmodule



 

 
 
Comparator (using always)
 

module comparator2 (a,b,c);
 
input  a;
input  b;
output c;
reg    c;
 
always @ (a or b)
    if (a == b)
       c = 1'b1;
    else
       c = 1'b0;
 
endmodule



 

 

Finite State Machines
A full example of a state machine and associated test bench

The state machine
The state machine test bench

The following is a simple four state finite state machine.
The methodology for writing finite state machines is as follows:
1. Draw a state diagram. Label all conditions, label all output values. Label the state encoding.
2. Use parameter to encode the states as in the example.
3. Use two processes or always statements- one sequential and one combinational. See the example.
4. The state machine is normally resettable _ choose synchronous or asynchronous.
5. The combinational process normally has one big case statement in it. Put default values at the beginning.

There are a couple of neat things about the example.
We are using parameters is the test bench and passing them to the state machine using parameter passing
We are using tasks to control the flow of the testbench
We are using hierarchical naming to access the state variable in the state machine from the test bench.
Finally we are using test bench messages which allow us to monitor the current state from the simulation waveform viewer (assuming we change the bus radix of the 'message' to ascii.

// --------------------------------------------
//
// S T A T E   M A C H I N E
//
// --------------------------------------------
module state_machine(sm_in,sm_clock,reset,sm_out);

parameter idle  = 2'b00;
parameter read  = 2'b01;
parameter write = 2'b11;
parameter wait  = 2'b10;

input sm_clock;
input reset;
input sm_in;
output sm_out;

reg [1:0] current_state, next_state;
 

always @ (posedge sm_clock)
   begin
   if (reset == 1'b1)
   current_state <= 2'b00;
   else
   current_state <= next_state;
   end
 

always @ (current_state or sm_in)
   begin
      // default values
      sm_out = 1'b1;
      next_state = current_state;
      case (current_state)
      idle:
         sm_out = 1'b0;
         if (sm_in)
         next_state = 2'b11;
      write:
         sm_out = 1'b0;
         if (sm_in == 1'b0)
         next_state = 2'b10;
      read:
         if (sm_in == 1'b1)
         next_state = 2'b01;
      wait:
         if (sm_in == 1'b1)
         next_state = 2'b00;
      endcase
   end

endmodule
 
 

// --------------------------------------------
//
// T E S T   B E N C H
//
// --------------------------------------------
module testbench;

// parameter declaration section
// ...
parameter idle_state  = 2'b00;
parameter read_state  = 2'b01;
parameter write_state = 2'b11;
parameter wait_state  = 2'b10;

// testbench declaration section
reg [500:1] message;
reg [500:1] state_message;
reg in1;
reg clk;
reg reset;
wire data_mux;

// instantiations
state_machine #(idle_state,
                read_state,
                write_state,
                wait_state)  st_mac (
   .sm_in       (in1),
   .sm_clock    (clk),
   .reset       (reset),
   .sm_out      (data_mux)
   );

// monitor section
always @ (st_mac.current_state)
   case (st_mac.current_state)
     idle_state : state_message = "idle";
     read_state : state_message = "read";
     write_state: state_message = "write";
     wait_state : state_message = "wait";
   endcase

// clock declaration
initial clk = 1'b0;
always #50 clk = ~clk;

// tasks
task reset_cct;
   begin
   @(posedge clk);
   message = " reset";
   @(posedge clk);
   reset = 1'b1;
   @(posedge clk);
   reset = 1'b0;
   @(posedge clk);
   @(posedge clk);
   end
endtask

task change_in1_to;
input  a;
begin
message = "change in1 task";
@ (posedge clk);
in1 = a;
end
endtask

// main task calling section
initial
begin
message = "start";
reset_cct;
change_in1_to(1'b1);
change_in1_to(1'b0);
change_in1_to(1'b1);
change_in1_to(1'b0);
change_in1_to(1'b1);
@ (posedge clk);
@ (posedge clk);
@ (posedge clk);
$stop;
end

endmodule
 
 
 
 
 

Please mail any comments or coding queries to finbarr.oregan@ee.ucd.ie

Last updated: August 23, 2000