nalzok
nalzok

Reputation: 16117

Understanding the SB_IO primitive in Lattice ICE40

I am playing with cliffordwolf/picorv32 and am having some problem understanding the following snippet in picosoc (link to source):

SB_IO #(
    .PIN_TYPE(6'b 1010_01),
    .PULLUP(1'b 0)
) flash_io_buf [3:0] (
    .PACKAGE_PIN({flash_io3, flash_io2, flash_io1, flash_io0}),
    .OUTPUT_ENABLE({flash_io3_oe, flash_io2_oe, flash_io1_oe, flash_io0_oe}),
    .D_OUT_0({flash_io3_do, flash_io2_do, flash_io1_do, flash_io0_do}),
    .D_IN_0({flash_io3_di, flash_io2_di, flash_io1_di, flash_io0_di})
);

I have found a graphic description for the SB_IO primitive in Lattice iCE40 technology library documentation, but I still cannot understand its purpose because it's too complex for me to interpret. There is another question about the primitive, after reading which I would assume it creates some kind of bidirectional connection, but I failed to understand how that is related to making the output pin "tristated".

I would appreciate a high-level description of the effect of the SB_IO cell under this particular configuration. Which pin is connected to which pin? Which are inputs and which are outputs? What is the purpose of instantiating this cell?

Upvotes: 2

Views: 3925

Answers (3)

RGD2
RGD2

Reputation: 469

This is my interpretation of the diagram in the documenatation (set means 1'b1 / high / True):

SB_IO.PIN_TYPE[5:0] config parameter by each bit index (left to right):

  • 5: Set if OUTPUT_ENABLE input signal used (use inout for PACKAGE_PIN)

  • 4: depends on 5:

    • if OE used, whether OUTPUT_ENABLE is registered to posedge OUTPUT_CLK, else the enable is direct (unregistered).
    • if no OE: PACKAGE_PIN is output else input
  • 3: Whether D_OUT_0 is a direct(unregistered) output else it's registered DDR along with D_OUT_1

  • 2: depends on 3:

    • if 3: inverts the direct output when set
    • if ~3: instead swaps D_OUT_0/1 DDR clock phase on output latch:
      • if set: D_OUT_O register loads on posedge .OUTPUT_CLK, but is output on negedge (during clock low), vice versa for D_OUT_1. If clear, then D_OUT_O is output during clock high, and D_OUT_1 is output during clock low.
  • 1: D_IN_0 input is latched with LATCH_INPUT_VALUE signal

  • 0: D_IN_0 input is direct else registered with .INPUT_CLK, with no effect if input latch enabled.

  • note D_IN_1 input is always registered to negedge INPUT_CLK, yet may be ignored for a posedge registered SDR input mode.

  • D_OUT_1 has no effect unless [3]==0, however, there is no SDR registered output mode!

    • you'll have to run the output as direct, and have an external register.
    • for this, typically you just let yosys infer the whole SB_IO for that pin as a direct output, maybe defined as type output reg.
  • also note D_OUT_1 is unable to be set on posedge clock, meaning if you need to set it from posedge domain, then all output may need to be one register later.

    • although, setting [3] may help with this.
  • 6'b1010_01 is thus a direct (unregistered) inout pin.

  • 6'b0010_01 is a plain input pin

  • 6'b0110_01 is a plain output pin

  • you rarely see those last two, because yosys will automatically infer them with sensible default settings, and can even infer the first, usually, so long as the assign packagepin = enablesig? outputsig : 1'bz; line is in the top level module.

    • You may see them if .PULLUP(1'b1) is desired, this enables the weak-high pullup resistor on that pin.
  • finally, PIN_TYPE maps into configuration bits, you can't wire dynamic signals to them, you just choose them as constant to be set at compile-time.

This sort of 'direct use of a primitive' is pretty common for parts of FPGA's which can't easily be 'inferred' from the verilog design behaviour, and which usually vary between FPGA architectures (fpga 'families' if you like).

Yosys treats these like 'black boxes', but you can load a verilog definition so that you can simulate how they behave.

Trivia: the 'SB_' on the front almost certainly meant 'Silicon Blue', who originally designed the ice40 architecture, before being bought up and incorporated into Lattice. You can still find some ice40 chips with the SiliconBlue logo on them.

Upvotes: 1

Neil Stockbridge
Neil Stockbridge

Reputation: 604

I found the following comments for the module parameters, which might go some way to explaining how to use SB_IO:

SB_IO #(
  .PIN_TYPE (6'b 1010_01),
  .PULLUP (HIGH)
) ram_d_io [15:0] (                   // Name of the cell.  Must be unique
  .PACKAGE_PIN (ram_d_inout [15:0]),  // Name of the module parameter
  .OUTPUT_ENABLE (~data_bus_we),      // Line that controls whether `ram_d_inout` is high-Z or driven
  .D_OUT_0 (data_bus_w [15:0]),       // Line that determines level when `ram_d_inout` is driven
  .D_IN_0 (data_bus_r [15:0])         // Line that is driven by `ram_d_inout` when high-Z
);

Upvotes: 1

gatecat
gatecat

Reputation: 1186

This instance was used because at the time Yosys didn't support tristates in Verilog well enough, it does now but in general tristate support in FPGA toolchains isn't always trusted.

It could be replaced with the following generic Verilog, repeated 4 times from 0 to 4.

assign flash_io0 = flash_io0_oe ? flash_io0_do : 1'bz;
assign flash_io0_di = flash_io0;

Upvotes: 5

Related Questions