Reorganize repository

Signed-off-by: Alex Forencich <alex@alexforencich.com>
This commit is contained in:
Alex Forencich
2025-05-18 12:25:59 -07:00
parent 8cdae180a1
commit 66b53d98a2
690 changed files with 2314 additions and 1581 deletions

View File

@@ -0,0 +1,81 @@
// SPDX-License-Identifier: CERN-OHL-S-2.0
/*
Copyright (c) 2014-2025 FPGA Ninja, LLC
Authors:
- Alex Forencich
*/
`resetall
`timescale 1ns / 1ps
`default_nettype none
/*
* Synchronizes switch and button inputs with a slow sampled shift register
*/
module taxi_debounce_switch #(
// width of the input and output signals
parameter WIDTH = 1,
// length of shift register
parameter N = 3,
// clock division factor
parameter RATE = 125000
)
(
input wire logic clk,
input wire logic rst,
input wire logic [WIDTH-1:0] in,
output wire logic [WIDTH-1:0] out
);
localparam CNT_W = $clog2(RATE);
logic [CNT_W-1:0] cnt_reg = '0;
logic strb_reg = 1'b0;
logic [N-1:0] debounce_reg[WIDTH-1:0];
logic [WIDTH-1:0] state_reg = '0;
assign out = state_reg;
always_ff @(posedge clk) begin
strb_reg <= 1'b0;
if (cnt_reg) begin
cnt_reg <= cnt_reg - 1;
end else begin
cnt_reg <= RATE-1;
strb_reg <= 1'b1;
end
if (strb_reg) begin
for (integer k = 0; k < WIDTH; k = k + 1) begin
debounce_reg[k] <= {debounce_reg[k][N-2:0], in[k]};
end
end
for (integer k = 0; k < WIDTH; k = k + 1) begin
if (|debounce_reg[k] == 0) begin
state_reg[k] <= 1'b0;
end else if (&debounce_reg[k] == 1) begin
state_reg[k] <= 1'b1;
end
end
if (rst) begin
cnt_reg <= '0;
state_reg <= '0;
for (integer k = 0; k < WIDTH; k = k + 1) begin
debounce_reg[k] <= '0;
end
end
end
endmodule
`resetall

157
src/io/rtl/taxi_iddr.sv Normal file
View File

@@ -0,0 +1,157 @@
// SPDX-License-Identifier: CERN-OHL-S-2.0
/*
Copyright (c) 2016-2025 FPGA Ninja, LLC
Authors:
- Alex Forencich
*/
`resetall
`timescale 1ns / 1ps
`default_nettype none
/*
* Generic IDDR module
*/
module taxi_iddr #
(
// simulation (set to avoid vendor primitives)
parameter logic SIM = 1'b0,
// vendor ("GENERIC", "XILINX", "ALTERA")
parameter string VENDOR = "XILINX",
// device family
parameter string FAMILY = "virtex7",
// Width of register in bits
parameter WIDTH = 1
)
(
input wire logic clk,
input wire logic [WIDTH-1:0] d,
output wire logic [WIDTH-1:0] q1,
output wire logic [WIDTH-1:0] q2
);
/*
Provides a consistent input DDR flip flop across multiple FPGA families
_____ _____ _____ _____ ____
clk ____/ \_____/ \_____/ \_____/ \_____/
_ _____ _____ _____ _____ _____ _____ _____ _____ _____ _
d _X_D0__X_D1__X_D2__X_D3__X_D4__X_D5__X_D6__X_D7__X_D8__X_
_______ ___________ ___________ ___________ ___________ _
q1 _______X___________X____D0_____X____D2_____X____D4_____X_
_______ ___________ ___________ ___________ ___________ _
q2 _______X___________X____D1_____X____D3_____X____D5_____X_
*/
if (!SIM && VENDOR == "XILINX") begin
// Xilinx/AMD device support
if (FAMILY == "spartan6") begin
// spartan6 uses IODDR2
for (genvar n = 0; n < WIDTH; n = n + 1) begin : iddr
wire q1_int;
logic q1_delay = 1'b0;
IDDR2 #(
.DDR_ALIGNMENT("C0")
)
iddr_inst (
.Q0(q1_int),
.Q1(q2[n]),
.C0(clk),
.C1(~clk),
.CE(1'b1),
.D(d[n]),
.R(1'b0),
.S(1'b0)
);
always_ff @(posedge clk) begin
q1_delay <= q1_int;
end
assign q1[n] = q1_delay;
end
end else begin
// virtex4, virtex5, virtex6, virtex7, kintex7, artix7, virtexu, kintexu, virtexuplus, kintexuplus
for (genvar n = 0; n < WIDTH; n = n + 1) begin : iddr
IDDR #(
.DDR_CLK_EDGE("SAME_EDGE_PIPELINED"),
.SRTYPE("ASYNC")
)
iddr_inst (
.Q1(q1[n]),
.Q2(q2[n]),
.C(clk),
.CE(1'b1),
.D(d[n]),
.R(1'b0),
.S(1'b0)
);
end
end
end else if (!SIM && VENDOR == "ALTERA") begin
// Altera/Intel/Altera device support
wire [WIDTH-1:0] q1_int;
logic [WIDTH-1:0] q1_delay = '0;
altddio_in #(
.WIDTH(WIDTH),
.POWER_UP_HIGH("OFF")
)
altddio_in_inst (
.aset(1'b0),
.datain(d),
.inclocken(1'b1),
.inclock(clk),
.aclr(1'b0),
.dataout_h(q1_int),
.dataout_l(q2)
);
always_ff @(posedge clk) begin
q1_delay <= q1_int;
end
assign q1 = q1_delay;
end else begin
// generic/simulation implementation (no vendor primitives)
logic [WIDTH-1:0] d_reg_1 = '0;
logic [WIDTH-1:0] d_reg_2 = '0;
logic [WIDTH-1:0] q_reg_1 = '0;
logic [WIDTH-1:0] q_reg_2 = '0;
always_ff @(posedge clk) begin
d_reg_1 <= d;
end
always_ff @(negedge clk) begin
d_reg_2 <= d;
end
always_ff @(posedge clk) begin
q_reg_1 <= d_reg_1;
q_reg_2 <= d_reg_2;
end
assign q1 = q_reg_1;
assign q2 = q_reg_2;
end
endmodule
`resetall

155
src/io/rtl/taxi_led_sreg.sv Normal file
View File

@@ -0,0 +1,155 @@
// SPDX-License-Identifier: CERN-OHL-S-2.0
/*
Copyright (c) 2020-2025 FPGA Ninja, LLC
Authors:
- Alex Forencich
*/
`resetall
`timescale 1ns / 1ps
`default_nettype none
/*
* LED shift register driver
*/
module taxi_led_sreg #(
// number of LEDs
parameter COUNT = 8,
// invert output
parameter logic INVERT = 1'b0,
// reverse order
parameter logic REVERSE = 1'b0,
// interleave A and B inputs, otherwise only use A
parameter logic INTERLEAVE = 1'b0,
// clock prescale
parameter PRESCALE = 31
)
(
input wire logic clk,
input wire logic rst,
input wire logic [COUNT-1:0] led_a,
input wire logic [COUNT-1:0] led_b,
output wire logic sreg_d,
output wire logic sreg_ld,
output wire logic sreg_clk
);
localparam COUNT_INT = INTERLEAVE ? COUNT*2 : COUNT;
localparam CL_COUNT = $clog2(COUNT_INT);
localparam CL_PRESCALE = $clog2(PRESCALE+1);
logic [CL_COUNT+1-1:0] count_reg = 0;
logic [CL_PRESCALE-1:0] prescale_count_reg = 0;
logic enable_reg = 1'b0;
logic update_reg = 1'b1;
logic cycle_reg = 1'b0;
logic [COUNT_INT-1:0] led_sync_reg_1 = 0;
logic [COUNT_INT-1:0] led_sync_reg_2 = 0;
logic [COUNT_INT-1:0] led_reg = 0;
logic sreg_d_reg = 1'b0;
logic sreg_ld_reg = 1'b0;
logic sreg_clk_reg = 1'b0;
assign sreg_d = INVERT ? !sreg_d_reg : sreg_d_reg;
assign sreg_ld = sreg_ld_reg;
assign sreg_clk = sreg_clk_reg;
wire [COUNT_INT-1:0] led_in;
wire [COUNT_INT-1:0] led_sync;
if (INTERLEAVE) begin
for (genvar i = 0; i < COUNT; i = i + 1) begin
assign led_in[i*2 +: 2] = {led_b[i], led_a[i]};
end
end else begin
assign led_in = led_a;
end
taxi_sync_signal #(
.WIDTH(COUNT_INT),
.N(2)
)
sync_inst (
.clk(clk),
.in(led_in),
.out(led_sync)
);
always @(posedge clk) begin
enable_reg <= 1'b0;
if (prescale_count_reg != 0) begin
prescale_count_reg <= prescale_count_reg - 1;
end else begin
enable_reg <= 1'b1;
prescale_count_reg <= PRESCALE;
end
if (enable_reg) begin
if (cycle_reg) begin
cycle_reg <= 1'b0;
sreg_clk_reg <= 1'b1;
end else if (count_reg != 0) begin
sreg_clk_reg <= 1'b0;
sreg_ld_reg <= 1'b0;
if (count_reg < COUNT_INT) begin
count_reg <= count_reg + 1;
cycle_reg <= 1'b1;
if (REVERSE) begin
sreg_d_reg <= led_reg[CL_COUNT'(COUNT_INT-1-count_reg)];
end else begin
sreg_d_reg <= led_reg[CL_COUNT'(count_reg)];
end
end else begin
count_reg <= 0;
cycle_reg <= 1'b0;
sreg_d_reg <= 1'b0;
sreg_ld_reg <= 1'b1;
end
end else begin
sreg_clk_reg <= 1'b0;
sreg_ld_reg <= 1'b0;
if (update_reg) begin
update_reg <= 1'b0;
count_reg <= 1;
cycle_reg <= 1'b1;
if (REVERSE) begin
sreg_d_reg <= led_reg[COUNT_INT-1];
end else begin
sreg_d_reg <= led_reg[0];
end
end
end
end
if (led_sync != led_reg) begin
led_reg <= led_sync;
update_reg <= 1'b1;
end
if (rst) begin
count_reg <= 0;
prescale_count_reg <= 0;
enable_reg <= 1'b0;
update_reg <= 1'b1;
cycle_reg <= 1'b0;
led_reg <= 0;
sreg_d_reg <= 1'b0;
sreg_ld_reg <= 1'b0;
sreg_clk_reg <= 1'b0;
end
end
endmodule
`resetall

129
src/io/rtl/taxi_oddr.sv Normal file
View File

@@ -0,0 +1,129 @@
// SPDX-License-Identifier: CERN-OHL-S-2.0
/*
Copyright (c) 2016-2025 FPGA Ninja, LLC
Authors:
- Alex Forencich
*/
`resetall
`timescale 1ns / 1ps
`default_nettype none
/*
* Generic ODDR module
*/
module taxi_oddr #
(
// simulation (set to avoid vendor primitives)
parameter logic SIM = 1'b0,
// vendor ("GENERIC", "XILINX", "ALTERA")
parameter string VENDOR = "XILINX",
// device family
parameter string FAMILY = "virtex7",
// Width of register in bits
parameter WIDTH = 1
)
(
input wire logic clk,
input wire logic [WIDTH-1:0] d1,
input wire logic [WIDTH-1:0] d2,
output wire logic [WIDTH-1:0] q
);
/*
Provides a consistent output DDR flip flop across multiple FPGA families
_____ _____ _____ _____
clk ____/ \_____/ \_____/ \_____/ \_____
_ ___________ ___________ ___________ ___________ __
d1 _X____D0_____X____D2_____X____D4_____X____D6_____X__
_ ___________ ___________ ___________ ___________ __
d2 _X____D1_____X____D3_____X____D5_____X____D7_____X__
_____ _____ _____ _____ _____ _____ _____ _____ ____
d _____X_D0__X_D1__X_D2__X_D3__X_D4__X_D5__X_D6__X_D7_
*/
if (!SIM && VENDOR == "XILINX") begin
// Xilinx/AMD device support
if (FAMILY == "spartan6") begin
// spartan6 uses IODDR2
for (genvar n = 0; n < WIDTH; n = n + 1) begin : oddr
ODDR2 #(
.DDR_ALIGNMENT("C0"),
.SRTYPE("ASYNC")
)
oddr_inst (
.Q(q[n]),
.C0(clk),
.C1(~clk),
.CE(1'b1),
.D0(d1[n]),
.D1(d2[n]),
.R(1'b0),
.S(1'b0)
);
end
end else begin
// virtex4, virtex5, virtex6, virtex7, kintex7, artix7, virtexu, kintexu, virtexuplus, kintexuplus
for (genvar n = 0; n < WIDTH; n = n + 1) begin : oddr
ODDR #(
.DDR_CLK_EDGE("SAME_EDGE"),
.SRTYPE("ASYNC")
)
oddr_inst (
.Q(q[n]),
.C(clk),
.CE(1'b1),
.D1(d1[n]),
.D2(d2[n]),
.R(1'b0),
.S(1'b0)
);
end
end
end else if (!SIM && VENDOR == "ALTERA") begin
// Altera/Intel/Altera device support
altddio_out #(
.WIDTH(WIDTH),
.POWER_UP_HIGH("OFF"),
.OE_REG("UNUSED")
)
altddio_out_inst (
.aset(1'b0),
.datain_h(d1),
.datain_l(d2),
.outclocken(1'b1),
.outclock(clk),
.aclr(1'b0),
.dataout(q)
);
end else begin
// generic/simulation implementation (no vendor primitives)
logic [WIDTH-1:0] d1_reg = '0;
logic [WIDTH-1:0] d2_reg = '0;
always_ff @(posedge clk) begin
d1_reg <= d1;
d2_reg <= d2;
end
assign q = clk ? d1_reg : d2_reg;
end
endmodule
`resetall

View File

@@ -0,0 +1,116 @@
// SPDX-License-Identifier: CERN-OHL-S-2.0
/*
Copyright (c) 2016-2025 FPGA Ninja, LLC
Authors:
- Alex Forencich
*/
`resetall
`timescale 1ns / 1ps
`default_nettype none
/*
* Generic source synchronous DDR input
*/
module taxi_ssio_ddr_in #
(
// simulation (set to avoid vendor primitives)
parameter logic SIM = 1'b0,
// vendor ("GENERIC", "XILINX", "ALTERA")
parameter string VENDOR = "XILINX",
// device family
parameter string FAMILY = "virtex7",
// Width of register in bits
parameter WIDTH = 1
)
(
input wire logic input_clk,
input wire logic [WIDTH-1:0] input_d,
output wire logic output_clk,
output wire logic [WIDTH-1:0] output_q1,
output wire logic [WIDTH-1:0] output_q2
);
wire clk_int;
wire clk_io;
if (!SIM && VENDOR == "XILINX") begin
// Xilinx/AMD device support
// use Xilinx clocking primitives
if (FAMILY == "virtex6" || FAMILY == "virtex7" || FAMILY == "kintex7" || FAMILY == "artix7") begin
// BUFIO + BUFR
// virtex6, virtex7, kintex7, artix7, zynq
assign clk_int = input_clk;
// pass through RX clock to input buffers
BUFIO
clk_bufio (
.I(clk_int),
.O(clk_io)
);
// pass through RX clock to logic
BUFR #(
.BUFR_DIVIDE("BYPASS")
)
clk_bufr (
.I(clk_int),
.O(output_clk),
.CE(1'b1),
.CLR(1'b0)
);
end else begin
// BUFG only
// spartan6, virtexu, kintexu, virtexuplus, virtexuplusHBM, virtexuplus58g, kintexuplus, zynquplus, zynquplusRFSOC
// buffer RX clock
BUFG
clk_bufg (
.I(input_clk),
.O(clk_int)
);
// pass through RX clock to logic and input buffers
assign clk_io = clk_int;
assign output_clk = clk_int;
end
end else begin
// generic/simulation implementation (no vendor primitives)
// pass through RX clock to input buffers
assign clk_io = input_clk;
// pass through RX clock to logic
assign clk_int = input_clk;
assign output_clk = clk_int;
end
taxi_iddr #(
.SIM(SIM),
.VENDOR(VENDOR),
.FAMILY(FAMILY),
.WIDTH(WIDTH)
)
data_iddr_inst (
.clk(clk_io),
.d(input_d),
.q1(output_q1),
.q2(output_q2)
);
endmodule
`resetall

View File

@@ -0,0 +1,107 @@
// SPDX-License-Identifier: CERN-OHL-S-2.0
/*
Copyright (c) 2016-2025 FPGA Ninja, LLC
Authors:
- Alex Forencich
*/
`resetall
`timescale 1ns / 1ps
`default_nettype none
/*
* Generic source synchronous DDR input
*/
module taxi_ssio_ddr_in_diff #
(
// simulation (set to avoid vendor primitives)
parameter logic SIM = 1'b0,
// vendor ("GENERIC", "XILINX", "ALTERA")
parameter string VENDOR = "XILINX",
// device family
parameter string FAMILY = "virtex7",
// Width of register in bits
parameter WIDTH = 1
)
(
input wire logic input_clk_p,
input wire logic input_clk_n,
input wire logic [WIDTH-1:0] input_d_p,
input wire logic [WIDTH-1:0] input_d_n,
output wire logic output_clk,
output wire logic [WIDTH-1:0] output_q1,
output wire logic [WIDTH-1:0] output_q2
);
wire input_clk;
wire [WIDTH-1:0] input_d;
if (!SIM && VENDOR == "XILINX") begin
// Xilinx/AMD device support
IBUFDS
clk_ibufds_inst (
.I(input_clk_p),
.IB(input_clk_n),
.O(input_clk)
);
for (genvar n = 0; n < WIDTH; n = n + 1) begin
IBUFDS
data_ibufds_inst (
.I(input_d_p[n]),
.IB(input_d_n[n]),
.O(input_d[n])
);
end
end else if (!SIM && VENDOR == "ALTERA") begin
// Altera/Intel/Altera device support
ALT_INBUF_DIFF
clk_inbuf_diff_inst (
.i(input_clk_p),
.ibar(input_clk_n),
.o(input_clk)
);
for (genvar n = 0; n < WIDTH; n = n + 1) begin
ALT_INBUF_DIFF
data_inbuf_diff_inst (
.i(input_d_p[n]),
.ibar(input_d_n[n]),
.o(input_d[n])
);
end
end else begin
// generic/simulation implementation (no vendor primitives)
assign input_clk = input_clk_p;
assign input_d = input_d_p;
end
taxi_ssio_ddr_in #(
.SIM(SIM),
.VENDOR(VENDOR),
.FAMILY(FAMILY),
.WIDTH(WIDTH)
)
ssio_ddr_in_inst(
.input_clk(input_clk),
.input_d(input_d),
.output_clk(output_clk),
.output_q1(output_q1),
.output_q2(output_q2)
);
endmodule
`resetall

View File

@@ -0,0 +1,72 @@
// SPDX-License-Identifier: CERN-OHL-S-2.0
/*
Copyright (c) 2016-2025 FPGA Ninja, LLC
Authors:
- Alex Forencich
*/
`resetall
`timescale 1ns / 1ps
`default_nettype none
/*
* Generic source synchronous DDR output
*/
module taxi_ssio_ddr_out #
(
// simulation (set to avoid vendor primitives)
parameter logic SIM = 1'b0,
// vendor ("GENERIC", "XILINX", "ALTERA")
parameter string VENDOR = "XILINX",
// device family
parameter string FAMILY = "virtex7",
// Use 90 degree clock for transmit
parameter logic USE_CLK90 = 1'b1,
// Width of register in bits
parameter WIDTH = 1
)
(
input wire logic clk,
input wire logic clk90,
input wire logic [WIDTH-1:0] input_d1,
input wire logic [WIDTH-1:0] input_d2,
output wire logic output_clk,
output wire logic [WIDTH-1:0] output_q
);
wire ref_clk = USE_CLK90 ? clk90 : clk;
taxi_oddr #(
.SIM(SIM),
.VENDOR(VENDOR),
.FAMILY(FAMILY),
.WIDTH(1)
)
clk_oddr_inst (
.clk(ref_clk),
.d1(1'b1),
.d2(1'b0),
.q(output_clk)
);
taxi_oddr #(
.SIM(SIM),
.VENDOR(VENDOR),
.FAMILY(FAMILY),
.WIDTH(WIDTH)
)
data_oddr_inst (
.clk(clk),
.d1(input_d1),
.d2(input_d2),
.q(output_q)
);
endmodule
`resetall

View File

@@ -0,0 +1,113 @@
// SPDX-License-Identifier: CERN-OHL-S-2.0
/*
Copyright (c) 2016-2025 FPGA Ninja, LLC
Authors:
- Alex Forencich
*/
`resetall
`timescale 1ns / 1ps
`default_nettype none
/*
* Generic source synchronous DDR output
*/
module taxi_ssio_ddr_out_diff #
(
// simulation (set to avoid vendor primitives)
parameter logic SIM = 1'b0,
// vendor ("GENERIC", "XILINX", "ALTERA")
parameter string VENDOR = "XILINX",
// device family
parameter string FAMILY = "virtex7",
// Use 90 degree clock for transmit
parameter logic USE_CLK90 = 1'b1,
// Width of register in bits
parameter WIDTH = 1
)
(
input wire logic clk,
input wire logic clk90,
input wire logic [WIDTH-1:0] input_d1,
input wire logic [WIDTH-1:0] input_d2,
output wire logic output_clk_p,
output wire logic output_clk_n,
output wire logic [WIDTH-1:0] output_q_p,
output wire logic [WIDTH-1:0] output_q_n
);
wire output_clk;
wire [WIDTH-1:0] output_q;
taxi_ssio_ddr_out #(
.SIM(SIM),
.VENDOR(VENDOR),
.FAMILY(FAMILY),
.USE_CLK90(USE_CLK90),
.WIDTH(WIDTH)
)
ssio_ddr_out_inst(
.clk(clk),
.clk90(clk90),
.input_d1(input_d1),
.input_d2(input_d2),
.output_clk(output_clk),
.output_q(output_q)
);
if (!SIM && VENDOR == "XILINX") begin
// Xilinx/AMD device support
OBUFDS
clk_obufds_inst (
.I(output_clk),
.O(output_clk_p),
.OB(output_clk_n)
);
for (genvar n = 0; n < WIDTH; n = n + 1) begin
OBUFDS
data_obufds_inst (
.I(output_q[n]),
.O(output_q_p[n]),
.OB(output_q_n[n])
);
end
end else if (!SIM && VENDOR == "ALTERA") begin
// Altera/Intel/Altera device support
ALT_OUTBUF_DIFF
clk_outbuf_diff_inst (
.i(output_clk),
.o(output_clk_p),
.obar(output_clk_n)
);
for (genvar n = 0; n < WIDTH; n = n + 1) begin
ALT_OUTBUF_DIFF
data_outbuf_diff_inst (
.i(output_q[n]),
.o(output_q_p[n]),
.obar(output_q_n[n])
);
end
end else begin
// generic/simulation implementation (no vendor primitives)
assign output_clk_p = output_clk;
assign output_clk_n = ~output_clk;
assign output_q_p = output_q;
assign output_q_n = ~output_q;
end
endmodule
`resetall

View File

@@ -0,0 +1,134 @@
// SPDX-License-Identifier: CERN-OHL-S-2.0
/*
Copyright (c) 2016-2025 FPGA Ninja, LLC
Authors:
- Alex Forencich
*/
`resetall
`timescale 1ns / 1ps
`default_nettype none
/*
* Generic source synchronous SDR input
*/
module taxi_ssio_sdr_in #
(
// simulation (set to avoid vendor primitives)
parameter logic SIM = 1'b0,
// vendor ("GENERIC", "XILINX", "ALTERA")
parameter string VENDOR = "XILINX",
// device family
parameter string FAMILY = "virtex7",
// Width of register in bits
parameter WIDTH = 1
)
(
input wire logic input_clk,
input wire logic [WIDTH-1:0] input_d,
output wire logic output_clk,
output wire logic [WIDTH-1:0] output_q
);
wire clk_int;
wire clk_io;
if (!SIM && VENDOR == "XILINX") begin
// Xilinx/AMD device support
if (FAMILY == "virtex6" || FAMILY == "virtex7" || FAMILY == "kintex7" || FAMILY == "artix7") begin
// BUFIO + BUFR
// virtex6, virtex7, kintex7, artix7, zynq
assign clk_int = input_clk;
// pass through RX clock to input buffers
BUFIO
clk_bufio (
.I(clk_int),
.O(clk_io)
);
// pass through RX clock to logic
BUFR #(
.BUFR_DIVIDE("BYPASS")
)
clk_bufr (
.I(clk_int),
.O(output_clk),
.CE(1'b1),
.CLR(1'b0)
);
end else if (FAMILY == "spartan6") begin
// BUFIO2 + BUFG
// spartan6
// pass through RX clock to input buffers
BUFIO2 #(
.DIVIDE(1),
.DIVIDE_BYPASS("TRUE"),
.I_INVERT("FALSE"),
.USE_DOUBLER("FALSE")
)
clk_bufio (
.I(input_clk),
.DIVCLK(clk_int),
.IOCLK(clk_io),
.SERDESSTROBE()
);
// pass through RX clock to MAC
BUFG
clk_bufg (
.I(clk_int),
.O(output_clk)
);
end else begin
// BUFG only
// virtexu, kintexu, virtexuplus, virtexuplusHBM, virtexuplus58g, kintexuplus, zynquplus, zynquplusRFSOC
// buffer RX clock
BUFG
clk_bufg (
.I(input_clk),
.O(clk_int)
);
// pass through RX clock to logic and input buffers
assign clk_io = clk_int;
assign output_clk = clk_int;
end
end else begin
// generic/simulation implementation (no vendor primitives)
// pass through RX clock to input buffers
assign clk_io = input_clk;
// pass through RX clock to logic
assign clk_int = input_clk;
assign output_clk = clk_int;
end
(* IOB = "TRUE" *)
logic [WIDTH-1:0] output_q_reg = '0;
assign output_q = output_q_reg;
always_ff @(posedge clk_io) begin
output_q_reg <= input_d;
end
endmodule
`resetall

View File

@@ -0,0 +1,105 @@
// SPDX-License-Identifier: CERN-OHL-S-2.0
/*
Copyright (c) 2016-2025 FPGA Ninja, LLC
Authors:
- Alex Forencich
*/
`resetall
`timescale 1ns / 1ps
`default_nettype none
/*
* Generic source synchronous SDR input
*/
module ssio_sdr_in_diff #
(
// simulation (set to avoid vendor primitives)
parameter logic SIM = 1'b0,
// vendor ("GENERIC", "XILINX", "ALTERA")
parameter string VENDOR = "XILINX",
// device family
parameter string FAMILY = "virtex7",
// Width of register in bits
parameter WIDTH = 1
)
(
input wire logic input_clk_p,
input wire logic input_clk_n,
input wire logic [WIDTH-1:0] input_d_p,
input wire logic [WIDTH-1:0] input_d_n,
output wire logic output_clk,
output wire logic [WIDTH-1:0] output_q
);
wire input_clk;
wire [WIDTH-1:0] input_d;
if (!SIM && VENDOR == "XILINX") begin
// Xilinx/AMD device support
IBUFDS
clk_ibufds_inst (
.I(input_clk_p),
.IB(input_clk_n),
.O(input_clk)
);
for (genvar n = 0; n < WIDTH; n = n + 1) begin
IBUFDS
data_ibufds_inst (
.I(input_d_p[n]),
.IB(input_d_n[n]),
.O(input_d[n])
);
end
end else if (!SIM && VENDOR == "ALTERA") begin
// Altera/Intel/Altera device support
ALT_INBUF_DIFF
clk_inbuf_diff_inst (
.i(input_clk_p),
.ibar(input_clk_n),
.o(input_clk)
);
for (genvar n = 0; n < WIDTH; n = n + 1) begin
ALT_INBUF_DIFF
data_inbuf_diff_inst (
.i(input_d_p[n]),
.ibar(input_d_n[n]),
.o(input_d[n])
);
end
end else begin
// generic/simulation implementation (no vendor primitives)
assign input_clk = input_clk_p;
assign input_d = input_d_p;
end
taxi_ssio_sdr_in #(
.SIM(SIM),
.VENDOR(VENDOR),
.FAMILY(FAMILY),
.WIDTH(WIDTH)
)
ssio_ddr_in_inst(
.input_clk(input_clk),
.input_d(input_d),
.output_clk(output_clk),
.output_q(output_q)
);
endmodule
`resetall

View File

@@ -0,0 +1,62 @@
// SPDX-License-Identifier: CERN-OHL-S-2.0
/*
Copyright (c) 2016-2025 FPGA Ninja, LLC
Authors:
- Alex Forencich
*/
`resetall
`timescale 1ns / 1ps
`default_nettype none
/*
* Generic source synchronous SDR output
*/
module taxi_ssio_sdr_out #
(
// simulation (set to avoid vendor primitives)
parameter logic SIM = 1'b0,
// vendor ("GENERIC", "XILINX", "ALTERA")
parameter string VENDOR = "XILINX",
// device family
parameter string FAMILY = "virtex7",
// Width of register in bits
parameter WIDTH = 1
)
(
input wire logic clk,
input wire logic [WIDTH-1:0] input_d,
output wire logic output_clk,
output wire logic [WIDTH-1:0] output_q
);
taxi_oddr #(
.SIM(SIM),
.VENDOR(VENDOR),
.FAMILY(FAMILY),
.WIDTH(1)
)
clk_oddr_inst (
.clk(clk),
.d1(1'b0),
.d2(1'b1),
.q(output_clk)
);
(* IOB = "TRUE" *)
logic [WIDTH-1:0] output_q_reg = '0;
assign output_q = output_q_reg;
always_ff @(posedge clk) begin
output_q_reg <= input_d;
end
endmodule
`resetall

View File

@@ -0,0 +1,106 @@
// SPDX-License-Identifier: CERN-OHL-S-2.0
/*
Copyright (c) 2016-2025 FPGA Ninja, LLC
Authors:
- Alex Forencich
*/
`resetall
`timescale 1ns / 1ps
`default_nettype none
/*
* Generic source synchronous SDR output
*/
module taxi_ssio_sdr_out_diff #
(
// simulation (set to avoid vendor primitives)
parameter logic SIM = 1'b0,
// vendor ("GENERIC", "XILINX", "ALTERA")
parameter string VENDOR = "XILINX",
// device family
parameter string FAMILY = "virtex7",
// Width of register in bits
parameter WIDTH = 1
)
(
input wire logic clk,
input wire logic [WIDTH-1:0] input_d,
output wire logic output_clk_p,
output wire logic output_clk_n,
output wire logic [WIDTH-1:0] output_q_p,
output wire logic [WIDTH-1:0] output_q_n
);
wire output_clk;
wire [WIDTH-1:0] output_q;
taxi_ssio_sdr_out #(
.SIM(SIM),
.VENDOR(VENDOR),
.FAMILY(FAMILY),
.WIDTH(WIDTH)
)
ssio_ddr_out_inst(
.clk(clk),
.input_d(input_d),
.output_clk(output_clk),
.output_q(output_q)
);
if (!SIM && VENDOR == "XILINX") begin
// Xilinx/AMD device support
OBUFDS
clk_obufds_inst (
.I(output_clk),
.O(output_clk_p),
.OB(output_clk_n)
);
for (genvar n = 0; n < WIDTH; n = n + 1) begin
OBUFDS
data_obufds_inst (
.I(output_q[n]),
.O(output_q_p[n]),
.OB(output_q_n[n])
);
end
end else if (!SIM && VENDOR == "ALTERA") begin
// Altera/Intel/Altera device support
ALT_OUTBUF_DIFF
clk_outbuf_diff_inst (
.i(output_clk),
.o(output_clk_p),
.obar(output_clk_n)
);
for (genvar n = 0; n < WIDTH; n = n + 1) begin
ALT_OUTBUF_DIFF
data_outbuf_diff_inst (
.i(output_q[n]),
.o(output_q_p[n]),
.obar(output_q_n[n])
);
end
end else begin
// generic/simulation implementation (no vendor primitives)
assign output_clk_p = output_clk;
assign output_clk_n = ~output_clk;
assign output_q_p = output_q;
assign output_q_n = ~output_q;
end
endmodule
`resetall