Fatal error: SB_IO PACKAGE_PIN not connected to toplevel port


#1

Hello, I am in the process of trying to create a RAM from an example in a textbook, but using button inputs and LED outputs on a breadboard to input and read out the memory. I’m using apio v 0.4.0b5.

I have been getting this error “fatal error: SB_IO PACKAGE_PIN not connected to toplevel port” which always points to the very last line in the hardware.blif file, right at the end. What does it mean?

My code below:

module ram (Enable, ReadWrite, Address, DataIn, DataOut);
input Enable, ReadWrite;
input [7:0] DataIn;
input [1:0] Address;
output [7:0] DataOut;
reg[7:0] DataOut;
reg[1:0] Mem[0:7];

// enable internal pullups on all button inputs:
  SB_IO #(
    .PIN_TYPE(6'b 0000_01),
    .PULLUP(1'b 1)
  ) button_input[7:0](
    .PACKAGE_PIN({PIN_8, PIN_7, PIN_6, PIN_5, PIN_4, PIN_3, PIN_2, PIN_1}),
    .D_IN_0(DataIn[7:0])
  );

  // enable pullups on switch inputs:
  SB_IO #(
    .PIN_TYPE(6'b 0000_01),
    .PULLUP(1'b 1)
  ) switch_input[1:0](
    .PACKAGE_PIN({PIN_15, PIN_14}),
    .D_IN_0(Address[1:0])
  );

always @ (Enable or ReadWrite)
  if (Enable)
    if (ReadWrite) DataOut = Mem[Address];   // Read
    else Mem[Address] = DataIn;              // Write
  else DataOut = 4'bz;
endmodule

I also noticed that when I copied the code example straight from the textbook, apio wouldn’t let me run it because it complained that lots of pins weren’t connected. In fact nothing was, because the example is just an internal module… but in general will the toolchain complain if the module’s ports aren’t connected to anything larger? I would have thought that would just be a warning “Warning: you have no way to stimulate this module or receive the outputs” rather than a hard error.

(Edit: Sure wish this forum allowed easy code formatting. Any way to do it besides putting in 4 spaces on every single dang line?)


#2

You need all those PIN_1 … PIN_8 and PIN_14 … PIN_!5 declared as inputs to a top level module.

Without that PIN_xx are all undeclared and will be implicitly declared as wires and not package pins (as defined by Verilog unless you set `default_nettype none). Hence the error.

But that ram module is not meant to be a top level module. You need to create an instance of it in your top level module and set its inputs and outputs.

So you need something like:

// look in pins.pcf for all the pin names on the TinyFPGA BX board
module top (
    input CLK,    // 16MHz clock
    input PIN_1,
    input PIN_2,
    input PIN_3,
    input PIN_4,
    input PIN_5,
    input PIN_6,
    input PIN_7,
    input PIN_8,
    input PIN_14,
    input PIN_15,
    output USBPU  // USB pull-up resistor
);
      // drive USB pull-up resistor to '0' to disable USB
      assign USBPU = 0;

      // enable internal pullups on all button inputs:
      SB_IO #(
        .PIN_TYPE(6'b 0000_01),
        .PULLUP(1'b 1)
      ) button_input[7:0](
        .PACKAGE_PIN({PIN_8, PIN_7, PIN_6, PIN_5, PIN_4, PIN_3, PIN_2, PIN_1}),
        .D_IN_0(DataIn[7:0])
      );

      // enable pullups on switch inputs:
      SB_IO #(
        .PIN_TYPE(6'b 0000_01),
        .PULLUP(1'b 1)
      ) switch_input[1:0](
        .PACKAGE_PIN({PIN_15, PIN_14}),
        .D_IN_0(Address[1:0])
      );

      reg Enable, ReadWrite;
      reg [7:0] DataIn;
      reg [1:0] Address;
      reg [7:0] DataOut;

      ram ram_inst(
        .Enable(Enable),
        .ReadWrite(ReadWrite),
        .DataIn(DataIn),
        .Address(Address),
        .DataOut(DataOut)
      );

endmodule

module ram (Enable, ReadWrite, Address, DataIn, DataOut);
input Enable, ReadWrite;
input [7:0] DataIn;
input [1:0] Address;
output [7:0] DataOut;
reg[7:0] DataOut;
reg[1:0] Mem[0:7];

always @ (Enable or ReadWrite)
  if (Enable)
    if (ReadWrite) DataOut = Mem[Address];   // Read
    else Mem[Address] = DataIn;              // Write
  else DataOut = 4'bz;
endmodule

And that builds and uploads for me.

But it still has multiple problems.

  1. You set DataOut = 4’bz; when DataOut is 8 bits wide.
  2. You have no way of setting Enable or ReadWrite.
  3. Your example module seems to be asynchronous tri-stated RAM. I am not sure the tri-stating will work with icestorm. Synchronous RAM with a clock and non-blocking reads and writes are normally what is required.

You can use the pre-formatted text button for code.


#3

Thank you so much for your help!