summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJacob Corder <jacob@privateisland.tech>2026-07-01 15:48:33 -0400
committerJacob Corder <jacob@privateisland.tech>2026-07-01 15:48:33 -0400
commit74da990c9d1d38155f74a339939c7352855662e9 (patch)
tree7b011ccc5d2953cdefffc65e9015d2004df28150
parent6e0b5af5c789ca6fc3fa6d28300e30d9b3803e76 (diff)
gpio: first pass changes to support new GPIO daughter boardgpio
-rw-r--r--manufacturer/altera/cyclone10_lp/src/betsy.v81
-rw-r--r--src/controller.v61
2 files changed, 121 insertions, 21 deletions
diff --git a/manufacturer/altera/cyclone10_lp/src/betsy.v b/manufacturer/altera/cyclone10_lp/src/betsy.v
index ccefd3b..c388429 100644
--- a/manufacturer/altera/cyclone10_lp/src/betsy.v
+++ b/manufacturer/altera/cyclone10_lp/src/betsy.v
@@ -21,8 +21,9 @@
*/
// `define PASSTHROUGH
-`define PHY2_PRESENT
-
+//`define PHY2_PRESENT
+`define GPIO_PRESENT
+
module betsy (
input rstn,
input clk_i, // 25Mhz
@@ -70,6 +71,13 @@ module betsy (
input phy1_intn,
inout [1:0] phy1_gpio,
+//====================================
+// Replaced PHY2 to GPIO if deteced.
+// If not replaced, PHY2 continues.
+//====================================
+`ifdef GPIO_PRESENT
+ inout [19:0] gpio,
+`else
// PHY2 RGMII
output phy2_rstn,
@@ -86,6 +94,7 @@ module betsy (
input phy2_intn,
inout [1:0] phy2_gpio,
+`endif
// FLASH
output flash_clk,
@@ -111,6 +120,18 @@ module betsy (
reg sys_rstn;
wire cont_clk, clk_25, clk_125;
wire pclk; // main fabric clock for Ethernet pipeline
+
+// ============================================================
+// GPIO INTERNAL SIGNALS
+// These wires separate input, output, and direction control
+// for the bidirectional GPIO pins.
+// ============================================================
+`ifdef GPIO_PRESENT
+ wire [19:0] gpio_in;
+ wire [19:0] gpio_out;
+ wire [19:0] gpio_out_en;
+`endif
+
reg [3:0] cnt_init;
reg [25:0] heart_beat_cnt;
wire [NUM_PHYS-1:0] phy_up;
@@ -345,6 +366,23 @@ module betsy (
assign phy1_clk = clk_25;
assign pclk = clk_125;
+// ============================================================
+// GPIO CONTROL
+// Implements bidirectional behavior for GPIO pins.
+// If gpio_out_en[i] = 1 → pin drives gpio_out[i]
+// If gpio_out_en[i] = 0 → pin is high impedance (input mode)
+// ============================================================
+`ifdef GPIO_PRESENT
+ genvar i;
+ generate
+ for (i = 0; i < 20; i = i + 1) begin : gpio_tri
+ assign gpio[i] = gpio_out_en[i] ? gpio_out[i] : 1'bz;
+ end
+ endgenerate
+
+ assign gpio_in = gpio;
+`endif
+
always @(posedge cont_clk, negedge rstn)
if (!rstn)
cnt_init <= 4'd0;
@@ -362,12 +400,19 @@ module betsy (
// TODO: Review sequence and move to Controller control
assign phy0_rstn = sys_rstn;
assign phy1_rstn = pll_locked;
+
+`ifndef GPIO_PRESENT
assign phy2_rstn = pll_locked;
+`endif
// TODO: Fix this
assign phy_resetn = {pll_locked, pll_locked, pll_locked};
- assign phy_int = {~phy2_intn, ~phy1_intn, ~phy0_intn};
+`ifdef GPIO_PRESENT
+ assign phy_int = {1'b0, ~phy1_intn, ~phy0_intn}; // PHY2 slot tied off
+`else
+ assign phy_int = {~phy2_intn, ~phy1_intn, ~phy0_intn};
+`endif
// TODO: This will be replaced when the SPI master peripheral is ready
assign flash_d = 8'hab;
@@ -379,10 +424,14 @@ module betsy (
// TODO: Gate these when not in use
assign phy0_mdc = cont_clk;
assign phy1_mdc = cont_clk;
- assign phy2_mdc = cont_clk;
+`ifndef GPIO_PRESENT
+assign phy2_mdc = cont_clk;
+`endif
- assign phy2_gpio[0] = gpio_ipv4[0];
- assign phy2_gpio[1] = gpio_ipv4[1];
+`ifndef GPIO_PRESENT
+ assign phy2_gpio[0] = gpio_ipv4[0];
+ assign phy2_gpio[1] = gpio_ipv4[1];
+`endif
// Bits 3:0 on the positive edge of RX_CLK and bits 7:4 on the negative edge of RX_CLK.
@@ -400,12 +449,14 @@ module betsy (
.dataout_l ({rx1_ctl_i[1],rx1_d_i[7:4]})
);
- ddri rgmi_rx_2 (
- .datain ({phy2_rx_ctl, phy2_rx_d}),
- .inclock (phy2_rx_clk),
- .dataout_h ({rx2_ctl_i[0],rx2_d_i[3:0]}),
- .dataout_l ({rx2_ctl_i[1],rx2_d_i[7:4]})
+`ifndef GPIO_PRESENT
+ ddri rgmi_rx_2 (
+ .datain ({phy2_rx_ctl, phy2_rx_d}),
+ .inclock (phy2_rx_clk),
+ .dataout_h ({rx2_ctl_i[0],rx2_d_i[3:0]}),
+ .dataout_l ({rx2_ctl_i[1],rx2_d_i[7:4]})
);
+`endif
// Simple Pipeline to Make Timing
@@ -547,7 +598,13 @@ module betsy (
.phy_resetn(),
.mac_reset(mac_reset),
// Debug
+ `ifdef GPIO_PRESENT
+ .gpio_in(gpio_in),
+ .gpio_out(gpio_out),
+ .gpio_out_en(gpio_out_en)
+ `else
.gpio(gpio_controller)
+ `endif
);
@@ -1911,4 +1968,4 @@ module betsy (
assign fpga_led[1] = heart_beat_cnt[23];
assign fpga_led[2] = evt_toggle;
-endmodule
+endmodule \ No newline at end of file
diff --git a/src/controller.v b/src/controller.v
index e30d461..b0e7689 100644
--- a/src/controller.v
+++ b/src/controller.v
@@ -77,7 +77,17 @@ module controller #(parameter MDIO_ADDR_SZ = 7, parameter NUM_PHYS=3)
output reg [NUM_PHYS-1:0] mac_reset,
// Debug
- output [7:0] gpio
+// ===========================
+// GPIO INTERFACE
+// ===========================
+`ifdef GPIO_PRESENT
+ input [19:0] gpio_in,
+ output [19:0] gpio_out,
+ output [19:0] gpio_out_en
+`else
+ output [7:0] gpio
+`endif
+
);
`define INCLUDED
@@ -125,6 +135,13 @@ module controller #(parameter MDIO_ADDR_SZ = 7, parameter NUM_PHYS=3)
reg [3:0] mi_state; // mdio init state
reg [7:0] mdio_init_cnt;
reg [1:0] mdio_init_mux_sel;
+// ============================
+// GPIO REGISTERS
+// ============================
+`ifdef GPIO_PRESENT
+ reg [19:0] gpio_direction; //1 = output, 0 = input
+ reg [19:0] gpio_value;
+`endif
// metastability synchronizer regs
reg rx_fifo_int_m1, rx_fifo_int_m2;
@@ -323,8 +340,8 @@ module controller #(parameter MDIO_ADDR_SZ = 7, parameter NUM_PHYS=3)
else if (mem_state == MEM_ST_RD_FIFO && rx_cnt == 5'd11)
msg_data[7:0] <= mem_d_i[7:0];
- // msg_response
- always @(posedge clk, negedge rstn)
+ // msg_response
+ always @(posedge clk or negedge rstn)
if (!rstn)
msg_response <= 16'heeee;
else if (mem_state == MEM_ST_IDLE)
@@ -341,9 +358,14 @@ module controller #(parameter MDIO_ADDR_SZ = 7, parameter NUM_PHYS=3)
{MSG_MAC_ADDR[15:8],8'h??}: msg_response <= mem_d_i;
{MSG_MDIO_ADDR[15:8],8'h??}: msg_response <= mdio_d;
{MSG_MLE_ADDR[15:8],8'h??}: msg_response <= mem_d_i;
+`ifdef GPIO_PRESENT
+ 16'h0030: msg_response <= gpio_direction;
+ 16'h0034: msg_response <= gpio_value;
+ 16'h0038: msg_response <= gpio_in;
+`endif
default: msg_response <= mem_d_i[15:0];
- endcase
-
+ endcase
+
/***********************************************************************
*
@@ -388,7 +410,16 @@ module controller #(parameter MDIO_ADDR_SZ = 7, parameter NUM_PHYS=3)
// set mdio_phy_addr
assign mdio_phy_addr = 5'h00; // Set phy_addr[3:2]
-
+
+// =================================================
+// GPIO OUTPUT CONNECTIONS
+// Connect controller registers to GPIO interface
+// =================================================
+`ifdef GPIO_PRESENT
+ assign gpio_out = gpio_value;
+ assign gpio_out_en = gpio_direction;
+`endif
+
// set mdio_reg_addr
always @(posedge clk or negedge rstn)
begin
@@ -422,7 +453,8 @@ module controller #(parameter MDIO_ADDR_SZ = 7, parameter NUM_PHYS=3)
mdio_d <= 16'h0000;
else if (mdio_we)
mdio_d <= mdio_d_i;
- end
+ end
+
// PHY Reset
always @(posedge clk, negedge rstn)
@@ -704,6 +736,10 @@ module controller #(parameter MDIO_ADDR_SZ = 7, parameter NUM_PHYS=3)
mac_addr <= 2'd0;
mdio_mux_sel <= 2'b00;
pkt_filter_addr <= 16'd0;
+ `ifdef GPIO_PRESENT
+ gpio_direction <= 20'd0;
+ gpio_value <= 20'd0;
+ `endif
end
else if (rx_msg_captured && !msg_error && msg_type == MSG_TYPE_WRITE) begin
if (msg_addr==MAC_ADDR)
@@ -712,8 +748,15 @@ module controller #(parameter MDIO_ADDR_SZ = 7, parameter NUM_PHYS=3)
mdio_mux_sel <= msg_data[1:0];
else if (msg_addr==PKT_FILT_ADDR)
pkt_filter_addr <= msg_data[15:0];
+ `ifdef GPIO_PRESENT
+ else if (msg_addr == 16'h0030)
+ gpio_direction <= msg_data[19:0];
+ else if (msg_addr == 16'h0034)
+ gpio_value <= msg_data[19:0];
+ `endif
end
+
/***********************************************************************
*
* MDIO Initialization
@@ -793,7 +836,7 @@ module controller #(parameter MDIO_ADDR_SZ = 7, parameter NUM_PHYS=3)
/*
* Debug
*/
- assign gpio = 8'h00;
+
-endmodule
+endmodule \ No newline at end of file

Highly Recommended Verilog Books