From d7304cc724de43b0d61d5b9d61a528d58898f004 Mon Sep 17 00:00:00 2001 From: eklai Date: Thu, 23 Jan 2020 18:47:28 -0800 Subject: x300: add front-panel GPIO source control Adds a ZPU register to control the FP GPIO source. These are 2bits per GPIO pin, totalling 24 bits. 0 corresponds to RF-A, 1 corresponds to RF-B. The following Python code will control the upper 6 bits of the front-panel GPIO from the B-side radio on an X300: >>> import uhd >>> U = uhd.usrp.MultiUSRP("type=x300") >>> U.get_gpio_src_banks() ['FP0'] >>> U.get_gpio_src("FP0") ['RFA', 'RFA', 'RFA', 'RFA', 'RFA', 'RFA', 'RFA', 'RFA', 'RFA', 'RFA', 'RFA', 'RFA'] >>> U.set_gpio_src("FP0", ['RFA', 'RFA', 'RFA', 'RFA', 'RFA', 'RFA', 'RFB', 'RFB', 'RFB', 'RFB', 'RFB', 'RFB']) >>> U.get_gpio_src("FP0") ['RFA', 'RFA', 'RFA', 'RFA', 'RFA', 'RFA', 'RFB', 'RFB', 'RFB', 'RFB', 'RFB', 'RFB'] >>> # Make all GPIOs outputs: >>> U.set_gpio_attr("FP0A", "DDR", 0xFFF) >>> U.set_gpio_attr("FP0B", "DDR", 0xFFF) >>> # Control all GPIOs from software (not ATR): >>> U.set_gpio_attr("FP0A", "CTRL", 0x000) >>> U.set_gpio_attr("FP0B", "CTRL", 0x000) >>> # Bottom 3 pins go high from radio A >>> U.set_gpio_attr("FP0A", "OUT", 0x007) >>> # Top 3 pins go high from radio B >>> U.set_gpio_attr("FP0B", "OUT", 0xE00) Amends the gpio.cpp example to allow switching the source. Co-authored-by: Brent Stapleton --- fpga/usrp3/top/x300/x300_core.v | 39 +++++++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-) (limited to 'fpga/usrp3/top/x300/x300_core.v') diff --git a/fpga/usrp3/top/x300/x300_core.v b/fpga/usrp3/top/x300/x300_core.v index 0a721e06b..5665c397f 100644 --- a/fpga/usrp3/top/x300/x300_core.v +++ b/fpga/usrp3/top/x300/x300_core.v @@ -1,6 +1,7 @@ // // Copyright 2014 Ettus Research LLC // Copyright 2017 Ettus Research, a National Instruments Company +// Copyright 2020 Ettus Research, a National Instruments Brand // // SPDX-License-Identifier: LGPL-3.0-or-later // @@ -21,7 +22,7 @@ module x300_core #( // Radio 0 input [31:0] rx0, output [31:0] tx0, input [31:0] db0_gpio_in, output [31:0] db0_gpio_out, output [31:0] db0_gpio_ddr, - input [31:0] fp_gpio_in, output [31:0] fp_gpio_out, output [31:0] fp_gpio_ddr, + input [31:0] fp_gpio_in, output reg [31:0] fp_gpio_out, output reg [31:0] fp_gpio_ddr, output [7:0] sen0, output sclk0, output mosi0, input miso0, output [2:0] radio_led0, output reg [31:0] radio0_misc_out, input [31:0] radio0_misc_in, @@ -311,6 +312,8 @@ module x300_core #( // SFP 1 .SFPP1_ModAbs(SFPP1_ModAbs),.SFPP1_TxFault(SFPP1_TxFault),.SFPP1_RxLOS(SFPP1_RxLOS), .SFPP1_RS0(SFPP1_RS0), .SFPP1_RS1(SFPP1_RS1), + // Front-panel GPIO source + .fp_gpio_src(sr_fp_gpio_src), //clocky locky misc .clock_status({misc_clock_status, pps_detect, LMK_Holdover, LMK_Lock, LMK_Status}), .clock_control({1'b0, clock_misc_opt[1:0], pps_out_enb, pps_select[1:0], clock_ref_sel[1:0]}), @@ -528,6 +531,7 @@ module x300_core #( wire [31:0] db_gpio_in[0:NUM_DBOARDS-1], db_gpio_out[0:NUM_DBOARDS-1], db_gpio_ddr[0:NUM_DBOARDS-1]; wire [31:0] misc_outs[0:NUM_DBOARDS-1]; reg [31:0] misc_ins[0:NUM_DBOARDS-1]; + wire [24:0] sr_fp_gpio_src, fp_gpio_src; wire [7:0] sen[0:NUM_DBOARDS-1]; wire sclk[0:NUM_DBOARDS-1], mosi[0:NUM_DBOARDS-1], miso[0:NUM_DBOARDS-1]; wire rx_running[0:NUM_CHANNELS-1], tx_running[0:NUM_CHANNELS-1]; @@ -601,6 +605,34 @@ module x300_core #( end endgenerate + //------------------------------------ + // Front-Panel GPIO Source Mux + //------------------------------------ + // Number of FP GPIO Pins + localparam FP_GPIO_WIDTH = 12; + + // Bring FP GPIO controls into radio clk domain + synchronizer #(.WIDTH(24)) fp_gpio_sync ( + .clk(radio_clk), .rst(radio_rst), .in(sr_fp_gpio_src), .out(fp_gpio_src) + ); + + // For each bit in the front-panel GPIO, mux the output and the direction + // control bit based on the fp_gpio_src register. The fp_gpio_src register + // holds 2 bits per GPIO pin, which selects which source to use for GPIO + // control. Currently, only daughter board 0 and daughter board 1 are + // supported. + for (i=0; i