Friday, August 13, 2010

SystemVerilog - Interface with modports - master with multiple slaves

Playing around with Quartus 10.0, and so far this is synthesizable. This code uses a generate block to create multiple modports such that I can easily connect many slaves to a single interface programmatically where the interface has one bit per slave in a single bus.

This creates a 6-to-1 multiplexer sourced from 6 latches. Each latch has its own preset, clear, and select, and they all use a shared data and enable input.

Note the use of $size. It could have been done in other ways I'm sure.
Note the use of 'slave_modport_gen' in the instantiation of the slaves. This is how to reference the separate modports that are created in the interface. The need for separate modports is b/c I need to control different bits of q_bus for each modport.
Note the use of .sel(sel_in[i]) in the modport port direction descriptions. This is an alias (aliased to sel inside the module), also required to have the same module be able to control the desired bit of q_bus.


`timescale 1ns/1ns

interface bus # (
 parameter NUM_SLAVES = 1
) (
 input [NUM_SLAVES - 1:0] sel_in,
 input e_in,
 input d_in,
 input [NUM_SLAVES - 1:0] s_in,
 input [NUM_SLAVES - 1:0] r_in,
 output q_out
);

 logic q_bus [NUM_SLAVES - 1:0];

 modport master(
 input sel_in,
 output q_out,

 input q_bus
 );

 genvar i;
 generate
 for(i = 0; i < NUM_SLAVES; i++) begin : slave_modport_gen
  wire e_comb;
  assign e_comb = sel_in[i] && e_in;
  modport slave(
   input .e(e_comb),
   input .d(d_in),
   input .s(s_in[i]),
   input .r(r_in[i]),
   output .q(q_bus[i])
  );
 end
 endgenerate
endinterface

module master(
 bus.master m
);
 integer i;
 always_comb begin
  m.q_out = 0;
  for(i = 0; i < $size(m.sel_in); i++) begin
   if(m.sel_in[i])
    m.q_out = m.q_bus[i];
  end
 end
endmodule

module slave (
 interface s
);
 always_latch begin
  if(s.e)
   s.q <= s.d;
  if(s.s)
   s.q <= 1;
  if(s.r)
   s.q <= 0;
 end
endmodule

module top # (
 parameter NUM_SLAVES = 6
) (
 input [NUM_SLAVES - 1:0] sel_in,
 input e_in,
 input d_in,
 input [NUM_SLAVES - 1:0] s_in,
 input [NUM_SLAVES - 1:0] r_in,
 output q_out
);

 bus # (
  .NUM_SLAVES(NUM_SLAVES)
 ) bus_inst(
  .sel_in(sel_in),
  .e_in(e_in),
  .d_in(d_in),
  .s_in(s_in),
  .r_in(r_in),
  .q_out(q_out)
 );

 master master_inst(bus_inst);

 genvar i;
 generate
 for(i = 0; i < NUM_SLAVES; i++) begin : slave_gen
  slave slave_inst(bus_inst.slave_modport_gen[i].slave);
 end
 endgenerate

endmodule

No comments:

Post a Comment