Ready-to-run snippets

Code Examples

Ready-to-run Verilog, SystemVerilog, and UVM examples. Click any to open it live in the IDE.

← All examples

Handshakes: four-phase, two-phase, valid/ready

Verilog Bus Protocols

Three handshakes on the same clock, side by side, with a stalling valid/ready receiver.

Open in IDE
design.v
// Three handshakes between a sender and a receiver that run on the same clock.

// 1. Four-phase req/ack: req rises, ack rises, req falls, ack falls.
module hs4_sender (
  input            clk,
  input            rst,
  input            go,
  input      [7:0] din,
  input            ack,
  output reg       req,
  output reg [7:0] data
);
  always @(posedge clk) begin
    if (rst) begin
      req <= 1'b0;
    end
    else if (go && !req && !ack) begin     // phase 1: request, with the data
      req  <= 1'b1;
      data <= din;
    end
    else if (req && ack) begin             // phase 3: drop the request
      req <= 1'b0;
    end
  end
endmodule

module hs4_receiver (
  input            clk,
  input            rst,
  input            req,
  input      [7:0] data,
  output reg       ack,
  output reg [7:0] got
);
  always @(posedge clk) begin
    if (rst) begin
      ack <= 1'b0;
    end
    else if (req && !ack) begin            // phase 2: take the data, acknowledge
      ack <= 1'b1;
      got <= data;
    end
    else if (!req && ack) begin            // phase 4: drop the acknowledge
      ack <= 1'b0;
    end
  end
endmodule

// 2. Two-phase (toggle): every change of req is a new word, every change of ack acknowledges it.
module hs2_sender (
  input            clk,
  input            rst,
  input            go,
  input      [7:0] din,
  input            ack,
  output reg       req,
  output reg [7:0] data
);
  always @(posedge clk) begin
    if (rst) begin
      req <= 1'b0;
    end
    else if (go && req == ack) begin       // idle when req equals ack
      req  <= ~req;
      data <= din;
    end
  end
endmodule

module hs2_receiver (
  input            clk,
  input            rst,
  input            req,
  input      [7:0] data,
  output reg       ack,
  output reg [7:0] got
);
  always @(posedge clk) begin
    if (rst) begin
      ack <= 1'b0;
    end
    else if (req != ack) begin             // a new word is waiting
      ack <= req;
      got <= data;
    end
  end
endmodule

// 3. Valid/ready: a word moves in every cycle in which both are high.
module vr_sender (
  input            clk,
  input            rst,
  input            go,
  input            ready,
  output reg       valid,
  output reg [7:0] data
);
  always @(posedge clk) begin
    if (rst) begin
      valid <= 1'b0;
      data  <= 8'h01;
    end
    else begin
      if (valid && ready)                  // the word was taken: offer the next one
        data <= data + 8'h01;
      if (!valid || ready)                 // never withdraw a word that is waiting
        valid <= go;
    end
  end
endmodule

module vr_receiver (
  input            clk,
  input            rst,
  input            valid,
  input      [7:0] data,
  input            stall,
  output           ready,
  output reg [7:0] got,
  output reg [3:0] count
);
  assign ready = !stall;

  always @(posedge clk) begin
    if (rst) begin
      count <= 4'd0;
    end
    else if (valid && ready) begin
      got   <= data;
      count <= count + 4'd1;
    end
  end
endmodule
testbench.v
module tb;
  reg        clk   = 0;
  reg        rst   = 1;
  reg        go4   = 0;
  reg        go2   = 0;
  reg        govr  = 0;
  reg        stall = 0;
  reg  [7:0] din   = 8'h00;

  wire       req4, ack4, req2, ack2, valid, ready;
  wire [7:0] data4, got4, data2, got2, vdata, vgot;
  wire [3:0] vcount;

  hs4_sender u_s4 (
    .clk  (clk),
    .rst  (rst),
    .go   (go4),
    .din  (din),
    .ack  (ack4),
    .req  (req4),
    .data (data4)
  );

  hs4_receiver u_r4 (
    .clk  (clk),
    .rst  (rst),
    .req  (req4),
    .data (data4),
    .ack  (ack4),
    .got  (got4)
  );

  hs2_sender u_s2 (
    .clk  (clk),
    .rst  (rst),
    .go   (go2),
    .din  (din),
    .ack  (ack2),
    .req  (req2),
    .data (data2)
  );

  hs2_receiver u_r2 (
    .clk  (clk),
    .rst  (rst),
    .req  (req2),
    .data (data2),
    .ack  (ack2),
    .got  (got2)
  );

  vr_sender u_sv (
    .clk   (clk),
    .rst   (rst),
    .go    (govr),
    .ready (ready),
    .valid (valid),
    .data  (vdata)
  );

  vr_receiver u_rv (
    .clk   (clk),
    .rst   (rst),
    .valid (valid),
    .data  (vdata),
    .stall (stall),
    .ready (ready),
    .got   (vgot),
    .count (vcount)
  );

  always #5 clk = ~clk;

  always @(posedge clk) begin
    if (req4 && !ack4)
      $display("%0t  four-phase: word %h offered", $time, data4);
    if (valid && ready)
      $display("%0t  valid/ready: word %h transferred", $time, vdata);
  end

  initial begin
    $dumpfile("dump.vcd");
    $dumpvars(0, tb);
    #12 rst = 0;

    // two words with each handshake, back to back
    @(negedge clk);
    din  = 8'h11;
    go4  = 1;
    go2  = 1;
    govr = 1;
    repeat (4) @(negedge clk);
    din   = 8'h22;
    stall = 1;                       // the valid/ready receiver stalls for two cycles
    repeat (2) @(negedge clk);
    stall = 0;
    repeat (4) @(negedge clk);
    go4  = 0;
    go2  = 0;
    govr = 0;
    #40 $finish;
  end
endmodule
Admin mode — edit and delete controls are visible on each row. Use the IDE to add new snippets via File → Save as Snippet.