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

Pipelining and Outstanding Transactions

Verilog Bus Protocols

Eight reads from a memory with a 3-cycle latency, with 1, 2 and 4 reads allowed in flight.

Open in IDE
design.v
// A memory with a read latency of LAT cycles that accepts a new request in every cycle
// (a pipelined slave), and a master that may have up to MAX_OUT requests outstanding.

module lat_mem #(
  parameter LAT = 3
) (
  input            clk,
  input            rst,
  input            req_valid,      // a read request is presented this cycle
  input      [7:0] req_addr,
  output           rsp_valid,      // read data returns LAT cycles later, in order
  output     [7:0] rsp_data
);
  reg [LAT-1:0] v;                 // one stage per cycle of latency
  reg [7:0]     a [0:LAT-1];
  integer       i;

  always @(posedge clk) begin
    if (rst) begin
      v <= 0;
    end
    else begin
      v[0] <= req_valid;
      a[0] <= req_addr;
      for (i = 1; i < LAT; i = i + 1) begin
        v[i] <= v[i-1];
        a[i] <= a[i-1];
      end
    end
  end

  assign rsp_valid = v[LAT-1];
  assign rsp_data  = a[LAT-1] ^ 8'hA0;   // stand-in for memory contents
endmodule

module reader #(
  parameter MAX_OUT = 1,           // how many reads may be in flight at once
  parameter N       = 8            // how many reads to do
) (
  input            clk,
  input            rst,
  input            rsp_valid,
  output           req_valid,
  output reg [7:0] req_addr,
  output reg [3:0] issued,
  output reg [3:0] done
);
  wire [3:0] outstanding = issued - done;

  assign req_valid = (issued < N) && (outstanding < MAX_OUT);

  always @(posedge clk) begin
    if (rst) begin
      req_addr <= 8'h00;
      issued   <= 4'd0;
      done     <= 4'd0;
    end
    else begin
      if (req_valid) begin
        req_addr <= req_addr + 8'h01;
        issued   <= issued + 4'd1;
      end
      if (rsp_valid)
        done <= done + 4'd1;
    end
  end
endmodule
testbench.v
// Eight reads from a memory with a latency of 3 cycles, with 1, 2 and 4 reads allowed in flight
module tb;
  reg        clk = 0;
  reg        rst = 1;
  wire       rq1, rq2, rq4, rs1, rs2, rs4;
  wire [7:0] ad1, ad2, ad4, rd1, rd2, rd4;
  wire [3:0] is1, is2, is4, dn1, dn2, dn4;
  integer    cyc = 0, t1 = 0, t2 = 0, t4 = 0;

  reader #(.MAX_OUT(1)) m1 (
    .clk       (clk),
    .rst       (rst),
    .rsp_valid (rs1),
    .req_valid (rq1),
    .req_addr  (ad1),
    .issued    (is1),
    .done      (dn1)
  );

  lat_mem #(.LAT(3)) s1 (
    .clk       (clk),
    .rst       (rst),
    .req_valid (rq1),
    .req_addr  (ad1),
    .rsp_valid (rs1),
    .rsp_data  (rd1)
  );

  reader #(.MAX_OUT(2)) m2 (
    .clk       (clk),
    .rst       (rst),
    .rsp_valid (rs2),
    .req_valid (rq2),
    .req_addr  (ad2),
    .issued    (is2),
    .done      (dn2)
  );

  lat_mem #(.LAT(3)) s2 (
    .clk       (clk),
    .rst       (rst),
    .req_valid (rq2),
    .req_addr  (ad2),
    .rsp_valid (rs2),
    .rsp_data  (rd2)
  );

  reader #(.MAX_OUT(4)) m4 (
    .clk       (clk),
    .rst       (rst),
    .rsp_valid (rs4),
    .req_valid (rq4),
    .req_addr  (ad4),
    .issued    (is4),
    .done      (dn4)
  );

  lat_mem #(.LAT(3)) s4 (
    .clk       (clk),
    .rst       (rst),
    .req_valid (rq4),
    .req_addr  (ad4),
    .rsp_valid (rs4),
    .rsp_data  (rd4)
  );

  always #5 clk = ~clk;

  always @(posedge clk) begin
    if (!rst) begin
      cyc = cyc + 1;
      if (dn1 == 7 && rs1)
        t1 = cyc;
      if (dn2 == 7 && rs2)
        t2 = cyc;
      if (dn4 == 7 && rs4)
        t4 = cyc;
    end
  end

  initial begin
    $dumpfile("dump.vcd");
    $dumpvars(0, tb);
    #12 rst = 0;
    #500;
    $display("1 read in flight:  8 reads took %0d cycles", t1);
    $display("2 reads in flight: 8 reads took %0d cycles", t2);
    $display("4 reads in flight: 8 reads took %0d cycles", t4);
    $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.