diff options
Diffstat (limited to 'manufacturer/altera/cyclone10_lp/sim/src/tb.sv')
| -rw-r--r-- | manufacturer/altera/cyclone10_lp/sim/src/tb.sv | 359 |
1 files changed, 359 insertions, 0 deletions
diff --git a/manufacturer/altera/cyclone10_lp/sim/src/tb.sv b/manufacturer/altera/cyclone10_lp/sim/src/tb.sv new file mode 100644 index 0000000..9b6b3a2 --- /dev/null +++ b/manufacturer/altera/cyclone10_lp/sim/src/tb.sv @@ -0,0 +1,359 @@ +/* + * tb.sv + * + * Copyright (C) 2025 Private Island Networks Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * function: test bench for Betsy + * + * Notes: + * + * RX data is from the TB to the DUT + * TX data is from the DUT to the TB + * + */ + +`timescale 1ns / 1ps + +//`define TEST_ETOE +`define ML_ENGINE +//`define TEST_CONTROLLER + +`define INCLUDED +`include "../../../../../src/rgmii_params.v" +`include "../../../../../src/ethernet_params.v" +`undef INCLUDED + +module tb; + + parameter NUM_PHYS = 3; + + // System clocks + parameter PERIOD_CLK_25 = 40; // 25 MHz + parameter PERIOD_CLK_125 = 8; // 125 MHz + parameter PERIOD_CLK_250 = 4; // 250 MHz to support RGMII DDR + + localparam IDLE_SHIFT = 4; // Used to multiple the specified # of idle clocks + +`ifdef ML_ENGINE + localparam RX0_CLK_CNT_START = 'd400; + localparam RX1_CLK_CNT_START = 'd4000_0000; + localparam RX2_CLK_CNT_START = 'd4000_0000; +`else + localparam RX0_CLK_CNT_START = 'd400; + localparam RX1_CLK_CNT_START = 'd400; + localparam RX2_CLK_CNT_START = 'd400; +`endif + + + // FPGA I/O + reg rstn; + reg clk_125, clk_25, clk_phy, clk_phyx2; + wire phy0_rx_clk, phy1_rx_clk, phy2_rx_clk; + reg phy0_rx_ctl, phy1_rx_ctl, phy2_rx_ctl; + reg [3:0] phy0_rx_d, phy1_rx_d, phy2_rx_d; + wire phy0_tx_clk, phy1_tx_clk, phy2_tx_clk; + wire phy0_tx_ctl, phy1_tx_ctl, phy2_tx_ctl; + wire [3:0] phy0_tx_d, phy1_tx_d, phy2_tx_d; + wire phy0_mdc, phy0_mdio, phy0_resetn, phy0_intn; + wire phy1_mdc, phy1_mdio, phy1_resetn, phy1_intn; + wire phy2_mdc, phy2_mdio, phy2_resetn, phy2_intn; + wire [2:0] led; + + // sim only I/O + wire pclk; + wire pll_lock; + wire [2:0] phy_up; + + betsy dut( + .rstn(rstn), + .clk_i(clk_25), + .phy0_clk(clk_25), + .phy1_clk(), + + // Sim Only + .pll_locked_o(pll_lock), + .pclk_o(pclk), + .phy_up_o(phy_up), + + .phy0_rstn(phy0_resetn), + .phy0_rx_clk(phy0_rx_clk), + .phy0_rx_ctl(phy0_rx_ctl), + .phy0_rx_d(phy0_rx_d), + .phy0_tx_clk(phy0_tx_clk), + .phy0_tx_ctl(phy0_tx_ctl), + .phy0_tx_d(phy0_tx_d), + .phy0_mdc(phy0_mdc), + .phy0_mdio(phy0_mdio), + .phy0_intn(phy0_intn), + + .phy1_rstn(phy1_resetn), + .phy1_rx_clk(phy1_rx_clk), + .phy1_rx_ctl(phy1_rx_ctl), + .phy1_rx_d(phy1_rx_d), + .phy1_tx_clk(phy1_tx_clk), + .phy1_tx_ctl(phy1_tx_ctl), + .phy1_tx_d(phy1_tx_d), + .phy1_mdc(phy1_mdc), + .phy1_mdio(phy1_mdio), + .phy1_intn(phy1_intn), + + .phy2_rstn(phy2_resetn), + .phy2_rx_clk(phy2_rx_clk), + .phy2_rx_ctl(phy2_rx_ctl), + .phy2_rx_d(phy2_rx_d), + .phy2_tx_clk(phy2_tx_clk), + .phy2_tx_ctl(phy2_tx_ctl), + .phy2_tx_d(phy2_tx_d), + .phy2_mdc(phy2_mdc), + .phy2_mdio(phy2_mdio), + .phy2_intn(phy2_intn), + + .flash_clk(), + .flash_dqs(), + .flash_seln(), + .flash_d(), + + .fpga_led(led) + + ); + + + reg [23:0] rx_clk_cnt; + reg [23:0] rx0_clk_cnt_start, rx1_clk_cnt_start, rx2_clk_cnt_start; + reg [13:0] rx0_idle_cnt, rx1_idle_cnt, rx2_idle_cnt; + reg [13:0] rx0_data_cnt, rx1_data_cnt, rx2_data_cnt; + reg rx0_last_byte, rx1_last_byte, rx2_last_byte; + reg [8:0] rx0_d[0:16383]; // 2**14 + reg [8:0] rx1_d[0:16383]; // + reg [8:0] rx2_d[0:16383]; // + + +`ifdef ML_ENGINE + initial begin + $readmemh("../data/cont_mle_w.dat",rx0_d); + $display("[%0t ns] ==INFO== Load memory from file for rx0: %0s.", $time, "cont_mle_w.dat"); + end +`endif + +`ifdef TEST_ETOE + initial begin + $readmemh("../data/etoe0.dat",rx0_d); + $display("[%0t ns] ==INFO== Load memory from file for rx0: %0s.", $time, "etoe0.dat"); + $readmemh("../data/etoe1.dat",rx1_d); + $display("[%0t ns] ==INFO== Load memory from file for rx1: %0s.", $time, "etoe1.dat"); + $readmemh("../data/etoe2.dat",rx2_d); + $display("[%0t ns] ==INFO== Load memory from file for rx2: %0s.", $time, "etoe2.dat"); + end +`endif + +`ifdef TEST_CONTROLLER + initial begin + $readmemh("../data/cont_query.dat",rx0_d); + $display("[%0t ns] ==INFO== Load memory from file for rx0: %0s.", $time, "cont_query.dat"); + end +`endif + + + initial begin + rstn = 1'b0; + clk_25 = 1'b0; + clk_125 = 1'b0; + clk_phy = 0; + clk_phyx2 = 0; + #25 rstn = 1'b1; + end + + // Clocks + always + #(PERIOD_CLK_125/2) clk_125 = ~clk_125; + + always + #(PERIOD_CLK_25/2) clk_25 = ~clk_25; + + always + #(PERIOD_CLK_125/2) clk_phy = ~clk_phy; + + always + #(PERIOD_CLK_250/2) clk_phyx2 = ~clk_phyx2; + + + assign #2 phy0_rx_clk = ~clk_phy; // 2.0 ns of delay + assign #2 phy1_rx_clk = ~clk_phy; + assign #2 phy2_rx_clk = ~clk_phy; + + // DDR count. Use bit 0 to indicate rising edge + always @(posedge clk_phyx2, negedge rstn) + if (!rstn) + rx_clk_cnt <= 24'd0; + else + rx_clk_cnt <= rx_clk_cnt + 1'b1; + + // PHY0 + always @(posedge clk_phy, negedge rstn) + if (!rstn) + rx0_idle_cnt <= 14'd0; + else if (rx0_d[rx0_data_cnt][8]) + rx0_idle_cnt <= rx0_d[rx0_data_cnt+1][7:0] << IDLE_SHIFT; + + always @(posedge clk_phy, negedge rstn) + if (!rstn) + rx0_clk_cnt_start <= RX0_CLK_CNT_START; + else if (rx0_d[rx0_data_cnt][8]) + rx0_clk_cnt_start <= rx_clk_cnt + (rx0_d[rx0_data_cnt+1][7:0] << IDLE_SHIFT) + 1'b1; + + always @(negedge clk_phyx2, negedge rstn) + if (!rstn) + rx0_last_byte <= 1'b0; + else if (rx0_d[rx0_data_cnt][8] && rx_clk_cnt[0]) + rx0_last_byte <= 1'b1; + else + rx0_last_byte <= 1'b0; + + always @(negedge clk_phyx2, negedge rstn) + if (!rstn) begin + phy0_rx_ctl <= 1'b0; + phy0_rx_d <= 4'hD; + rx0_data_cnt <= 24'd0; + end + else if (rx_clk_cnt >= rx0_clk_cnt_start && !rx0_last_byte) begin + if (!rx_clk_cnt[0]) begin + phy0_rx_ctl <= 1'b1; + phy0_rx_d <= rx0_d[rx0_data_cnt][3:0]; + end + else begin + phy0_rx_ctl <= 1'b1; + phy0_rx_d <= rx0_d[rx0_data_cnt][7:4]; + rx0_data_cnt <= rx0_data_cnt + 1'b1; + end + end + else if (rx0_last_byte) begin + phy0_rx_ctl <= 1'b0; + phy0_rx_d <= 4'hD; + rx0_data_cnt <= rx0_data_cnt + 1'b1; + end + else begin + phy0_rx_ctl <= 1'b0; + phy0_rx_d <= 4'hD; + end + + + // PHY1 + + // rx1_idle_cnt: when flag is set, update idle count + always @(posedge clk_phy, negedge rstn) + if (!rstn) + rx1_idle_cnt <= 14'd0; + else if (rx1_d[rx1_data_cnt][8]) + rx1_idle_cnt <= rx1_d[rx1_data_cnt+1][7:0] << IDLE_SHIFT; + + // rx1_clk_cnt_start: + always @(posedge clk_phy, negedge rstn) + if (!rstn) + rx1_clk_cnt_start <= RX1_CLK_CNT_START; + else if (rx1_d[rx1_data_cnt][8]) + rx1_clk_cnt_start <= rx_clk_cnt + (rx1_d[rx1_data_cnt+1][7:0] << IDLE_SHIFT) + 1'b1; + + + always @(negedge clk_phyx2, negedge rstn) + if (!rstn) + rx1_last_byte <= 1'b0; + else if (rx1_d[rx1_data_cnt][8] && rx_clk_cnt[0]) + rx1_last_byte <= 1'b1; + else + rx1_last_byte <= 1'b0; + + always @(negedge clk_phyx2, negedge rstn) + if (!rstn) begin + phy1_rx_ctl <= 1'b0; + phy1_rx_d <= 4'hD; + rx1_data_cnt <= 24'd0; + end + else if (rx_clk_cnt >= rx1_clk_cnt_start && !rx1_last_byte) begin + if (!rx_clk_cnt[0]) begin + phy1_rx_ctl <= 1'b1; + phy1_rx_d <= rx1_d[rx1_data_cnt][3:0]; + end + else begin + phy1_rx_ctl <= 1'b1; + phy1_rx_d <= rx1_d[rx1_data_cnt][7:4]; + rx1_data_cnt <= rx1_data_cnt + 1'b1; + end + end + else if (rx1_last_byte) begin + phy1_rx_ctl <= 1'b0; + phy1_rx_d <= 4'hD; + rx1_data_cnt <= rx1_data_cnt + 1'b1; + end + else begin + phy1_rx_ctl <= 1'b0; + phy1_rx_d <= 4'hD; + end + + // PHY2 + + // rx1_idle_cnt: when flag is set, update idle count + always @(posedge clk_phy, negedge rstn) + if (!rstn) + rx2_idle_cnt <= 14'd0; + else if (rx2_d[rx2_data_cnt][8]) + rx2_idle_cnt <= rx2_d[rx2_data_cnt+1][7:0] << IDLE_SHIFT; + + always @(posedge clk_phy, negedge rstn) + if (!rstn) + rx2_clk_cnt_start <= RX2_CLK_CNT_START; + else if (rx2_d[rx2_data_cnt][8]) + rx2_clk_cnt_start <= rx_clk_cnt + (rx2_d[rx2_data_cnt+1][7:0] << IDLE_SHIFT) + 1'b1; + + // + always @(negedge clk_phyx2, negedge rstn) + if (!rstn) + rx2_last_byte <= 1'b0; + else if (rx2_d[rx2_data_cnt][8] && rx_clk_cnt[0]) + rx2_last_byte <= 1'b1; + else + rx2_last_byte <= 1'b0; + + + always @(negedge clk_phyx2, negedge rstn) + if (!rstn) begin + phy2_rx_ctl <= 1'b0; + phy2_rx_d <= 4'hD; + rx2_data_cnt <= 24'd0; + end + else if (rx_clk_cnt >= rx2_clk_cnt_start && !rx2_last_byte) begin + if (!rx_clk_cnt[0]) begin + phy2_rx_ctl <= 1'b1; + phy2_rx_d <= rx2_d[rx2_data_cnt][3:0]; + end + else begin + phy2_rx_ctl <= 1'b1; + phy2_rx_d <= rx2_d[rx2_data_cnt][7:4]; + rx2_data_cnt <= rx2_data_cnt + 1'b1; + end + end + else if (rx2_last_byte) begin + phy2_rx_ctl <= 1'b0; + phy2_rx_d <= 4'hD; + rx2_data_cnt <= rx2_data_cnt + 1'b1; + end + else begin + phy2_rx_ctl <= 1'b0; + phy2_rx_d <= 4'hD; + end + + +endmodule + + |



