CPEN 230: Introduction to Digital Logic

A Verilog example showing how to code FSMs

RTL code implementing an edge detector

edgedetector.v
// Edge Detector - Claudio Talarico
module edgedetector (Clk, Rst, Din, Pulse);
input Clk, Rst, Din;
output Pulse;
reg pulse_d, Pulse;

parameter zero=0, pedge=1, nedge=2, one=3;
reg [1:0] state, nextstate;

// Combinational logic
always @ (state or Din)
begin

  case (state)
    zero :
      begin
        if (Din == 0)
          begin
            nextstate = zero;
            pulse_d = 0;
          end
        else
          begin
            nextstate = pedge;
            pulse_d = 1;
          end
      end
    one :
      begin
        if (Din)
          begin
            nextstate = one;
            pulse_d = 0;
          end
        else
          begin
            nextstate = nedge;
            pulse_d = 1;
          end
      end
    pedge :
      begin
        if (Din)
          begin
            nextstate = one;
            pulse_d = 0;
          end
        else
          begin
            nextstate = nedge;
            pulse_d = 1;
          end
      end
    nedge :
      begin
        if (Din)
          begin
            nextstate = pedge;
            pulse_d = 1;
          end
        else
          begin
            nextstate = zero;
            pulse_d = 0;
          end
      end
    default :
      begin
        nextstate = zero;
        pulse_d = 0;
      end
  endcase
end

//sequential logic
always @ (posedge Rst or posedge Clk) //active high async. reset
begin
  if (Rst)
    begin
      state <= zero;
      Pulse <= 0;
    end
  else
    begin
      state <= nextstate;
      Pulse <= pulse_d;
    end
end

endmodule

Test vectors (stimuli & expected outputs) read in by testbench:

test.vec
11
10
10
10
10
01
11
10
10
10

Testbench:

edgedetector_tb.v
// Edge Detector TestBench - Claudio Talarico

`timescale 1ns/1ns

module edgedetector_tb;
parameter ClkPeriod=20, NVect=10, ClkOffset=2, ProbeDel = 2,  NField = 2;
integer j, fc; //fc=failcount
integer Log_File;
reg [NField : 1] Vmem [1 : NVect];
reg Pulse_exp;
reg Clk_tb;

// inputs to RTL hardware model (Device Under Test)
reg Clk, Rst, Din;

//outputs from DUT
wire Pulse;

//instantiate the DUT
edgedetector edge_detector_inst(Clk, Rst, Din, Pulse);

initial
begin
  $dumpfile("edgedetector.vcd");
  $dumpvars(0);
end

// initialiaze inputs
initial
  begin
    Rst=0;
    Din=0;
    Clk=0;
  end

// initialize testbench
initial
  begin
    Clk_tb = 0;
    fc = 0;
  end

//setup a free running virtual clock
always
  begin
    #(ClkPeriod/2) Clk_tb = ~Clk_tb;
  end

//setup a free running system clock
initial
  begin
    #ClkOffset; //initial offset between the clocks
    forever
      #(ClkPeriod/2) Clk = ~Clk;
  end

// Perform System Reset
initial
  begin
    #2;
    #1 Rst = 1;
    #4 Rst = 0;
  end

// main test
initial
  begin
    Log_File = $fopen("logfile");
    $readmemb("test.vec", Vmem);

    for(j=1;j<=NVect;j=j+1)
    begin
      @ (posedge Clk_tb);
      begin
        {Din,Pulse_exp} = Vmem[j];
        #(ClkOffset + ProbeDel); // let value settle
        if (Pulse !== Pulse_exp)
        begin
          $fdisplay(Log_File, "Time=%t ::", $time," ***** Mismatch on Vector %d *****", j);
          fc = fc + 1;
        end else
        begin
          $fdisplay(Log_File, "Time=%t ::", $time, "vector %d successfull", j);
        end
      end
    end
    if(!fc) $fdisplay(Log_File, "Simulation finished successfully");
    else $fdisplay(Log_File, "***** Simulation finished unsuccessfully *****");
    $fclose(Log_File);
    $finish;
  end

initial
  begin
    $monitor("Time=%t :: ", $time, "Clk_tb=%b, Clk=%b, Din=%b, Pulse=%b", Clk_tb, Clk, Din, Pulse);
  end

endmodule