diff options
| -rw-r--r-- | fpga/usrp3/top/x400/Makefile.x4xx.inc | 1 | ||||
| -rw-r--r-- | fpga/usrp3/top/x400/doc/X4XX_FPGA_left.htm | 18 | ||||
| -rw-r--r-- | fpga/usrp3/top/x400/doc/X4XX_FPGA_right.htm | 553 | ||||
| -rw-r--r-- | fpga/usrp3/top/x400/regmap/dig_ifc_regmap_utils.vh | 88 | ||||
| -rw-r--r-- | fpga/usrp3/top/x400/regmap/radio_dio_regmap_utils.vh | 5 | ||||
| -rw-r--r-- | fpga/usrp3/top/x400/x4xx_core.v | 1 | ||||
| -rw-r--r-- | fpga/usrp3/top/x400/x4xx_core_common.v | 194 | ||||
| -rw-r--r-- | fpga/usrp3/top/x400/x4xx_gpio_atr.v | 4 | ||||
| -rw-r--r-- | fpga/usrp3/top/x400/x4xx_gpio_spi.v | 534 | 
9 files changed, 1338 insertions, 60 deletions
diff --git a/fpga/usrp3/top/x400/Makefile.x4xx.inc b/fpga/usrp3/top/x400/Makefile.x4xx.inc index 2c6de75ec..fa6208088 100644 --- a/fpga/usrp3/top/x400/Makefile.x4xx.inc +++ b/fpga/usrp3/top/x400/Makefile.x4xx.inc @@ -74,6 +74,7 @@ x4xx_global_regs.v \  x4xx_versioning_regs.v \  x4xx_dio.v \  x4xx_gpio_atr.v \ +x4xx_gpio_spi.v \  rf/100m/rf_core_100m.v \  rf/200m/rf_core_200m.v \  rf/200m/rf_down_4to2.v \ diff --git a/fpga/usrp3/top/x400/doc/X4XX_FPGA_left.htm b/fpga/usrp3/top/x400/doc/X4XX_FPGA_left.htm index c302c2f9c..0a101710e 100644 --- a/fpga/usrp3/top/x400/doc/X4XX_FPGA_left.htm +++ b/fpga/usrp3/top/x400/doc/X4XX_FPGA_left.htm @@ -270,6 +270,21 @@        </div>          </div>          <p> +      <span class="pm" id="pm_DIG_IFC_REGMAP" onclick="pm('DIG_IFC_REGMAP');">+</span> +      <span class="regmap" id="a_DIG_IFC_REGMAP" onclick="a('DIG_IFC_REGMAP');">DIG_IFC_REGMAP</span> +    </p>    <div class="sh" id="div_DIG_IFC_REGMAP">       +      <p>         +        <span class="pm" id="pm_DIG_IFC_REGMAP|SPI_OVER_GPIO_REGS" onclick="pm('DIG_IFC_REGMAP|SPI_OVER_GPIO_REGS');">+</span>       +        <span class="group" id="a_DIG_IFC_REGMAP|SPI_OVER_GPIO_REGS" onclick="a('DIG_IFC_REGMAP|SPI_OVER_GPIO_REGS');">SPI_OVER_GPIO_REGS</span> +      </p> +      <div class="sh" id="div_DIG_IFC_REGMAP|SPI_OVER_GPIO_REGS">         +        <p><span class="register" id="a_DIG_IFC_REGMAP|SPI_SLAVE_CONFIG" onclick="a('DIG_IFC_REGMAP|SPI_SLAVE_CONFIG');">SPI_SLAVE_CONFIG</span></p>         +        <p><span class="register" id="a_DIG_IFC_REGMAP|SPI_TRANSACTION_CONFIG" onclick="a('DIG_IFC_REGMAP|SPI_TRANSACTION_CONFIG');">SPI_TRANSACTION_CONFIG</span></p>         +        <p><span class="register" id="a_DIG_IFC_REGMAP|SPI_TRANSACTION_GO" onclick="a('DIG_IFC_REGMAP|SPI_TRANSACTION_GO');">SPI_TRANSACTION_GO</span></p>         +        <p><span class="register" id="a_DIG_IFC_REGMAP|SPI_STATUS" onclick="a('DIG_IFC_REGMAP|SPI_STATUS');">SPI_STATUS</span></p>       +      </div>     +    </div>     +    <p>        <span class="pm" id="pm_DIO_REGMAP" onclick="pm('DIO_REGMAP');">+</span>        <span class="regmap" id="a_DIO_REGMAP" onclick="a('DIO_REGMAP');">DIO_REGMAP</span>      </p>    <div class="sh" id="div_DIO_REGMAP">       @@ -579,7 +594,8 @@        </p>        <div class="sh" id="div_RADIO_DIO_REGMAP|DIO_SOURCES">                  <p><span class="register" id="a_RADIO_DIO_REGMAP|RADIO_GPIO_ATR_REGS" onclick="a('RADIO_DIO_REGMAP|RADIO_GPIO_ATR_REGS');">RADIO_GPIO_ATR_REGS</span></p>         -        <p><span class="register" id="a_RADIO_DIO_REGMAP|DIO_SOURCE_CONTROL" onclick="a('RADIO_DIO_REGMAP|DIO_SOURCE_CONTROL');">DIO_SOURCE_CONTROL</span></p>       +        <p><span class="register" id="a_RADIO_DIO_REGMAP|DIO_SOURCE_CONTROL" onclick="a('RADIO_DIO_REGMAP|DIO_SOURCE_CONTROL');">DIO_SOURCE_CONTROL</span></p>         +        <p><span class="register" id="a_RADIO_DIO_REGMAP|DIGITAL_IFC_REGS" onclick="a('RADIO_DIO_REGMAP|DIGITAL_IFC_REGS');">DIGITAL_IFC_REGS</span></p>              </div>          </div>          <p> diff --git a/fpga/usrp3/top/x400/doc/X4XX_FPGA_right.htm b/fpga/usrp3/top/x400/doc/X4XX_FPGA_right.htm index 4e3b3c3a8..2827c1a93 100644 --- a/fpga/usrp3/top/x400/doc/X4XX_FPGA_right.htm +++ b/fpga/usrp3/top/x400/doc/X4XX_FPGA_right.htm @@ -3232,6 +3232,492 @@ Total Offset =</td></tr>  </div>              <div class="regmap"> +              <a name="DIG_IFC_REGMAP"></a> +              <h1 class="regmap">DIG_IFC_REGMAP</h1> +             +            <div class="group"><a name="DIG_IFC_REGMAP|SPI_OVER_GPIO_REGS"></a><h2 class="group">SPI_OVER_GPIO_REGS</h2> +             +            <div class="register"> +              <a name="DIG_IFC_REGMAP|SPI_SLAVE_CONFIG"></a> +             +<h3 class="register">Offset 0x0000: SPI_SLAVE_CONFIG(3:0) Register Array (R|W)</h3> + +                 <a class="sh_addrs" href="javascript:sa('DIG_IFC_REGMAP|SPI_SLAVE_CONFIG_in')">(<span id="show_DIG_IFC_REGMAP|SPI_SLAVE_CONFIG_in">show</span> extended info)</a> +                 <div class="sh_addrs" id="div_DIG_IFC_REGMAP|SPI_SLAVE_CONFIG_in"> +                  +                <table class="extended_info"> +                 +<tr> + +<td class="outercell" rowspan="1"> + +<table border="0" cellspacing="0" cellpadding="0"> +  <tr><td class="offset_info" align="right"><a href="#RADIO_CTRLPORT_REGMAP|DIO_WINDOW">RADIO_CTRLPORT_REGMAP|DIO_WINDOW</a></td></tr> +  <tr><td class="offset_info" align="right">  0x00C000</td></tr> +</table> + +</td> + +<td class="outercell" rowspan="1"> + +<table border="0" cellspacing="0" cellpadding="0"> +  <tr><td class="offset_info" align="right"><a href="#RADIO_DIO_REGMAP|DIGITAL_IFC_REGS">RADIO_DIO_REGMAP|DIGITAL_IFC_REGS</a></td></tr> +  <tr><td class="offset_info" align="right">  0x002000</td></tr> +</table> + +</td> + +<td class="outercell" rowspan="1"> + +<table border="0" cellspacing="0" cellpadding="0"> +  <tr><td class="offset_info" align="right">SPI_SLAVE_CONFIG</td></tr> +  <tr><td class="offset_info" align="right">  offset=0x0000 + i*4</td></tr> +</table> + +</td> + +<td class="outercell" rowspan="1"> + +<table border="0" cellspacing="0" cellpadding="0"> + +<tr><td class="offset_info"> + + +Cannot determine accessibility through this path</td></tr> +<tr><td class="offset_info"> +Total Offset =</td></tr> +<tr><td class="offset_info">  0x00E000 + i*4 + +</td></tr> +</table> + +</td> + +</tr> + +</table><p/> + +<p class="reg_info"><B>Initial Values</B><BR/> +<table> +  <tr><td>default</td><td>=></td><td>0x00000000</td></tr> +</table> +</p> + +<p class="reg_info">This register is defined in HDL source file x4xx_gpio_spi.v.<BR/> +It uses RegType <b>SPI_SETUP</b> which is defined in HDL source file x4xx_gpio_spi.v.</p> + +</div> + +<div class="info"> + +Controls SPI Transaction<BR/> +Set of configuration registers for the supported slaves. + +</div> + +                <table class="bitfields" border="0" cellspacing="0" cellpadding="0"> +                  <tr class="header"><td class="bits">Bits</td><td>Name</td></tr> +                 +            <tr  valign="top"> +              <td class="bits">31..28</td> +              <td> +                <p><span class="name">Reserved</span><span class="attr"> </span></p> +                <p></p> +             +              </td> +            </tr> +             +            <tr  valign="top"> +              <td class="bits">27</td> +              <td> +                <p><span class="name"><a name="DIG_IFC_REGMAP|SPI_SLAVE_CONFIG|MOSI_EDGE"></a>MOSI_EDGE</span><span class="attr">   (initialvalue=0)</span></p> +                <p>Controls the edge in which the MOSI line is updated.</br> +            0 =  falling edge of SCLK.</br> +            1 =  rising edge of SCLK.</p> +             +              </td> +            </tr> +             +            <tr  valign="top"> +              <td class="bits">26</td> +              <td> +                <p><span class="name"><a name="DIG_IFC_REGMAP|SPI_SLAVE_CONFIG|MISO_EDGE"></a>MISO_EDGE</span><span class="attr">   (initialvalue=0)</span></p> +                <p>Controls the edge in which the MISO line is latched.</br> +            0 =  falling edge of SCLK.</br> +            1 =  rising edge of SCLK.</p> +             +              </td> +            </tr> +             +            <tr  valign="top"> +              <td class="bits">25..20</td> +              <td> +                <p><span class="name"><a name="DIG_IFC_REGMAP|SPI_SLAVE_CONFIG|SPI_LENGTH"></a>SPI_LENGTH</span><span class="attr">   (initialvalue=0)</span></p> +                <p>Indicates the length of SPI transactions to this slave.</p> +             +              </td> +            </tr> +             +            <tr  valign="top"> +              <td class="bits">19..15</td> +              <td> +                <p><span class="name"><a name="DIG_IFC_REGMAP|SPI_SLAVE_CONFIG|SLAVE_CS"></a>SLAVE_CS</span><span class="attr">   (initialvalue=0)</span></p> +                <p>Indicates which GPIO line to use for the CS signal.</br> +            0-11 : Port A GPIO</br> +            16-27: Port B GPIO</p> +             +              </td> +            </tr> +             +            <tr  valign="top"> +              <td class="bits">14..10</td> +              <td> +                <p><span class="name"><a name="DIG_IFC_REGMAP|SPI_SLAVE_CONFIG|SLAVE_MISO"></a>SLAVE_MISO</span><span class="attr">   (initialvalue=0)</span></p> +                <p>Indicates which GPIO line to use for the MISO signal.</br> +            0-11 : Port A GPIO</br> +            16-27: Port B GPIO</p> +             +              </td> +            </tr> +             +            <tr  valign="top"> +              <td class="bits">9..5</td> +              <td> +                <p><span class="name"><a name="DIG_IFC_REGMAP|SPI_SLAVE_CONFIG|SLAVE_MOSI"></a>SLAVE_MOSI</span><span class="attr">   (initialvalue=0)</span></p> +                <p>Indicates which GPIO line to use for the MOSI signal.</br> +            0-11 : Port A GPIO</br> +            16-27: Port B GPIO</p> +             +              </td> +            </tr> +             +            <tr  valign="top"> +              <td class="bits">4..0</td> +              <td> +                <p><span class="name"><a name="DIG_IFC_REGMAP|SPI_SLAVE_CONFIG|SLAVE_CLK"></a>SLAVE_CLK</span><span class="attr">   (initialvalue=0)</span></p> +                <p>Indicates which GPIO line to use for the SCLK signal.</br> +            0-11 : Port A GPIO</br> +            16-27: Port B GPIO</p> +             +              </td> +            </tr> +             +</table> + +</div> + +            <div class="register"> +              <a name="DIG_IFC_REGMAP|SPI_TRANSACTION_CONFIG"></a> +             +<h3 class="register">Offset 0x0010: SPI_TRANSACTION_CONFIG Register (R|W)</h3> + +                 <a class="sh_addrs" href="javascript:sa('DIG_IFC_REGMAP|SPI_TRANSACTION_CONFIG_in')">(<span id="show_DIG_IFC_REGMAP|SPI_TRANSACTION_CONFIG_in">show</span> extended info)</a> +                 <div class="sh_addrs" id="div_DIG_IFC_REGMAP|SPI_TRANSACTION_CONFIG_in"> +                  +                <table class="extended_info"> +                 +<tr> + +<td class="outercell" rowspan="1"> + +<table border="0" cellspacing="0" cellpadding="0"> +  <tr><td class="offset_info" align="right"><a href="#RADIO_CTRLPORT_REGMAP|DIO_WINDOW">RADIO_CTRLPORT_REGMAP|DIO_WINDOW</a></td></tr> +  <tr><td class="offset_info" align="right">  0x00C000</td></tr> +</table> + +</td> + +<td class="outercell" rowspan="1"> + +<table border="0" cellspacing="0" cellpadding="0"> +  <tr><td class="offset_info" align="right"><a href="#RADIO_DIO_REGMAP|DIGITAL_IFC_REGS">RADIO_DIO_REGMAP|DIGITAL_IFC_REGS</a></td></tr> +  <tr><td class="offset_info" align="right">  0x002000</td></tr> +</table> + +</td> + +<td class="outercell" rowspan="1"> + +<table border="0" cellspacing="0" cellpadding="0"> +  <tr><td class="offset_info" align="right">SPI_TRANSACTION_CONFIG</td></tr> +  <tr><td class="offset_info" align="right">  offset=0x0010</td></tr> +</table> + +</td> + +<td class="outercell" rowspan="1"> + +<table border="0" cellspacing="0" cellpadding="0"> + +<tr><td class="offset_info"> + + +Total Offset =</td></tr> +<tr><td class="offset_info">  0x00E010 + +</td></tr> +</table> + +</td> + +</tr> + +</table><p/> + +<p class="reg_info">Initial Value = 0x00000000 +</p> + +<p class="reg_info">This register is defined in HDL source file x4xx_gpio_spi.v.</p> + +</div> + +<div class="info"> + +Controls clock rate and target for subsequent SPI transactions. + +</div> + +                <table class="bitfields" border="0" cellspacing="0" cellpadding="0"> +                  <tr class="header"><td class="bits">Bits</td><td>Name</td></tr> +                 +            <tr  valign="top"> +              <td class="bits">31..24</td> +              <td> +                <p><span class="name">Reserved</span><span class="attr"> </span></p> +                <p></p> +             +              </td> +            </tr> +             +            <tr class='byte' valign="top"> +              <td class="bits">23..18</td> +              <td> +                <p><span class="name">Reserved</span><span class="attr"> </span></p> +                <p></p> +             +              </td> +            </tr> +             +            <tr  valign="top"> +              <td class="bits">17..16</td> +              <td> +                <p><span class="name"><a name="DIG_IFC_REGMAP|SPI_TRANSACTION_CONFIG|SPI_SLAVE_SELECT"></a>SPI_SLAVE_SELECT</span><span class="attr">   (initialvalue=0)</span></p> +                <p></p> +             +              </td> +            </tr> +             +            <tr class='byte' valign="top"> +              <td class="bits">15..0</td> +              <td> +                <p><span class="name"><a name="DIG_IFC_REGMAP|SPI_TRANSACTION_CONFIG|SPI_CLK_DIV"></a>SPI_CLK_DIV</span><span class="attr">   (initialvalue=0)</span></p> +                <p>Controls the rate for subsequent SPI transactions. SCLK = DataClk/[(SPI_CLK_DIV+1)]</p> +             +              </td> +            </tr> +             +</table> + +</div> + +            <div class="register"> +              <a name="DIG_IFC_REGMAP|SPI_TRANSACTION_GO"></a> +             +<h3 class="register">Offset 0x0014: SPI_TRANSACTION_GO Register (W)</h3> + +                 <a class="sh_addrs" href="javascript:sa('DIG_IFC_REGMAP|SPI_TRANSACTION_GO_in')">(<span id="show_DIG_IFC_REGMAP|SPI_TRANSACTION_GO_in">show</span> extended info)</a> +                 <div class="sh_addrs" id="div_DIG_IFC_REGMAP|SPI_TRANSACTION_GO_in"> +                  +                <table class="extended_info"> +                 +<tr> + +<td class="outercell" rowspan="1"> + +<table border="0" cellspacing="0" cellpadding="0"> +  <tr><td class="offset_info" align="right"><a href="#RADIO_CTRLPORT_REGMAP|DIO_WINDOW">RADIO_CTRLPORT_REGMAP|DIO_WINDOW</a></td></tr> +  <tr><td class="offset_info" align="right">  0x00C000</td></tr> +</table> + +</td> + +<td class="outercell" rowspan="1"> + +<table border="0" cellspacing="0" cellpadding="0"> +  <tr><td class="offset_info" align="right"><a href="#RADIO_DIO_REGMAP|DIGITAL_IFC_REGS">RADIO_DIO_REGMAP|DIGITAL_IFC_REGS</a></td></tr> +  <tr><td class="offset_info" align="right">  0x002000</td></tr> +</table> + +</td> + +<td class="outercell" rowspan="1"> + +<table border="0" cellspacing="0" cellpadding="0"> +  <tr><td class="offset_info" align="right">SPI_TRANSACTION_GO</td></tr> +  <tr><td class="offset_info" align="right">  offset=0x0014</td></tr> +</table> + +</td> + +<td class="outercell" rowspan="1"> + +<table border="0" cellspacing="0" cellpadding="0"> + +<tr><td class="offset_info"> + + +Total Offset =</td></tr> +<tr><td class="offset_info">  0x00E014 + +</td></tr> +</table> + +</td> + +</tr> + +</table><p/> + +<p class="reg_info">Initial Value = 0x00000000 +</p> + +<p class="reg_info">This register is defined in HDL source file x4xx_gpio_spi.v.</p> + +</div> + +<div class="info"> + +Starts a SPI transaction + +</div> + +                <table class="bitfields" border="0" cellspacing="0" cellpadding="0"> +                  <tr class="header"><td class="bits">Bits</td><td>Name</td></tr> +                 +            <tr  valign="top"> +              <td class="bits">31..0w</td> +              <td> +                <p><span class="name"><a name="DIG_IFC_REGMAP|SPI_TRANSACTION_GO|SPI_DATA"></a>SPI_DATA</span><span class="attr">   (initialvalue=0)</span></p> +                <p>Payload to be sent for the SPI transaction. If the payload is shorter than 32 bits, +               it must be aligned to the MSbs in this field. LSbs are ignored in this scenario.</p> +             +              </td> +            </tr> +             +</table> + +</div> + +            <div class="register"> +              <a name="DIG_IFC_REGMAP|SPI_STATUS"></a> +             +<h3 class="register">Offset 0x0018: SPI_STATUS Register (R)</h3> + +                 <a class="sh_addrs" href="javascript:sa('DIG_IFC_REGMAP|SPI_STATUS_in')">(<span id="show_DIG_IFC_REGMAP|SPI_STATUS_in">show</span> extended info)</a> +                 <div class="sh_addrs" id="div_DIG_IFC_REGMAP|SPI_STATUS_in"> +                  +                <table class="extended_info"> +                 +<tr> + +<td class="outercell" rowspan="1"> + +<table border="0" cellspacing="0" cellpadding="0"> +  <tr><td class="offset_info" align="right"><a href="#RADIO_CTRLPORT_REGMAP|DIO_WINDOW">RADIO_CTRLPORT_REGMAP|DIO_WINDOW</a></td></tr> +  <tr><td class="offset_info" align="right">  0x00C000</td></tr> +</table> + +</td> + +<td class="outercell" rowspan="1"> + +<table border="0" cellspacing="0" cellpadding="0"> +  <tr><td class="offset_info" align="right"><a href="#RADIO_DIO_REGMAP|DIGITAL_IFC_REGS">RADIO_DIO_REGMAP|DIGITAL_IFC_REGS</a></td></tr> +  <tr><td class="offset_info" align="right">  0x002000</td></tr> +</table> + +</td> + +<td class="outercell" rowspan="1"> + +<table border="0" cellspacing="0" cellpadding="0"> +  <tr><td class="offset_info" align="right">SPI_STATUS</td></tr> +  <tr><td class="offset_info" align="right">  offset=0x0018</td></tr> +</table> + +</td> + +<td class="outercell" rowspan="1"> + +<table border="0" cellspacing="0" cellpadding="0"> + +<tr><td class="offset_info"> + + +Total Offset =</td></tr> +<tr><td class="offset_info">  0x00E018 + +</td></tr> +</table> + +</td> + +</tr> + +</table><p/> + +<p class="reg_info">Initial Value = 0x00000000 +</p> + +<p class="reg_info">This register is defined in HDL source file x4xx_gpio_spi.v.</p> + +</div> + +<div class="info"> + +Contains the status of the SPI engine. + +</div> + +                <table class="bitfields" border="0" cellspacing="0" cellpadding="0"> +                  <tr class="header"><td class="bits">Bits</td><td>Name</td></tr> +                 +            <tr  valign="top"> +              <td class="bits">31..25</td> +              <td> +                <p><span class="name">Reserved</span><span class="attr"> </span></p> +                <p></p> +             +              </td> +            </tr> +             +            <tr  valign="top"> +              <td class="bits">24</td> +              <td> +                <p><span class="name"><a name="DIG_IFC_REGMAP|SPI_STATUS|SPI_READY"></a>SPI_READY</span><span class="attr">   (initialvalue=0)</span></p> +                <p>Indicates the SPI engine is ready to start a new SPI transaction.</p> +             +              </td> +            </tr> +             +            <tr class='byte' valign="top"> +              <td class="bits">23..0</td> +              <td> +                <p><span class="name"><a name="DIG_IFC_REGMAP|SPI_STATUS|SPI_RESPONSE"></a>SPI_RESPONSE</span><span class="attr">   (initialvalue=0)</span></p> +                <p>Records the response of the last completed SPI transaction.</p> +             +              </td> +            </tr> +             +</table> + +</div> + +</div> + +</div> + +            <div class="regmap">                <a name="DIO_REGMAP"></a>                <h1 class="regmap">DIO_REGMAP</h1> @@ -8020,7 +8506,7 @@ Total Offset =</td></tr>  Controls whether GPIO lines use the TX and RX state of an RF channel          (Classic ATR) or the daughterboard state the selector for the -        @.GPIO_ATR_STATE. +        <a href="#GPIO_ATR_REGMAP|ATR_STATE">ATR_STATE</a>.  </div> @@ -8069,7 +8555,7 @@ Controls whether GPIO lines use the TX and RX state of an RF channel                  <p><span class="name"><a name="GPIO_ATR_REGMAP|ATR_OPTION_REGISTRER|ATR_OPTION"></a>ATR_OPTION</span><span class="attr">   (initialvalue=0)</span></p>                  <p>Sets the scheme in which RF states in the radio will control GPIO            lines. 0 = DB state is used. RF states are combined and the -          GPIO state is driven based on all 16 @.GPIO_ATR_STATE registers. +          GPIO state is driven based on all 16 <a href="#GPIO_ATR_REGMAP|ATR_STATE">ATR_STATE</a> registers.            1 = Each RF channel has its separate ATR state(Classic ATR).            Use register <a href="#GPIO_ATR_REGMAP|CLASSIC_ATR_CONFIG">CLASSIC_ATR_CONFIG</a> to indicate the RF channel            to which each GPIO line responds to.</p> @@ -16324,6 +16810,69 @@ Window to access the DIO register map through the control port from the radio bl  </div> +            <div class="register"> +              <a name="RADIO_DIO_REGMAP|DIGITAL_IFC_REGS"></a> +             +<h3 class="register">Offset 0x2000: DIGITAL_IFC_REGS Window (R|W)</h3> +<p class="offset_info">  Target regmap = <a href="#DIG_IFC_REGMAP">DIG_IFC_REGMAP</a></p> +                 <a class="sh_addrs" href="javascript:sa('RADIO_DIO_REGMAP|DIGITAL_IFC_REGS_in')">(<span id="show_RADIO_DIO_REGMAP|DIGITAL_IFC_REGS_in">show</span> extended info)</a> +                 <div class="sh_addrs" id="div_RADIO_DIO_REGMAP|DIGITAL_IFC_REGS_in"> +                  +                <table class="extended_info"> +                 +<tr> + +<td class="outercell" rowspan="1"> + +<table border="0" cellspacing="0" cellpadding="0"> +  <tr><td class="offset_info" align="right"><a href="#RADIO_CTRLPORT_REGMAP|DIO_WINDOW">RADIO_CTRLPORT_REGMAP|DIO_WINDOW</a></td></tr> +  <tr><td class="offset_info" align="right">  0x00C000</td></tr> +</table> + +</td> + +<td class="outercell" rowspan="1"> + +<table border="0" cellspacing="0" cellpadding="0"> +  <tr><td class="offset_info" align="right">DIGITAL_IFC_REGS</td></tr> +  <tr><td class="offset_info" align="right">  offset=0x2000</td></tr> +  <tr><td class="offset_info" align="right">  size=0x1000 (4 Kbytes)</td></tr> +</table> + +</td> + +<td class="outercell" rowspan="1"> + +<table border="0" cellspacing="0" cellpadding="0"> + +<tr><td class="offset_info"> + + +Total Offset =</td></tr> +<tr><td class="offset_info">  0x00E000 + +</td></tr> +</table> + +</td> + +</tr> + +</table><p/> + +<p class="reg_info">This window is defined in HDL source file x4xx_core_common.v.</p> + +</div> + +<div class="info"> + +Register space reserved for configuring a digital interface over the GPIO lines. +            Currently, SPI is the only supported protocol. + +</div> + +</div> +  </div>  </div> diff --git a/fpga/usrp3/top/x400/regmap/dig_ifc_regmap_utils.vh b/fpga/usrp3/top/x400/regmap/dig_ifc_regmap_utils.vh new file mode 100644 index 000000000..7ead185d7 --- /dev/null +++ b/fpga/usrp3/top/x400/regmap/dig_ifc_regmap_utils.vh @@ -0,0 +1,88 @@ +// +// Copyright 2021 Ettus Research, A National Instruments Company +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Module: dig_ifc_regmap_utils.vh +// Description: +// The constants in this file are autogenerated by XmlParse. + +//=============================================================================== +// A numerically ordered list of registers and their HDL source files +//=============================================================================== + +  // SPI_SLAVE_CONFIG       : 0x0 (x4xx_gpio_spi.v) +  // SPI_TRANSACTION_CONFIG : 0x10 (x4xx_gpio_spi.v) +  // SPI_TRANSACTION_GO     : 0x14 (x4xx_gpio_spi.v) +  // SPI_STATUS             : 0x18 (x4xx_gpio_spi.v) + +//=============================================================================== +// RegTypes +//=============================================================================== + +  // SPI_SETUP Type (from x4xx_gpio_spi.v) +  localparam SPI_SETUP_SIZE = 32; +  localparam SPI_SETUP_MASK = 32'hFFFFFFF; +  localparam SLAVE_CLK_SIZE = 5;  //SPI_SETUP:SLAVE_CLK +  localparam SLAVE_CLK_MSB  = 4;  //SPI_SETUP:SLAVE_CLK +  localparam SLAVE_CLK      = 0;  //SPI_SETUP:SLAVE_CLK +  localparam SLAVE_MOSI_SIZE = 5;  //SPI_SETUP:SLAVE_MOSI +  localparam SLAVE_MOSI_MSB  = 9;  //SPI_SETUP:SLAVE_MOSI +  localparam SLAVE_MOSI      = 5;  //SPI_SETUP:SLAVE_MOSI +  localparam SLAVE_MISO_SIZE =  5;  //SPI_SETUP:SLAVE_MISO +  localparam SLAVE_MISO_MSB  = 14;  //SPI_SETUP:SLAVE_MISO +  localparam SLAVE_MISO      = 10;  //SPI_SETUP:SLAVE_MISO +  localparam SLAVE_CS_SIZE =  5;  //SPI_SETUP:SLAVE_CS +  localparam SLAVE_CS_MSB  = 19;  //SPI_SETUP:SLAVE_CS +  localparam SLAVE_CS      = 15;  //SPI_SETUP:SLAVE_CS +  localparam SPI_LENGTH_SIZE =  6;  //SPI_SETUP:SPI_LENGTH +  localparam SPI_LENGTH_MSB  = 25;  //SPI_SETUP:SPI_LENGTH +  localparam SPI_LENGTH      = 20;  //SPI_SETUP:SPI_LENGTH +  localparam MISO_EDGE_SIZE =  1;  //SPI_SETUP:MISO_EDGE +  localparam MISO_EDGE_MSB  = 26;  //SPI_SETUP:MISO_EDGE +  localparam MISO_EDGE      = 26;  //SPI_SETUP:MISO_EDGE +  localparam MOSI_EDGE_SIZE =  1;  //SPI_SETUP:MOSI_EDGE +  localparam MOSI_EDGE_MSB  = 27;  //SPI_SETUP:MOSI_EDGE +  localparam MOSI_EDGE      = 27;  //SPI_SETUP:MOSI_EDGE + +//=============================================================================== +// Register Group SPI_OVER_GPIO_REGS +//=============================================================================== + +  // SPI_SLAVE_CONFIG Register (from x4xx_gpio_spi.v) +  localparam SPI_SLAVE_CONFIG_COUNT = 4; // Number of elements in array + +  // SPI_TRANSACTION_CONFIG Register (from x4xx_gpio_spi.v) +  localparam SPI_TRANSACTION_CONFIG = 'h10; // Register Offset +  localparam SPI_TRANSACTION_CONFIG_SIZE = 32;  // register width in bits +  localparam SPI_TRANSACTION_CONFIG_MASK = 32'h3FFFF; +  localparam SPI_CLK_DIV_SIZE = 16;  //SPI_TRANSACTION_CONFIG:SPI_CLK_DIV +  localparam SPI_CLK_DIV_MSB  = 15;  //SPI_TRANSACTION_CONFIG:SPI_CLK_DIV +  localparam SPI_CLK_DIV      =  0;  //SPI_TRANSACTION_CONFIG:SPI_CLK_DIV +  localparam SPI_SLAVE_SELECT_SIZE =  2;  //SPI_TRANSACTION_CONFIG:SPI_SLAVE_SELECT +  localparam SPI_SLAVE_SELECT_MSB  = 17;  //SPI_TRANSACTION_CONFIG:SPI_SLAVE_SELECT +  localparam SPI_SLAVE_SELECT      = 16;  //SPI_TRANSACTION_CONFIG:SPI_SLAVE_SELECT + +  // SPI_TRANSACTION_GO Register (from x4xx_gpio_spi.v) +  localparam SPI_TRANSACTION_GO = 'h14; // Register Offset +  localparam SPI_TRANSACTION_GO_SIZE = 32;  // register width in bits +  localparam SPI_TRANSACTION_GO_MASK = 32'hFFFFFFFF; +  localparam SPI_DATA_SIZE = 32;  //SPI_TRANSACTION_GO:SPI_DATA +  localparam SPI_DATA_MSB  = 31;  //SPI_TRANSACTION_GO:SPI_DATA +  localparam SPI_DATA      =  0;  //SPI_TRANSACTION_GO:SPI_DATA + +  // SPI_STATUS Register (from x4xx_gpio_spi.v) +  localparam SPI_STATUS = 'h18; // Register Offset +  localparam SPI_STATUS_SIZE = 32;  // register width in bits +  localparam SPI_STATUS_MASK = 32'h1FFFFFF; +  localparam SPI_RESPONSE_SIZE = 24;  //SPI_STATUS:SPI_RESPONSE +  localparam SPI_RESPONSE_MSB  = 23;  //SPI_STATUS:SPI_RESPONSE +  localparam SPI_RESPONSE      =  0;  //SPI_STATUS:SPI_RESPONSE +  localparam SPI_READY_SIZE =  1;  //SPI_STATUS:SPI_READY +  localparam SPI_READY_MSB  = 24;  //SPI_STATUS:SPI_READY +  localparam SPI_READY      = 24;  //SPI_STATUS:SPI_READY + +  // Return the offset of an element of register array SPI_SLAVE_CONFIG +  function integer SPI_SLAVE_CONFIG (input integer i); +    SPI_SLAVE_CONFIG = (i * 'h4) + 'h0; +  endfunction diff --git a/fpga/usrp3/top/x400/regmap/radio_dio_regmap_utils.vh b/fpga/usrp3/top/x400/regmap/radio_dio_regmap_utils.vh index 62de3d75e..6916dc79c 100644 --- a/fpga/usrp3/top/x400/regmap/radio_dio_regmap_utils.vh +++ b/fpga/usrp3/top/x400/regmap/radio_dio_regmap_utils.vh @@ -13,6 +13,7 @@    // RADIO_GPIO_ATR_REGS : 0x0 (x4xx_core_common.v)    // DIO_SOURCE_CONTROL  : 0x1000 (x4xx_core_common.v) +  // DIGITAL_IFC_REGS    : 0x2000 (x4xx_core_common.v)  //===============================================================================  // RegTypes @@ -29,3 +30,7 @@    // DIO_SOURCE_CONTROL Window (from x4xx_core_common.v)    localparam DIO_SOURCE_CONTROL = 'h1000; // Window Offset    localparam DIO_SOURCE_CONTROL_SIZE = 'h1000;  // size in bytes + +  // DIGITAL_IFC_REGS Window (from x4xx_core_common.v) +  localparam DIGITAL_IFC_REGS = 'h2000; // Window Offset +  localparam DIGITAL_IFC_REGS_SIZE = 'h1000;  // size in bytes diff --git a/fpga/usrp3/top/x400/x4xx_core.v b/fpga/usrp3/top/x400/x4xx_core.v index 4e944e335..609892581 100644 --- a/fpga/usrp3/top/x400/x4xx_core.v +++ b/fpga/usrp3/top/x400/x4xx_core.v @@ -249,6 +249,7 @@ module x4xx_core #(      .PCIE_PRESENT   (0)    ) x4xx_core_common_i (      .radio_clk                        (radio_clk), +    .radio_clk_2x                     (radio_clk_2x),      .radio_rst                        (radio_rst),      .rfnoc_chdr_clk                   (rfnoc_chdr_clk),      .rfnoc_chdr_rst                   (rfnoc_chdr_rst), diff --git a/fpga/usrp3/top/x400/x4xx_core_common.v b/fpga/usrp3/top/x400/x4xx_core_common.v index 3dac18ad5..89dd49a49 100644 --- a/fpga/usrp3/top/x400/x4xx_core_common.v +++ b/fpga/usrp3/top/x400/x4xx_core_common.v @@ -38,6 +38,7 @@ module x4xx_core_common #(  ) (    // Clocks and resets    input wire radio_clk, +  input wire radio_clk_2x,    input wire radio_rst,    input wire rfnoc_chdr_clk, @@ -234,16 +235,16 @@ module x4xx_core_common #(      .s_ctrlport_resp_ack     (m_resp_ack),      .s_ctrlport_resp_status  (m_resp_status),      .s_ctrlport_resp_data    (m_resp_data), -    .m_ctrlport_req_wr       ({timekeeper_req_wr, versioning_req_wr, global_regs_req_wr, dio_req_wr}), -    .m_ctrlport_req_rd       ({timekeeper_req_rd, versioning_req_rd, global_regs_req_rd, dio_req_rd}), -    .m_ctrlport_req_addr     ({timekeeper_req_addr, versioning_req_addr, global_regs_req_addr, dio_req_addr}), -    .m_ctrlport_req_data     ({timekeeper_req_data, versioning_req_data, global_regs_req_data, dio_req_data}), +    .m_ctrlport_req_wr       ({timekeeper_req_wr,      versioning_req_wr,      global_regs_req_wr,      dio_req_wr}), +    .m_ctrlport_req_rd       ({timekeeper_req_rd,      versioning_req_rd,      global_regs_req_rd,      dio_req_rd}), +    .m_ctrlport_req_addr     ({timekeeper_req_addr,    versioning_req_addr,    global_regs_req_addr,    dio_req_addr}), +    .m_ctrlport_req_data     ({timekeeper_req_data,    versioning_req_data,    global_regs_req_data,    dio_req_data}),      .m_ctrlport_req_byte_en  (),      .m_ctrlport_req_has_time (),      .m_ctrlport_req_time     (), -    .m_ctrlport_resp_ack     ({timekeeper_resp_ack, versioning_resp_ack, global_regs_resp_ack, dio_resp_ack}), +    .m_ctrlport_resp_ack     ({timekeeper_resp_ack,    versioning_resp_ack,    global_regs_resp_ack,    dio_resp_ack}),      .m_ctrlport_resp_status  ({timekeeper_resp_status, versioning_resp_status, global_regs_resp_status, dio_resp_status}), -    .m_ctrlport_resp_data    ({timekeeper_resp_data, versioning_resp_data, global_regs_resp_data, dio_resp_data}) +    .m_ctrlport_resp_data    ({timekeeper_resp_data,   versioning_resp_data,   global_regs_resp_data,   dio_resp_data})    ); @@ -349,6 +350,7 @@ module x4xx_core_common #(    // Radio CtrlPort Splitter    //----------------------------------------------------------------------- +  // Radio CtrlPort endpoints    wire [  1*NUM_DBOARDS-1:0] rf_ctrlport_req_wr;    wire [  1*NUM_DBOARDS-1:0] rf_ctrlport_req_rd;    wire [ 20*NUM_DBOARDS-1:0] rf_ctrlport_req_addr; @@ -371,9 +373,36 @@ module x4xx_core_common #(    wire [  2*NUM_DBOARDS-1:0] radio_dio_resp_status;    wire [ 32*NUM_DBOARDS-1:0] radio_dio_resp_data; +  wire [  1*NUM_DBOARDS-1:0] gpio_atr_ctrlport_req_wr; +  wire [  1*NUM_DBOARDS-1:0] gpio_atr_ctrlport_req_rd; +  wire [ 20*NUM_DBOARDS-1:0] gpio_atr_ctrlport_req_addr; +  wire [ 32*NUM_DBOARDS-1:0] gpio_atr_ctrlport_req_data; +  wire [  4*NUM_DBOARDS-1:0] gpio_atr_ctrlport_req_byte_en; +  wire [  1*NUM_DBOARDS-1:0] gpio_atr_ctrlport_req_has_time; +  wire [ 64*NUM_DBOARDS-1:0] gpio_atr_ctrlport_req_time; +  wire [  1*NUM_DBOARDS-1:0] gpio_atr_ctrlport_resp_ack; +  wire [  2*NUM_DBOARDS-1:0] gpio_atr_ctrlport_resp_status; +  wire [ 32*NUM_DBOARDS-1:0] gpio_atr_ctrlport_resp_data; + +  wire [  1*NUM_DBOARDS-1:0] gpio_spi_ctrlport_req_wr; +  wire [  1*NUM_DBOARDS-1:0] gpio_spi_ctrlport_req_rd; +  wire [ 20*NUM_DBOARDS-1:0] gpio_spi_ctrlport_req_addr; +  wire [ 32*NUM_DBOARDS-1:0] gpio_spi_ctrlport_req_data; +  wire [  4*NUM_DBOARDS-1:0] gpio_spi_ctrlport_req_byte_en; +  wire [  1*NUM_DBOARDS-1:0] gpio_spi_ctrlport_req_has_time; +  wire [ 64*NUM_DBOARDS-1:0] gpio_spi_ctrlport_req_time; +  wire [  1*NUM_DBOARDS-1:0] gpio_spi_ctrlport_resp_ack; +  wire [  2*NUM_DBOARDS-1:0] gpio_spi_ctrlport_resp_status; +  wire [ 32*NUM_DBOARDS-1:0] gpio_spi_ctrlport_resp_data; + +  // GPIO control signals from radio ctrlport endpoints to +  // x4xx_dio.    wire [NUM_DBOARDS*32-1:0] atr_gpio_out;    wire [NUM_DBOARDS*32-1:0] atr_gpio_ddr; +  wire [NUM_DBOARDS*32-1:0] spi_gpio_out; +  wire [NUM_DBOARDS*32-1:0] spi_gpio_ddr; +    genvar db;    generate      for (db = 0; db < NUM_DBOARDS; db = db+1) begin : gen_radio_ctrlport @@ -385,67 +414,100 @@ module x4xx_core_common #(        //   This section takes the CtrlPort master from each radio block and splits it        //   into a CtrlPort bus for the associated daughter(m_radio_ctrlport_*), the        //   RFDC timing control (rf_ctrlport_*), the ATR GPIO control for the DB state -      //   the current radio(db) and DIO main control block(x4xx_dio). +      //   the current radio(db), the SPI controller of the radio, and DIO main +      //   control block(x4xx_dio).        //   Refer to diagram in the RADIO_CTRLPORT_REGMAP Register map for a        //   visual representation on how these interfaces are distributed.        // Register space offset calculation        localparam [19:0] DIO_SOURCE_CONTROL_OFFSET = DIO_WINDOW + DIO_SOURCE_CONTROL;        localparam [19:0] RADIO_GPIO_ATR_OFFSET = DIO_WINDOW + RADIO_GPIO_ATR_REGS; +      localparam [19:0] DIGITAL_IFC_OFFSET = DIO_WINDOW + DIGITAL_IFC_REGS;        // Register space size calculation        localparam [31:0] RFDC_TIMING_WINDOW_SIZE_W = $clog2(RFDC_TIMING_WINDOW_SIZE);        localparam [31:0] DB_WINDOW_SIZE_W          = $clog2(DB_WINDOW_SIZE);        localparam [31:0] DIO_SOURCE_CONTROL_SIZE_W = $clog2(DIO_SOURCE_CONTROL_SIZE);        localparam [31:0] RADIO_GPIO_ATR_SIZE_W     = $clog2(RADIO_GPIO_ATR_REGS_SIZE); - -      wire        gpio_atr_ctrlport_req_wr; -      wire        gpio_atr_ctrlport_req_rd; -      wire [19:0] gpio_atr_ctrlport_req_addr; -      wire [31:0] gpio_atr_ctrlport_req_data; -      wire [ 3:0] gpio_atr_ctrlport_req_byte_en; -      wire        gpio_atr_ctrlport_req_has_time; -      wire [63:0] gpio_atr_ctrlport_req_time; -      wire        gpio_atr_ctrlport_resp_ack; -      wire [ 1:0] gpio_atr_ctrlport_resp_status; -      wire [31:0] gpio_atr_ctrlport_resp_data; - +      localparam [31:0] DIGITAL_IFC_REGS_SIZE_W   = $clog2(DIGITAL_IFC_REGS_SIZE);        ctrlport_decoder_param #( -        .NUM_SLAVES  (4), -        .PORT_BASE   ({ DIO_SOURCE_CONTROL_OFFSET, +        .NUM_SLAVES  (5), +        .PORT_BASE   ({ DIGITAL_IFC_OFFSET, +                        DIO_SOURCE_CONTROL_OFFSET,                          RADIO_GPIO_ATR_OFFSET,                          RFDC_TIMING_WINDOW[19:0],                          DB_WINDOW[19:0]                        }), -        .PORT_ADDR_W ({ DIO_SOURCE_CONTROL_SIZE_W, +        .PORT_ADDR_W ({ DIGITAL_IFC_REGS_SIZE_W, +                        DIO_SOURCE_CONTROL_SIZE_W,                          RADIO_GPIO_ATR_SIZE_W,                          RFDC_TIMING_WINDOW_SIZE_W,                          DB_WINDOW_SIZE_W                        })        ) ctrlport_decoder_param_i ( -        .ctrlport_clk            (radio_clk), -        .ctrlport_rst            (radio_rst), -        .s_ctrlport_req_wr       (s_radio_ctrlport_req_wr       [ 1*db+: 1]), -        .s_ctrlport_req_rd       (s_radio_ctrlport_req_rd       [ 1*db+: 1]), -        .s_ctrlport_req_addr     (s_radio_ctrlport_req_addr     [20*db+:20]), -        .s_ctrlport_req_data     (s_radio_ctrlport_req_data     [32*db+:32]), -        .s_ctrlport_req_byte_en  (s_radio_ctrlport_req_byte_en  [ 4*db+: 4]), -        .s_ctrlport_req_has_time (s_radio_ctrlport_req_has_time [ 1*db+: 1]), -        .s_ctrlport_req_time     (s_radio_ctrlport_req_time     [64*db+:64]), -        .s_ctrlport_resp_ack     (s_radio_ctrlport_resp_ack     [ 1*db+: 1]), -        .s_ctrlport_resp_status  (s_radio_ctrlport_resp_status  [ 2*db+: 2]), -        .s_ctrlport_resp_data    (s_radio_ctrlport_resp_data    [32*db+:32]), -        .m_ctrlport_req_wr       ({ radio_dio_req_wr       [ 1*db+: 1], gpio_atr_ctrlport_req_wr,        rf_ctrlport_req_wr       [ 1*db+: 1], m_radio_ctrlport_req_wr       [ 1*db+: 1] }), -        .m_ctrlport_req_rd       ({ radio_dio_req_rd       [ 1*db+: 1], gpio_atr_ctrlport_req_rd,        rf_ctrlport_req_rd       [ 1*db+: 1], m_radio_ctrlport_req_rd       [ 1*db+: 1] }), -        .m_ctrlport_req_addr     ({ radio_dio_req_addr     [20*db+:20], gpio_atr_ctrlport_req_addr,      rf_ctrlport_req_addr     [20*db+:20], m_radio_ctrlport_req_addr     [20*db+:20] }), -        .m_ctrlport_req_data     ({ radio_dio_req_data     [32*db+:32], gpio_atr_ctrlport_req_data,      rf_ctrlport_req_data     [32*db+:32], m_radio_ctrlport_req_data     [32*db+:32] }), -        .m_ctrlport_req_byte_en  ({ radio_dio_req_byte_en  [ 4*db+: 4], gpio_atr_ctrlport_req_byte_en,   rf_ctrlport_req_byte_en  [ 4*db+: 4], m_radio_ctrlport_req_byte_en  [ 4*db+: 4] }), -        .m_ctrlport_req_has_time ({ radio_dio_req_has_time [ 1*db+: 1], gpio_atr_ctrlport_req_has_time,  rf_ctrlport_req_has_time [ 1*db+: 1], m_radio_ctrlport_req_has_time [ 1*db+: 1] }), -        .m_ctrlport_req_time     ({ radio_dio_req_time     [64*db+:64], gpio_atr_ctrlport_req_time,      rf_ctrlport_req_time     [64*db+:64], m_radio_ctrlport_req_time     [64*db+:64] }), -        .m_ctrlport_resp_ack     ({ radio_dio_resp_ack     [ 1*db+: 1], gpio_atr_ctrlport_resp_ack,      rf_ctrlport_resp_ack     [ 1*db+: 1], m_radio_ctrlport_resp_ack     [ 1*db+: 1] }), -        .m_ctrlport_resp_status  ({ radio_dio_resp_status  [ 2*db+: 2], gpio_atr_ctrlport_resp_status,   rf_ctrlport_resp_status  [ 2*db+: 2], m_radio_ctrlport_resp_status  [ 2*db+: 2] }), -        .m_ctrlport_resp_data    ({ radio_dio_resp_data    [32*db+:32], gpio_atr_ctrlport_resp_data,     rf_ctrlport_resp_data    [32*db+:32], m_radio_ctrlport_resp_data    [32*db+:32] }) +        .ctrlport_clk            (  radio_clk ), +        .ctrlport_rst            (  radio_rst ), +        .s_ctrlport_req_wr       (  s_radio_ctrlport_req_wr         [ 1*db+: 1] ), +        .s_ctrlport_req_rd       (  s_radio_ctrlport_req_rd         [ 1*db+: 1] ), +        .s_ctrlport_req_addr     (  s_radio_ctrlport_req_addr       [20*db+:20] ), +        .s_ctrlport_req_data     (  s_radio_ctrlport_req_data       [32*db+:32] ), +        .s_ctrlport_req_byte_en  (  s_radio_ctrlport_req_byte_en    [ 4*db+: 4] ), +        .s_ctrlport_req_has_time (  s_radio_ctrlport_req_has_time   [ 1*db+: 1] ), +        .s_ctrlport_req_time     (  s_radio_ctrlport_req_time       [64*db+:64] ), +        .s_ctrlport_resp_ack     (  s_radio_ctrlport_resp_ack       [ 1*db+: 1] ), +        .s_ctrlport_resp_status  (  s_radio_ctrlport_resp_status    [ 2*db+: 2] ), +        .s_ctrlport_resp_data    (  s_radio_ctrlport_resp_data      [32*db+:32] ), +        .m_ctrlport_req_wr       ({ gpio_spi_ctrlport_req_wr        [ 1*db+: 1], +                                    radio_dio_req_wr                [ 1*db+: 1], +                                    gpio_atr_ctrlport_req_wr        [ 1*db+: 1], +                                    rf_ctrlport_req_wr              [ 1*db+: 1], +                                    m_radio_ctrlport_req_wr         [ 1*db+: 1] }), +        .m_ctrlport_req_rd       ({ gpio_spi_ctrlport_req_rd        [ 1*db+: 1], +                                    radio_dio_req_rd                [ 1*db+: 1], +                                    gpio_atr_ctrlport_req_rd        [ 1*db+: 1], +                                    rf_ctrlport_req_rd              [ 1*db+: 1], +                                    m_radio_ctrlport_req_rd         [ 1*db+: 1] }), +        .m_ctrlport_req_addr     ({ gpio_spi_ctrlport_req_addr      [20*db+:20], +                                    radio_dio_req_addr              [20*db+:20], +                                    gpio_atr_ctrlport_req_addr      [20*db+:20], +                                    rf_ctrlport_req_addr            [20*db+:20], +                                    m_radio_ctrlport_req_addr       [20*db+:20] }), +        .m_ctrlport_req_data     ({ gpio_spi_ctrlport_req_data      [32*db+:32], +                                    radio_dio_req_data              [32*db+:32], +                                    gpio_atr_ctrlport_req_data      [32*db+:32], +                                    rf_ctrlport_req_data            [32*db+:32], +                                    m_radio_ctrlport_req_data       [32*db+:32] }), +        .m_ctrlport_req_byte_en  ({ gpio_spi_ctrlport_req_byte_en   [ 4*db+: 4], +                                    radio_dio_req_byte_en           [ 4*db+: 4], +                                    gpio_atr_ctrlport_req_byte_en   [ 4*db+: 4], +                                    rf_ctrlport_req_byte_en         [ 4*db+: 4], +                                    m_radio_ctrlport_req_byte_en    [ 4*db+: 4] }), +        .m_ctrlport_req_has_time ({ gpio_spi_ctrlport_req_has_time  [ 1*db+: 1], +                                    radio_dio_req_has_time          [ 1*db+: 1], +                                    gpio_atr_ctrlport_req_has_time  [ 1*db+: 1], +                                    rf_ctrlport_req_has_time        [ 1*db+: 1], +                                    m_radio_ctrlport_req_has_time   [ 1*db+: 1] }), +        .m_ctrlport_req_time     ({ gpio_spi_ctrlport_req_time      [64*db+:64], +                                    radio_dio_req_time              [64*db+:64], +                                    gpio_atr_ctrlport_req_time      [64*db+:64], +                                    rf_ctrlport_req_time            [64*db+:64], +                                    m_radio_ctrlport_req_time       [64*db+:64] }), +        .m_ctrlport_resp_ack     ({ gpio_spi_ctrlport_resp_ack      [ 1*db+: 1], +                                    radio_dio_resp_ack              [ 1*db+: 1], +                                    gpio_atr_ctrlport_resp_ack      [ 1*db+: 1], +                                    rf_ctrlport_resp_ack            [ 1*db+: 1], +                                    m_radio_ctrlport_resp_ack       [ 1*db+: 1] }), +        .m_ctrlport_resp_status  ({ gpio_spi_ctrlport_resp_status   [ 2*db+: 2], +                                    radio_dio_resp_status           [ 2*db+: 2], +                                    gpio_atr_ctrlport_resp_status   [ 2*db+: 2], +                                    rf_ctrlport_resp_status         [ 2*db+: 2], +                                    m_radio_ctrlport_resp_status    [ 2*db+: 2] }), +        .m_ctrlport_resp_data    ({ gpio_spi_ctrlport_resp_data     [32*db+:32], +                                    radio_dio_resp_data             [32*db+:32], +                                    gpio_atr_ctrlport_resp_data     [32*db+:32], +                                    rf_ctrlport_resp_data           [32*db+:32], +                                    m_radio_ctrlport_resp_data      [32*db+:32] })        );        // Compute ATR state for this radio @@ -459,19 +521,37 @@ module x4xx_core_common #(        ) x4xx_gpio_atr_i (          .ctrlport_clk             (radio_clk),          .ctrlport_rst             (radio_rst), -        .s_ctrlport_req_wr        (gpio_atr_ctrlport_req_wr), -        .s_ctrlport_req_rd        (gpio_atr_ctrlport_req_rd), -        .s_ctrlport_req_addr      (gpio_atr_ctrlport_req_addr), -        .s_ctrlport_req_data      (gpio_atr_ctrlport_req_data), -        .s_ctrlport_resp_ack      (gpio_atr_ctrlport_resp_ack), -        .s_ctrlport_resp_status   (gpio_atr_ctrlport_resp_status), -        .s_ctrlport_resp_data     (gpio_atr_ctrlport_resp_data), +        .s_ctrlport_req_wr        (gpio_atr_ctrlport_req_wr       [ 1*db+: 1]), +        .s_ctrlport_req_rd        (gpio_atr_ctrlport_req_rd       [ 1*db+: 1]), +        .s_ctrlport_req_addr      (gpio_atr_ctrlport_req_addr     [20*db+:20]), +        .s_ctrlport_req_data      (gpio_atr_ctrlport_req_data     [32*db+:32]), +        .s_ctrlport_resp_ack      (gpio_atr_ctrlport_resp_ack     [ 1*db+: 1]), +        .s_ctrlport_resp_status   (gpio_atr_ctrlport_resp_status  [ 2*db+: 2]), +        .s_ctrlport_resp_data     (gpio_atr_ctrlport_resp_data    [32*db+:32]),          .db_state                 (db_state),          .gpio_in                  ({4'b0, gpio_in_b, 4'b0, gpio_in_a}),          .gpio_out                 (atr_gpio_out[db*32+: 32]),          .gpio_ddr                 (atr_gpio_ddr[db*32+: 32])        ); +      x4xx_gpio_spi #( +        .NUM_SLAVES (2) +      ) x4xx_gpio_spi_i( +        .ctrlport_clk             (radio_clk), +        .ctrlport_clk_2x          (radio_clk_2x), +        .ctrlport_rst             (radio_rst), +        .s_ctrlport_req_wr        (gpio_spi_ctrlport_req_wr       [ 1*db+: 1]), +        .s_ctrlport_req_rd        (gpio_spi_ctrlport_req_rd       [ 1*db+: 1]), +        .s_ctrlport_req_addr      (gpio_spi_ctrlport_req_addr     [20*db+:20]), +        .s_ctrlport_req_data      (gpio_spi_ctrlport_req_data     [32*db+:32]), +        .s_ctrlport_resp_ack      (gpio_spi_ctrlport_resp_ack     [ 1*db+: 1]), +        .s_ctrlport_resp_status   (gpio_spi_ctrlport_resp_status  [ 2*db+: 2]), +        .s_ctrlport_resp_data     (gpio_spi_ctrlport_resp_data    [32*db+:32]), +        .gpio_out                 (spi_gpio_out[db*32+: 32]), +        .gpio_ddr                 (spi_gpio_ddr[db*32+: 32]), +        .gpio_in                  ({4'b0, gpio_in_b, 4'b0, gpio_in_a}) +      ); +      end    endgenerate @@ -686,10 +766,10 @@ module x4xx_core_common #(      .atr_gpio_ddr                 (atr_gpio_ddr),      .ps_gpio_out                  ({4'b0, ps_gpio_out_b, 4'b0, ps_gpio_out_a}),      .ps_gpio_ddr                  ({4'b0, ps_gpio_ddr_b, 4'b0, ps_gpio_ddr_a}), -    .digital_ifc_gpio_out_radio0  (32'b0), -    .digital_ifc_gpio_ddr_radio0  (32'b0), -    .digital_ifc_gpio_out_radio1  (32'b0), -    .digital_ifc_gpio_ddr_radio1  (32'b0), +    .digital_ifc_gpio_out_radio0  (spi_gpio_out[31:0]), +    .digital_ifc_gpio_ddr_radio0  (spi_gpio_ddr[31:0]), +    .digital_ifc_gpio_out_radio1  (spi_gpio_out[63:32]), +    .digital_ifc_gpio_ddr_radio1  (spi_gpio_ddr[63:32]),      .user_app_in_a                (gpio_in_fabric_a),      .user_app_in_b                (gpio_in_fabric_b),      .user_app_out_a               (gpio_out_fabric_a), @@ -771,6 +851,10 @@ endmodule  //    <window name="DIO_SOURCE_CONTROL"      offset="0x1000" size="0x1000" targetregmap="DIO_REGMAP">  //      <info>Window to access the DIO register map through the control port from the radio blocks.</info>  //    </window> +//    <window name="DIGITAL_IFC_REGS"      offset="0x2000" size="0x1000" targetregmap="DIG_IFC_REGMAP"> +//      <info>Register space reserved for configuring a digital interface over the GPIO lines. +//            Currently, SPI is the only supported protocol.</info> +//    </window>  //  </group>  //</regmap> diff --git a/fpga/usrp3/top/x400/x4xx_gpio_atr.v b/fpga/usrp3/top/x400/x4xx_gpio_atr.v index 98ba881f3..86e1a6afe 100644 --- a/fpga/usrp3/top/x400/x4xx_gpio_atr.v +++ b/fpga/usrp3/top/x400/x4xx_gpio_atr.v @@ -312,13 +312,13 @@ endmodule  //      <info>  //        Controls whether GPIO lines use the TX and RX state of an RF channel  //        (Classic ATR) or the daughterboard state the selector for the -//        @.GPIO_ATR_STATE. +//        @.ATR_STATE.  //      </info>  //      <bitfield name="ATR_OPTION" range="0" initialvalue="0">  //        <info>  //          Sets the scheme in which RF states in the radio will control GPIO  //          lines. 0 = DB state is used. RF states are combined and the -//          GPIO state is driven based on all 16 @.GPIO_ATR_STATE registers. +//          GPIO state is driven based on all 16 @.ATR_STATE registers.  //          1 = Each RF channel has its separate ATR state(Classic ATR).  //          Use register @.CLASSIC_ATR_CONFIG to indicate the RF channel  //          to which each GPIO line responds to. diff --git a/fpga/usrp3/top/x400/x4xx_gpio_spi.v b/fpga/usrp3/top/x400/x4xx_gpio_spi.v new file mode 100644 index 000000000..b5866f867 --- /dev/null +++ b/fpga/usrp3/top/x400/x4xx_gpio_spi.v @@ -0,0 +1,534 @@ +// +// Copyright 2021 Ettus Research, A National Instruments Brand +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Module: x4xx_gpio_spi +// +// Description: +// +//   This block enables control of a SPI master engine via CtrlPort +//   transactions. +//   It also enables customization on how signals from the SPI buses +//   connected to the master are mapped to the GPIO Ports. +//   This block supports configuring communication to up to 4 SPI slaves. +// +// Parameters: +// +//   NUM_SLAVES     : Number of SPI slaves to be supported. Values from 1 to 4 +//                    are supported. SPI transfers can only target one slave +//                    at a time. +//   BASE_ADDRESS   : Start address for this register block. +//   SIZE_ADDRESS   : Size of the CtrlPort window to consider in this block. +// + +`default_nettype none + + +module x4xx_gpio_spi #( +  parameter         NUM_SLAVES  = 4, +  parameter [19:0]  BASE_ADDRESS = 0, +  parameter [19:0]  SIZE_ADDRESS = 19'h20 +) ( +  input wire ctrlport_clk, +  input wire ctrlport_clk_2x, +  input wire ctrlport_rst, + +  // Request +  input wire        s_ctrlport_req_wr, +  input wire        s_ctrlport_req_rd, +  input wire [19:0] s_ctrlport_req_addr, +  input wire [31:0] s_ctrlport_req_data, + +  // Response +  output reg        s_ctrlport_resp_ack     = 1'b0, +  output reg [ 1:0] s_ctrlport_resp_status  = 2'b0, +  output reg [31:0] s_ctrlport_resp_data    = 32'b0, + +  // GPIO control/status +  output wire  [31:0] gpio_out, +  output wire  [31:0] gpio_ddr, +  input  wire  [31:0] gpio_in +); + +  `include "../../lib/rfnoc/core/ctrlport.vh" +  `include "regmap/dig_ifc_regmap_utils.vh" + +  // Registers / wires for SPI core communication +  reg  [31:0] set_data = 0; +  reg  [ 7:0] set_addr = 0; +  reg         set_stb  = 1'b0; + +  wire [31:0] readback; +  wire        readback_stb; +  wire        readback_stb_extended; + +  wire       sclk; +  wire       mosi; +  wire       miso; +  // This array is set to the maximum supported SPI slaves instead of +  // the provided NUM_SLAVES to facilitate concurrent re-mapping. +  // See section(GPIO Mapping) of this file. +  wire [3:0] ss; + +  // Auxiliary signals to compute which GPIO lines are outputs +  reg  [31:0] gpio_is_mosi = 32'b0; +  reg  [31:0] gpio_is_sclk = 32'b0; +  reg  [31:0] gpio_is_cs   = 32'b0; + +  // SPI-to-GPIO mapping signals. +  // These arrays are set to the maximum supported SPI slaves instead of +  // the provided NUM_SLAVES to facilitate concurrent re-mapping. +  // See section(GPIO Mapping) of this file. +  reg [ SLAVE_CLK_SIZE-1:0] sclk_mapping [3:0]; +  reg [SLAVE_MOSI_SIZE-1:0] mosi_mapping [3:0]; +  reg [SLAVE_MISO_SIZE-1:0] miso_mapping [3:0]; +  reg [  SLAVE_CS_SIZE-1:0] ss_mapping   [3:0]; + +  //--------------------------------------------------------------------------- +  // Address calculation +  //--------------------------------------------------------------------------- + +  wire address_in_range = +    (s_ctrlport_req_addr >= BASE_ADDRESS) && +    (s_ctrlport_req_addr < BASE_ADDRESS + SIZE_ADDRESS); + +  // Check that address is targeting slave configuration. +  wire address_is_slave = +    (s_ctrlport_req_addr >= BASE_ADDRESS + SPI_SLAVE_CONFIG(0)) && +    (s_ctrlport_req_addr <= BASE_ADDRESS + SPI_SLAVE_CONFIG(3)); + +  // Decode the slave being addressed. +  wire [1:0]slave_address = s_ctrlport_req_addr[3:2]; + +  //--------------------------------------------------------------------------- +  // Slave configuration signals +  //--------------------------------------------------------------------------- + +  // These settings are registered individually for each slave +  reg [     NUM_SLAVES-1:0] data_in_edge     = {NUM_SLAVES{1'b0}}; +  reg [     NUM_SLAVES-1:0] data_out_edge    = {NUM_SLAVES{1'b0}}; +  reg [SPI_LENGTH_SIZE-1:0] slave_spi_length   [NUM_SLAVES-1:0]; + +  // One-hot encoding to indicate active slave +  reg [NUM_SLAVES-1:0] slave_select     = {NUM_SLAVES{1'b0}}; + +  //--------------------------------------------------------------------------- +  // FSM to handle transfers +  //--------------------------------------------------------------------------- + +  localparam IDLE            = 3'd0; +  localparam SET_DIVIDER     = 3'd1; +  localparam WRITE_SPI       = 3'd2; +  localparam CONFIG_TRANSFER = 3'd3; +  localparam WAIT_SPI        = 3'd4; + +  localparam DIVIDER_ADDRESS    = 8'd0; +  localparam CTRL_ADDRESS       = 8'd1; +  localparam DATA_ADDRESS       = 8'd2; + +  reg [                 2:0] state        = IDLE; +  reg [                31:0] data_cache; +  reg [SPI_CLK_DIV_SIZE-1:0] divider; +  reg [                 1:0] cs; +  reg                        spi_go       = 1'b0; +  reg                        spi_ready    = 1'b0; + +  integer slave_i; + +  //--------------------------------------------------------------------------- +  // CtrlPort Register endpoints +  //--------------------------------------------------------------------------- + +  always @ (posedge ctrlport_clk) begin + +    if (ctrlport_rst) begin +      s_ctrlport_resp_ack <= 1'b0; +      spi_go              <= 1'b0; +      spi_ready           <= 1'b0; +      divider             <= {SPI_CLK_DIV_SIZE{1'b0}}; +      cs                  <= 2'b0; + +      // Assigned to unassigned mapping. This avoids overwriting +      // signals with those from uninitialized slaves. +      for (slave_i=0; slave_i<4; slave_i=slave_i+1) begin +        sclk_mapping[slave_i] <= 5'h31; +        mosi_mapping[slave_i] <= 5'h31; +        miso_mapping[slave_i] <= 5'h31; +        ss_mapping  [slave_i] <= 5'h31; +      end + +      for (slave_i=0; slave_i<NUM_SLAVES; slave_i=slave_i+1) begin +        slave_spi_length[slave_i] <= {SPI_LENGTH_SIZE{1'b0}}; +      end +    end else begin + +      // Default assignments +      s_ctrlport_resp_ack <= 1'b0; +      spi_go              <= 1'b0; + +      // Requests appear +      if (s_ctrlport_req_wr) begin +        s_ctrlport_resp_ack     <= 1'b1; +        s_ctrlport_resp_data    <= {32{1'bx}}; +        s_ctrlport_resp_status  <= CTRL_STS_OKAY; + +        // Address spi configuration writes +        if(address_is_slave) begin +          // GPIO mapping +          sclk_mapping     [slave_address] <= s_ctrlport_req_data[SLAVE_CLK_MSB:SLAVE_CLK]; +          mosi_mapping     [slave_address] <= s_ctrlport_req_data[SLAVE_MOSI_MSB:SLAVE_MOSI]; +          miso_mapping     [slave_address] <= s_ctrlport_req_data[SLAVE_MISO_MSB:SLAVE_MISO]; +          ss_mapping       [slave_address] <= s_ctrlport_req_data[SLAVE_CS_MSB:SLAVE_CS]; +          // Transfer Configuration +          slave_spi_length [slave_address] <= s_ctrlport_req_data[SPI_LENGTH_MSB:SPI_LENGTH]; +          data_in_edge     [slave_address] <= s_ctrlport_req_data[MISO_EDGE]; +          data_out_edge    [slave_address] <= s_ctrlport_req_data[MOSI_EDGE]; +        end else begin + +          case (s_ctrlport_req_addr) +            BASE_ADDRESS + SPI_TRANSACTION_CONFIG: begin +              divider <= s_ctrlport_req_data[SPI_CLK_DIV_MSB:SPI_CLK_DIV]; +              cs      <= s_ctrlport_req_data[SPI_SLAVE_SELECT_MSB:SPI_SLAVE_SELECT]; +            end + +            BASE_ADDRESS + SPI_TRANSACTION_GO: begin +              spi_ready  <= 1'b0; +              spi_go     <= 1'b1; +            end + +            // No register implementation for provided address +            default: begin +              // Acknowledge and provide error status if address is in range +              if (address_in_range) begin +                s_ctrlport_resp_status <= CTRL_STS_CMDERR; + +              // No response if out of range +              end else begin +                s_ctrlport_resp_ack <= 1'b0; +              end +            end + +          endcase +        end + +      end else if(s_ctrlport_req_rd) begin +        // default assumption: valid request +        s_ctrlport_resp_ack     <= 1'b1; +        s_ctrlport_resp_status  <= CTRL_STS_OKAY; +        s_ctrlport_resp_data    <= {32{1'b0}}; + +        case (s_ctrlport_req_addr) +          BASE_ADDRESS + SPI_TRANSACTION_CONFIG: begin +            s_ctrlport_resp_data[SPI_CLK_DIV_MSB:SPI_CLK_DIV] <= divider; +          end + +          BASE_ADDRESS + SPI_STATUS: begin +            s_ctrlport_resp_data[SPI_READY]                     <= spi_ready; +            s_ctrlport_resp_data[SPI_RESPONSE_MSB:SPI_RESPONSE] <= readback[SPI_RESPONSE_MSB:SPI_RESPONSE]; +          end + +          // No register implementation for provided address +          default: begin +            // Acknowledge and provide error status if address is in range +            if (address_in_range) begin +              s_ctrlport_resp_status <= CTRL_STS_CMDERR; + +            // No response if out of range +            end else begin +              s_ctrlport_resp_ack <= 1'b0; +            end +          end + +        endcase +      end + +      if (readback_stb_extended) begin +        spi_ready <= 1'b1; +      end +    end + +  end + +  //--------------------------------------------------------------------------- +  // SPI Control FSM +  //--------------------------------------------------------------------------- + +  always @ (posedge ctrlport_clk) begin +    if (ctrlport_rst) begin +      state         <= IDLE; +      set_stb       <= 1'b0; +      data_cache    <= 32'h0; +    end else begin + +      // Default Assignments +      set_stb             <= 1'b0; + +      case (state) +        IDLE: begin +          // Save data and address for further steps +          data_cache    <= s_ctrlport_req_data; +          if (spi_go) begin +            state            <= CONFIG_TRANSFER; + +            slave_select     <= {NUM_SLAVES{1'b0}}; +            slave_select[cs] <= 1'b1; +          end +        end + +        // Set slave select +        CONFIG_TRANSFER: begin +          state    <= SET_DIVIDER; + +          set_stb  <= 1'b1; +          set_addr <= CTRL_ADDRESS; +          set_data <= { data_out_edge[cs],      // 1 bit +                        data_in_edge[cs],       // 1 bit +                        slave_spi_length[cs],   // 6 bits +                        {24-NUM_SLAVES{1'b0}},  // Padding for slaves +                        slave_select            // NUM_SLAVES bits +                      }; +        end + +        // Write divider to SPI core +        SET_DIVIDER: begin +          state    <= WRITE_SPI; + +          set_stb  <= 1'b1; +          set_addr <= DIVIDER_ADDRESS; +          set_data <= {16'b0, divider}; +        end + +        // Write data bits to SPI core (aligned to MSB) +        WRITE_SPI: begin +          state    <= WAIT_SPI; + +          set_stb  <= 1'b1; +          set_addr <= DATA_ADDRESS; +          set_data <= data_cache; +        end + +        // Wait for transaction to complete and translate to ctrlport response +        WAIT_SPI: begin + +          if (readback_stb_extended) begin +            state     <= IDLE; +          end +        end + +        default: begin +          state <= IDLE; +        end +      endcase + +      // Update Auxiliary signals +      gpio_is_mosi  <= 32'h0; +      gpio_is_sclk  <= 32'h0; +      gpio_is_cs    <= 32'h0; + +      for (slave_i=0; slave_i<NUM_SLAVES; slave_i=slave_i+1) begin +        gpio_is_mosi  [mosi_mapping[slave_i]] <= 1'b1; +        gpio_is_sclk  [sclk_mapping[slave_i]] <= 1'b1; +        gpio_is_cs    [  ss_mapping[slave_i]] <= 1'b1; +      end + +    end +  end + + +  //--------------------------------------------------------------------------- +  // SPI master +  //--------------------------------------------------------------------------- + +  //  Register set_stb for use in 2x domain. +  reg set_stb_2x = 1'b0; +  reg ctrlport_clk_phase = 1'b0; + +  always @ (posedge ctrlport_clk_2x) begin +    // Assert strobe only during a single 2x cycle of the +    // 1x pulse. +    set_stb_2x         <= ctrlport_clk_phase & set_stb; +    ctrlport_clk_phase <= ~ctrlport_clk_phase; +  end + +  simple_spi_core #( +    .BASE     (0), +    .WIDTH    (NUM_SLAVES), +    .CLK_IDLE (0), +    .SEN_IDLE ({NUM_SLAVES{1'b1}}) +  ) simple_spi_core_i ( +    .clock        (ctrlport_clk_2x), +    .reset        (ctrlport_rst), +    .set_stb      (set_stb_2x), +    .set_addr     (set_addr), +    .set_data     (set_data), +    .readback     (readback), +    .readback_stb (readback_stb), +    .ready        (), +    .sen          (ss[NUM_SLAVES-1:0]), +    .sclk         (sclk), +    .mosi         (mosi), +    .miso         (miso), +    .debug        () +  ); + +  // Delay and extend signal for use in 1x domain. +  reg readback_stb_dly = 1'b0; + +  always @ (posedge ctrlport_clk_2x) begin +    readback_stb_dly <= readback_stb; +  end + +  assign readback_stb_extended = readback_stb_dly | readback_stb; + +  //--------------------------------------------------------------------------- +  // GPIO Mapping +  //--------------------------------------------------------------------------- + +  wire [31:0] mosi_mux_out; +  reg  [31:0] mosi_mux_out_dlyd; +  wire [31:0] ss_mux_out; +  wire [31:0] gated_sclk; +  reg  [31:0] gated_sclk_dlyd; +  reg  [31:0] gpio_is_sclk_dlyd; + +  genvar i; +  generate + +    for (i = 0; i < 32; i = i + 1) begin: dio_output_gen + +      // Indicate which GPIO lines are outputs +      assign gpio_ddr[i] = gpio_is_mosi[i] | gpio_is_sclk[i] | gpio_is_cs[i]; + +      // CS re-mapping +      assign ss_mux_out[i] =  ( i == ss_mapping[0] ) ? ss[0] : +                              ( i == ss_mapping[1] ) ? ss[1] : +                              ( i == ss_mapping[2] ) ? ss[2] : +                              ( i == ss_mapping[3] ) ? ss[3] : +                              1'b0; + +      assign mosi_mux_out[i] = gpio_is_mosi[i] ? mosi : ss_mux_out[i]; +      assign gated_sclk[i]   = gpio_is_sclk[i] ? sclk : 1'b0; + +      // register signals once remapping logic is resolved +      always @ (posedge ctrlport_clk_2x) begin +        mosi_mux_out_dlyd[i] <= mosi_mux_out[i]; +        gpio_is_sclk_dlyd[i] <= gpio_is_sclk[i]; +        gated_sclk_dlyd[i]   <= gated_sclk[i]; +      end + +      // Choose between SCLK and MOSI/SS mux. +      glitch_free_mux glitch_free_gpio_out ( +        .select       (gpio_is_sclk_dlyd[i]), +        .signal0      (mosi_mux_out_dlyd[i]), +        .signal1      (gated_sclk_dlyd[i]), +        .muxed_signal (gpio_out[i]) +      ); + +    end +  endgenerate + +  assign miso = ( ~ss[0] ) ? gpio_in[miso_mapping[0]] : +                ( ~ss[1] ) ? gpio_in[miso_mapping[1]] : +                ( ~ss[2] ) ? gpio_in[miso_mapping[2]] : +                ( ~ss[3] ) ? gpio_in[miso_mapping[3]] : +                1'b0; + + +endmodule + + +`default_nettype wire + +//XmlParse xml_on +//<regmap name="DIG_IFC_REGMAP" readablestrobes="false" generatevhdl="true" ettusguidelines="true"> +//  <group name="SPI_OVER_GPIO_REGS"> +//    <info> +//    </info> +//    <regtype name="SPI_SETUP" size="32"> +//      <info> +//        Controls SPI Transaction +//      </info> +//      <bitfield name="SLAVE_CLK"  range="0..4"   initialvalue="0"> +//        <info> +//          Indicates which GPIO line to use for the SCLK signal.</br> +//            0-11 : Port A GPIO</br> +//            16-27: Port B GPIO +//        </info> +//      </bitfield> +//      <bitfield name="SLAVE_MOSI" range="5..9"   initialvalue="0"> +//        <info> +//          Indicates which GPIO line to use for the MOSI signal.</br> +//            0-11 : Port A GPIO</br> +//            16-27: Port B GPIO +//        </info> +//      </bitfield> +//      <bitfield name="SLAVE_MISO" range="10..14" initialvalue="0"> +//        <info> +//          Indicates which GPIO line to use for the MISO signal.</br> +//            0-11 : Port A GPIO</br> +//            16-27: Port B GPIO +//        </info> +//      </bitfield> +//      <bitfield name="SLAVE_CS"   range="15..19" initialvalue="0"> +//        <info> +//          Indicates which GPIO line to use for the CS signal.</br> +//            0-11 : Port A GPIO</br> +//            16-27: Port B GPIO +//        </info> +//      </bitfield> +//      <bitfield name="SPI_LENGTH" range="20..25" initialvalue="0"> +//        <info> +//          Indicates the length of SPI transactions to this slave. +//        </info> +//      </bitfield> +//      <bitfield name="MISO_EDGE"  range="26"     initialvalue="0"> +//        <info> +//          Controls the edge in which the MISO line is latched.</br> +//            0 =  falling edge of SCLK.</br> +//            1 =  rising edge of SCLK. +//        </info> +//      </bitfield> +//      <bitfield name="MOSI_EDGE"  range="27"     initialvalue="0"> +//        <info> +//          Controls the edge in which the MOSI line is updated.</br> +//            0 =  falling edge of SCLK.</br> +//            1 =  rising edge of SCLK. +//        </info> +//      </bitfield> +//    </regtype> +//    <register name="SPI_SLAVE_CONFIG" typename="SPI_SETUP"  offset="0x00" count="4" options="--step 4"> +//      <info> Set of configuration registers for the supported slaves. </info> +//    </register> +//    <register name="SPI_TRANSACTION_CONFIG" offset="0x10" size="32"> +//      <info> +//        Controls clock rate and target for subsequent SPI transactions. +//      </info> +//      <bitfield name="SPI_CLK_DIV"      range="0..15"  initialvalue="0"> +//        <info> Controls the rate for subsequent SPI transactions. SCLK = DataClk/[(SPI_CLK_DIV+1)]</info> +//      </bitfield> +//      <bitfield name="SPI_SLAVE_SELECT" range="16..17" initialvalue="0"/> +//    </register> +//    <register name="SPI_TRANSACTION_GO" offset="0x14" size="32" readable="false"> +//      <info> +//        Starts a SPI transaction +//      </info> +//      <bitfield name="SPI_DATA"         range="0..31"  initialvalue="0"> +//        <info> Payload to be sent for the SPI transaction. If the payload is shorter than 32 bits, +//               it must be aligned to the MSbs in this field. LSbs are ignored in this scenario.</info> +//      </bitfield> +//    </register> +//    <register name="SPI_STATUS" offset="0x18" size="32" writable="false"> +//      <info> +//        Contains the status of the SPI engine. +//      </info> +//      <bitfield name="SPI_READY"        range="24"     initialvalue="0"> +//        <info> Indicates the SPI engine is ready to start a new SPI transaction. </info> +//      </bitfield> +//      <bitfield name="SPI_RESPONSE"     range="0..23"  initialvalue="0"> +//        <info> Records the response of the last completed SPI transaction. </info> +//      </bitfield> +//    </register> +//  </group> +//</regmap> +//XmlParse xml_off  | 
