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

Shared Bus vs Crossbar

Verilog Bus Protocols

Two masters and two slaves: a shared bus allows one transfer per cycle, a crossbar one per slave.

Open in IDE
design.v
// Two masters, two slaves. Each master has a number of single-cycle transfers to do,
// all to one target slave (tgt). A shared bus allows one transfer per cycle in total;
// a crossbar allows one transfer per cycle per slave.

module master_model #(
  parameter COUNT = 4
) (
  input            clk,
  input            rst,
  input            gnt,
  output           req,
  output reg [3:0] left
);
  assign req = (left != 0);

  always @(posedge clk) begin
    if (rst)
      left <= COUNT;
    else if (gnt)
      left <= left - 4'd1;
  end
endmodule

module bus_fabric #(
  parameter CROSSBAR = 0
) (
  input            clk,
  input            rst,
  input      [1:0] req,
  input            tgt0,           // slave targeted by master 0
  input            tgt1,           // slave targeted by master 1
  output reg [1:0] gnt
);
  reg last;                        // round robin: master granted last on a conflict

  wire conflict = CROSSBAR ? (req == 2'b11 && tgt0 == tgt1)   // same slave
                           : (req == 2'b11);                   // one shared bus

  always @(*) begin
    if (conflict)
      gnt = last ? 2'b01 : 2'b10;
    else
      gnt = req;
  end

  always @(posedge clk) begin
    if (rst)
      last <= 1'b1;
    else if (conflict)
      last <= ~last;
  end
endmodule
testbench.v
// Master 0 talks to slave 0, master 1 to slave 1, four transfers each.
module tb;
  reg        clk = 0;
  reg        rst = 1;
  wire [1:0] req_s, gnt_s, req_x, gnt_x;
  wire [3:0] left0_s, left1_s, left0_x, left1_x;
  integer    cyc = 0, t_s = 0, t_x = 0;

  // shared bus
  master_model m0_s (
    .clk  (clk),
    .rst  (rst),
    .gnt  (gnt_s[0]),
    .req  (req_s[0]),
    .left (left0_s)
  );

  master_model m1_s (
    .clk  (clk),
    .rst  (rst),
    .gnt  (gnt_s[1]),
    .req  (req_s[1]),
    .left (left1_s)
  );

  bus_fabric #(.CROSSBAR(0)) u_shared (
    .clk  (clk),
    .rst  (rst),
    .req  (req_s),
    .tgt0 (1'b0),
    .tgt1 (1'b1),
    .gnt  (gnt_s)
  );

  // crossbar
  master_model m0_x (
    .clk  (clk),
    .rst  (rst),
    .gnt  (gnt_x[0]),
    .req  (req_x[0]),
    .left (left0_x)
  );

  master_model m1_x (
    .clk  (clk),
    .rst  (rst),
    .gnt  (gnt_x[1]),
    .req  (req_x[1]),
    .left (left1_x)
  );

  bus_fabric #(.CROSSBAR(1)) u_xbar (
    .clk  (clk),
    .rst  (rst),
    .req  (req_x),
    .tgt0 (1'b0),
    .tgt1 (1'b1),
    .gnt  (gnt_x)
  );

  always #5 clk = ~clk;

  always @(posedge clk) begin
    if (!rst) begin
      cyc = cyc + 1;
      if (req_s == 2'b00 && t_s == 0)
        t_s = cyc - 1;
      if (req_x == 2'b00 && t_x == 0)
        t_x = cyc - 1;
    end
  end

  initial begin
    $dumpfile("dump.vcd");
    $dumpvars(0, tb);
    #12 rst = 0;
    #150;
    $display("shared bus: 8 transfers took %0d cycles", t_s);
    $display("crossbar:   8 transfers took %0d cycles", t_x);
    $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.