aboutsummaryrefslogtreecommitdiffstats
path: root/fpga/usrp3/lib/axi/axi_chdr_test_pattern.v
diff options
context:
space:
mode:
authorMartin Braun <martin.braun@ettus.com>2020-01-23 16:10:22 -0800
committerMartin Braun <martin.braun@ettus.com>2020-01-28 09:35:36 -0800
commitbafa9d95453387814ef25e6b6256ba8db2df612f (patch)
tree39ba24b5b67072d354775272e687796bb511848d /fpga/usrp3/lib/axi/axi_chdr_test_pattern.v
parent3075b981503002df3115d5f1d0b97d2619ba30f2 (diff)
downloaduhd-bafa9d95453387814ef25e6b6256ba8db2df612f.tar.gz
uhd-bafa9d95453387814ef25e6b6256ba8db2df612f.tar.bz2
uhd-bafa9d95453387814ef25e6b6256ba8db2df612f.zip
Merge FPGA repository back into UHD repository
The FPGA codebase was removed from the UHD repository in 2014 to reduce the size of the repository. However, over the last half-decade, the split between the repositories has proven more burdensome than it has been helpful. By merging the FPGA code back, it will be possible to create atomic commits that touch both FPGA and UHD codebases. Continuous integration testing is also simplified by merging the repositories, because it was previously difficult to automatically derive the correct UHD branch when testing a feature branch on the FPGA repository. This commit also updates the license files and paths therein. We are therefore merging the repositories again. Future development for FPGA code will happen in the same repository as the UHD host code and MPM code. == Original Codebase and Rebasing == The original FPGA repository will be hosted for the foreseeable future at its original local location: https://github.com/EttusResearch/fpga/ It can be used for bisecting, reference, and a more detailed history. The final commit from said repository to be merged here is 05003794e2da61cabf64dd278c45685a7abad7ec. This commit is tagged as v4.0.0.0-pre-uhd-merge. If you have changes in the FPGA repository that you want to rebase onto the UHD repository, simply run the following commands: - Create a directory to store patches (this should be an empty directory): mkdir ~/patches - Now make sure that your FPGA codebase is based on the same state as the code that was merged: cd src/fpga # Or wherever your FPGA code is stored git rebase v4.0.0.0-pre-uhd-merge Note: The rebase command may look slightly different depending on what exactly you're trying to rebase. - Create a patch set for your changes versus v4.0.0.0-pre-uhd-merge: git format-patch v4.0.0.0-pre-uhd-merge -o ~/patches Note: Make sure that only patches are stored in your output directory. It should otherwise be empty. Make sure that you picked the correct range of commits, and only commits you wanted to rebase were exported as patch files. - Go to the UHD repository and apply the patches: cd src/uhd # Or wherever your UHD repository is stored git am --directory fpga ~/patches/* rm -rf ~/patches # This is for cleanup == Contributors == The following people have contributed mainly to these files (this list is not complete): Co-authored-by: Alex Williams <alex.williams@ni.com> Co-authored-by: Andrej Rode <andrej.rode@ettus.com> Co-authored-by: Ashish Chaudhari <ashish@ettus.com> Co-authored-by: Ben Hilburn <ben.hilburn@ettus.com> Co-authored-by: Ciro Nishiguchi <ciro.nishiguchi@ni.com> Co-authored-by: Daniel Jepson <daniel.jepson@ni.com> Co-authored-by: Derek Kozel <derek.kozel@ettus.com> Co-authored-by: EJ Kreinar <ej@he360.com> Co-authored-by: Humberto Jimenez <humberto.jimenez@ni.com> Co-authored-by: Ian Buckley <ian.buckley@gmail.com> Co-authored-by: Jörg Hofrichter <joerg.hofrichter@ni.com> Co-authored-by: Jon Kiser <jon.kiser@ni.com> Co-authored-by: Josh Blum <josh@joshknows.com> Co-authored-by: Jonathon Pendlum <jonathan.pendlum@ettus.com> Co-authored-by: Martin Braun <martin.braun@ettus.com> Co-authored-by: Matt Ettus <matt@ettus.com> Co-authored-by: Michael West <michael.west@ettus.com> Co-authored-by: Moritz Fischer <moritz.fischer@ettus.com> Co-authored-by: Nick Foster <nick@ettus.com> Co-authored-by: Nicolas Cuervo <nicolas.cuervo@ettus.com> Co-authored-by: Paul Butler <paul.butler@ni.com> Co-authored-by: Paul David <paul.david@ettus.com> Co-authored-by: Ryan Marlow <ryan.marlow@ettus.com> Co-authored-by: Sugandha Gupta <sugandha.gupta@ettus.com> Co-authored-by: Sylvain Munaut <tnt@246tNt.com> Co-authored-by: Trung Tran <trung.tran@ettus.com> Co-authored-by: Vidush Vishwanath <vidush.vishwanath@ettus.com> Co-authored-by: Wade Fife <wade.fife@ettus.com>
Diffstat (limited to 'fpga/usrp3/lib/axi/axi_chdr_test_pattern.v')
-rw-r--r--fpga/usrp3/lib/axi/axi_chdr_test_pattern.v505
1 files changed, 505 insertions, 0 deletions
diff --git a/fpga/usrp3/lib/axi/axi_chdr_test_pattern.v b/fpga/usrp3/lib/axi/axi_chdr_test_pattern.v
new file mode 100644
index 000000000..e73eaaa9d
--- /dev/null
+++ b/fpga/usrp3/lib/axi/axi_chdr_test_pattern.v
@@ -0,0 +1,505 @@
+//
+// Copyright 2014 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+//
+// Synthesizable test pattern generator and checker
+// for AXI-Stream that can be used to test transparent blocks
+// (FIFOs, switches, etc)
+//
+
+module axi_chdr_test_pattern #(
+ parameter SR_BASE = 8'h0, //Base address for settings in this module
+ parameter DELAY_MODE = "DYNAMIC", //Are delays configurable at runtime {STATIC, DYNAMIC}
+ parameter SID_MODE = "DYNAMIC", //Is the SID configurable at runtime {STATIC, DYNAMIC}
+ parameter STATIC_SID = 32'h0, //SID Value if it is static
+ parameter BW_COUNTER = 1 //Instantiate counters to measure bandwidth (Cycles of Data Xfer / Total cycles)
+) (
+ input clk,
+ input reset,
+
+ // AXI stream to hook up to input of DUT
+ output reg [63:0] i_tdata,
+ output reg i_tlast,
+ output reg i_tvalid,
+ input i_tready,
+
+ // AXI stream to hook up to output of DUT
+ input [63:0] o_tdata,
+ input o_tlast,
+ input o_tvalid,
+ output reg o_tready,
+
+ //Settings bus interface
+ input set_stb,
+ input [7:0] set_addr,
+ input [31:0] set_data,
+
+ // Test flags
+ output reg running, //Test is currently in progress
+ output reg done, //(Sticky) Test has finished executing
+ output reg [1:0] error, //Error code from last test execution
+
+ output [127:0] status_vtr, //More information about test failure.
+ output [95:0] bw_ratio //Bandwidth counter info
+);
+
+ //
+ // Error Codes
+ //
+ localparam ERR_SUCCESS = 0;
+ localparam ERR_DATA_MISMATCH = 1;
+ localparam ERR_SIZE_MISMATCH_TOO_LONG = 2;
+ localparam ERR_SIZE_MISMATCH_TOO_SHORT = 3;
+
+ localparam ERR_TIMEOUT_LOG2 = 10;
+
+ //
+ // Settings
+ //
+ wire bist_size_ramp;
+ wire [1:0] bist_test_patt;
+ wire [12:0] bist_max_pkt_size;
+ wire bist_go, bist_cont, bist_ctrl_wr;
+ wire [1:0] bist_ctrl_reserved;
+ wire [17:0] bist_max_pkts;
+ wire [15:0] bist_tx_pkt_delay;
+ wire [7:0] bist_rx_samp_delay;
+ wire [31:0] bist_cvita_sid;
+
+ localparam TEST_PATT_ZERO_ONE = 2'd0;
+ localparam TEST_PATT_CHECKERBOARD = 2'd1;
+ localparam TEST_PATT_COUNT = 2'd2;
+ localparam TEST_PATT_COUNT_INV = 2'd3;
+
+ // SETTING: Test Control Register
+ // Fields:
+ // - [0] : (Strobe) Start the test if 1, otherwise stop a running test.
+ // If no test is running then reset the status. (Reseting a
+ // continuously running test requires two writes to this reg)
+ // - [1] : Start the test in continuous mode. (Run until reset or failure)
+ // - [3:2] : <Unused>
+ // - [5:4] : Test pattern:
+ // * 00 = Zeros and Ones (0x0000000000000000 <-> 0xFFFFFFFFFFFFFFFF)
+ // * 01 = Checkerboard (0x5555555555555555 <-> 0xAAAAAAAAAAAAAAAA)
+ // * 10 = Counter (Each byte will count up)
+ // * 11 = Invert Counter (Each byte will count up and invert)
+ setting_reg #(
+ .my_addr(SR_BASE + 0), .width(6), .at_reset(3'b0)
+ ) reg_ctrl (
+ .clk(clk), .rst(reset),
+ .strobe(set_stb), .addr(set_addr), .in(set_data),
+ .out({bist_test_patt, bist_ctrl_reserved, bist_cont, bist_go}),.changed(bist_ctrl_wr)
+ );
+
+ wire bist_start = bist_ctrl_wr & bist_go;
+ wire bist_clear = bist_ctrl_wr & ~bist_go;
+
+ // SETTING: Test Packet Configuration Register
+ // Fields:
+ // - [17:0] : Number of packets to transfer per BIST execution
+ // - [30:18] : Max number of bytes of payload per packet
+ // - [31] : Send variable (ramping) sized packets
+ setting_reg #(
+ .my_addr(SR_BASE + 1), .width(32), .at_reset(32'b0)
+ ) reg_pkt_config (
+ .clk(clk), .rst(reset),
+ .strobe(set_stb), .addr(set_addr), .in(set_data),
+ .out({bist_size_ramp, bist_max_pkt_size, bist_max_pkts}),.changed()
+ );
+
+ generate if (DELAY_MODE == "DYNAMIC") begin
+ // SETTING: Delay Register
+ // Fields:
+ // - [15:0] : Number of cycles to wait between generating consecutive *packets*
+ // - [23:16] : Number of cycles to wait between consuming consecutive *samples*
+ setting_reg #(
+ .my_addr(SR_BASE + 2), .width(24), .at_reset(24'b0)
+ ) reg_delay (
+ .clk(clk), .rst(reset),
+ .strobe(set_stb), .addr(set_addr), .in(set_data),
+ .out({bist_rx_samp_delay, bist_tx_pkt_delay}),.changed()
+ );
+ end else begin
+ assign {bist_rx_samp_delay, bist_tx_pkt_delay} = 24'h0;
+ end endgenerate
+
+ generate if (SID_MODE == "DYNAMIC") begin
+ // SETTING: CHDR Stream ID Register
+ // Fields:
+ // - [31:0] : Stream ID to attach to CHDR packets
+ setting_reg #(
+ .my_addr(SR_BASE + 3), .width(32), .at_reset(32'b0)
+ ) reg_sid (
+ .clk(clk), .rst(reset),
+ .strobe(set_stb), .addr(set_addr), .in(set_data),
+ .out(bist_cvita_sid),.changed()
+ );
+ end else begin
+ assign bist_cvita_sid = STATIC_SID;
+ end endgenerate
+
+ //
+ // State
+ //
+ localparam TX_IDLE = 3'd0;
+ localparam TX_START = 3'd1;
+ localparam TX_ACTIVE = 3'd2;
+ localparam TX_GAP = 3'd3;
+ localparam TX_DONE = 3'd4;
+ localparam TX_WAIT = 3'd5;
+
+ localparam RX_IDLE = 3'd0;
+ localparam RX_ACTIVE = 3'd1;
+ localparam RX_FAIL = 3'd2;
+ localparam RX_DONE = 3'd3;
+ localparam RX_WAIT = 3'd4;
+
+ reg [2:0] tx_state, rx_state;
+ reg [ERR_TIMEOUT_LOG2-1:0] err_timeout;
+ reg [1:0] test_pattern;
+ reg rearm_test;
+
+ reg [17:0] tx_pkt_cnt, rx_pkt_cnt;
+ reg [13:0] tx_byte_cnt, rx_byte_cnt;
+ reg [23:0] test_run_cnt;
+ reg [15:0] tx_delay;
+ reg [7:0] rx_delay;
+ wire [63:0] tx_cvita_hdr, rx_cvita_hdr;
+
+ wire tx_next_pkt_cond, rx_next_pkt_cond;
+ assign tx_next_pkt_cond = (tx_byte_cnt[12:3] == bist_max_pkt_size[12:3]) || //Packet size reaches max OR
+ (bist_size_ramp && ({7'h0, tx_byte_cnt[13:3]} == tx_pkt_cnt)); //Packet size / 8 == Packet Count
+ assign rx_next_pkt_cond = (rx_byte_cnt[12:3] == bist_max_pkt_size[12:3]) ||
+ (bist_size_ramp && ({7'h0, rx_byte_cnt[13:3]} == rx_pkt_cnt));
+
+ wire tx_test_done_cond, rx_test_done_cond;
+ assign tx_test_done_cond = (tx_pkt_cnt == bist_max_pkts);
+ assign rx_test_done_cond = (rx_pkt_cnt == bist_max_pkts);
+
+ reg [63:0] tx_data_next, rx_data_exp;
+ always @(*) begin
+ case (test_pattern)
+ TEST_PATT_ZERO_ONE: begin
+ tx_data_next <= {8{tx_byte_cnt[3] ? 8'h00 : 8'hFF}};
+ rx_data_exp <= {8{rx_byte_cnt[3] ? 8'h00 : 8'hFF}};
+ end
+ TEST_PATT_CHECKERBOARD: begin
+ tx_data_next <= {32{tx_byte_cnt[3] ? 2'b01 : 2'b10}};
+ rx_data_exp <= {32{rx_byte_cnt[3] ? 2'b01 : 2'b10}};
+ end
+ TEST_PATT_COUNT: begin
+ tx_data_next <= {8{tx_byte_cnt[10:3]}};
+ rx_data_exp <= {8{rx_byte_cnt[10:3]}};
+ end
+ TEST_PATT_COUNT_INV: begin
+ tx_data_next <= {8{(tx_byte_cnt[3] ? 8'hFF : 8'h00) ^ tx_byte_cnt[10:3]}};
+ rx_data_exp <= {8{(rx_byte_cnt[3] ? 8'hFF : 8'h00) ^ rx_byte_cnt[10:3]}};
+ end
+ default: begin
+ tx_data_next <= 64'd0;
+ rx_data_exp <= 64'd0;
+ end
+ endcase
+ end
+
+ //NOTE: We always attach the max size in the packet header for simplicity.
+ // This will not work with state machines that validate the packet length in the
+ // header with the tlast position.
+ assign tx_cvita_hdr = {4'h0, tx_pkt_cnt[11:0], 2'b00, bist_max_pkt_size, bist_cvita_sid};
+ assign rx_cvita_hdr = {4'h0, rx_pkt_cnt[11:0], 2'b00, bist_max_pkt_size, bist_cvita_sid};
+
+ reg [63:0] o_tdata_fail;
+ assign status_vtr = { //Status at the time of failure
+ o_tdata_fail, //[127:64]
+ test_run_cnt, //[63:40]
+ rx_data_exp[7:0], //[39:32]
+ rx_pkt_cnt, //[31:14]
+ rx_byte_cnt //[13:0]
+ };
+
+ //-------------------------------------------------------
+ // Transmitter
+ //-------------------------------------------------------
+ always @(posedge clk) begin
+ if (reset | (bist_clear & ~rearm_test)) begin
+ tx_delay <= 0;
+ tx_pkt_cnt <= 0;
+ tx_byte_cnt <= 0;
+ i_tdata <= 64'h0;
+ i_tlast <= 1'b0;
+ i_tvalid <= 1'b0;
+ tx_state <= TX_IDLE;
+ end else begin
+ case(tx_state)
+ TX_IDLE: begin
+ tx_delay <= 0;
+ tx_pkt_cnt <= 1;
+ tx_byte_cnt <= 0;
+ i_tdata <= 64'h0;
+ i_tlast <= 1'b0;
+ i_tvalid <= 1'b0;
+ // Run when bist_start asserted.
+ if (bist_start | rearm_test) begin
+ tx_state <= TX_START;
+ test_pattern <= bist_test_patt;
+ end
+ end // case: TX_IDLE
+
+ // START signal is asserted.
+ // Now need to start transmiting a packet.
+ TX_START: begin
+ // At the next clock edge drive first beat of new packet onto HDR bus.
+ i_tlast <= 1'b0;
+ i_tvalid <= 1'b1;
+ tx_byte_cnt <= tx_byte_cnt + 8;
+ i_tdata <= tx_cvita_hdr;
+ tx_state <= TX_ACTIVE;
+ end
+
+ // Valid data is (already) being driven onto the CHDR bus.
+ // i_tlast may also be driven asserted if current data count has reached EOP.
+ // Watch i_tready to see when it's consumed.
+ // When packets are consumed increment data counter or transition state if
+ // EOP has sucsesfully concluded.
+ TX_ACTIVE: begin
+ i_tvalid <= 1'b1; // Always assert tvalid
+ if (i_tready) begin
+ i_tdata <= tx_data_next;
+ // Will this next beat be the last in a packet?
+ if (tx_next_pkt_cond) begin
+ tx_byte_cnt <= 0;
+ i_tlast <= 1'b1;
+ tx_state <= TX_GAP;
+ end else begin
+ tx_byte_cnt <= tx_byte_cnt + 8;
+ i_tlast <= 1'b0;
+ tx_state <= TX_ACTIVE;
+ end
+ end else begin
+ //Keep driving all CHDR bus signals as-is until i_tready is asserted.
+ tx_state <= TX_ACTIVE;
+ end
+ end // case: TX_ACTIVE
+
+ // Force an inter-packet gap between packets in a BIST sequence where tvalid is driven low.
+ // As we leave this state check if all packets in BIST sequence have been generated yet,
+ // and if so go to done state.
+ TX_GAP: begin
+ if (i_tready) begin
+ i_tvalid <= 1'b0;
+ i_tdata <= 64'h0;
+ i_tlast <= 1'b0;
+ tx_pkt_cnt <= tx_pkt_cnt + 1;
+
+ if (tx_test_done_cond) begin
+ tx_state <= TX_DONE;
+ end else begin
+ tx_state <= TX_WAIT;
+ tx_delay <= bist_tx_pkt_delay;
+ end
+ end else begin // if (i_tready)
+ tx_state <= TX_GAP;
+ end
+ end // case: TX_GAP
+
+ // Simulate inter packet gap in real UHD system
+ TX_WAIT: begin
+ if (tx_delay == 0)
+ tx_state <= TX_START;
+ else begin
+ tx_delay <= tx_delay - 1;
+ tx_state <= TX_WAIT;
+ end
+ end
+
+ // Complete test pattern BIST sequence has been transmitted.
+ // Sit in this state until the RX side consumes all packets except
+ // for when the test is running in continuous mode.
+ TX_DONE: begin
+ i_tvalid <= 1'b0;
+ i_tlast <= 1'b0;
+ i_tdata <= 64'd0;
+
+ if (running & ~rearm_test) begin
+ tx_state <= TX_DONE;
+ end else begin
+ tx_state <= TX_IDLE;
+ end
+ end
+ endcase // case (tx_state)
+ end
+ end
+
+ //-------------------------------------------------------
+ // Receiver
+ //-------------------------------------------------------
+ always @(posedge clk) begin
+ if (reset | (bist_clear & ~rearm_test)) begin
+ rx_delay <= 0;
+ rx_pkt_cnt <= 0;
+ rx_byte_cnt <= 0;
+ o_tdata_fail <= 64'h0;
+ o_tready <= 1'b0;
+ error <= ERR_SUCCESS;
+ done <= 1'b0;
+ rx_state <= RX_IDLE;
+ err_timeout <= {ERR_TIMEOUT_LOG2{1'b0}};
+ test_run_cnt <= 0;
+ end else begin
+ case(rx_state)
+ RX_IDLE: begin
+ rx_delay <= 0;
+ rx_pkt_cnt <= 1;
+ rx_byte_cnt <= 0;
+ o_tdata_fail <= 64'h0;
+ o_tready <= 1'b0;
+ error <= ERR_SUCCESS;
+ done <= 1'b0;
+ err_timeout <= {ERR_TIMEOUT_LOG2{1'b0}};
+ // Not accepting data whilst Idle,
+ // switch to active when packet arrives
+ if (o_tvalid) begin
+ o_tready <= 1'b1;
+ rx_state <= RX_ACTIVE;
+ end else begin
+ rx_state <= RX_IDLE;
+ end
+ end
+
+ RX_ACTIVE: begin
+ o_tready <= 1'b1;
+ if (o_tvalid) begin
+ if (o_tdata != (rx_byte_cnt == 0 ? rx_cvita_hdr : rx_data_exp)) begin
+ $display("axis_test_pattern: o_tdata: %x != expected: %x @ time: %d", o_tdata, rx_data_exp, $time);
+ error <= ERR_DATA_MISMATCH;
+ rx_state <= RX_FAIL;
+ o_tdata_fail <= o_tdata;
+ end else if (rx_next_pkt_cond) begin
+ // Last not asserted when it should be!
+ if (~(o_tlast === 1)) begin
+ $display("axis_test_pattern: o_tlast not asserted when it should be @ time: %d", $time);
+ error <= ERR_SIZE_MISMATCH_TOO_LONG;
+ rx_state <= RX_FAIL;
+ end else begin
+ // End of packet, set up to RX next
+ rx_byte_cnt <= 0;
+ rx_pkt_cnt <= rx_pkt_cnt + 1;
+ rx_delay <= bist_rx_samp_delay;
+ if (rx_test_done_cond) begin
+ rx_state <= rearm_test ? RX_IDLE : RX_DONE;
+ error <= ERR_SUCCESS;
+ test_run_cnt <= test_run_cnt + 1;
+ end else begin
+ rx_state <= RX_WAIT;
+ end
+ o_tready <= 1'b0;
+ end
+ end else begin
+ // ...last asserted when it should not be!
+ if (~(o_tlast === 0)) begin
+ $display("axis_test_pattern: o_tlast asserted when it should not be @ time: %d", $time);
+ error <= ERR_SIZE_MISMATCH_TOO_SHORT;
+ rx_state <= RX_FAIL;
+ end else begin
+ // Still in packet body
+ rx_byte_cnt <= rx_byte_cnt + 8;
+ rx_delay <= bist_rx_samp_delay;
+ if (bist_rx_samp_delay == 0) begin
+ rx_state <= RX_ACTIVE;
+ end else begin
+ rx_state <= RX_WAIT;
+ o_tready <= 1'b0;
+ end
+ end
+ end
+ end else begin
+ // Nothing to do this cycle
+ rx_state <= RX_ACTIVE;
+ end
+ end // case: RX_ACTIVE
+
+ // To simulate the radio consuming samples at a steady rate set by the decimation
+ // have a programable delay here
+ RX_WAIT: begin
+ if (rx_delay == 0) begin
+ rx_state <= RX_ACTIVE;
+ o_tready <= 1'b1;
+ end else begin
+ rx_delay <= rx_delay - 1;
+ rx_state <= RX_WAIT;
+ end
+ end
+
+ RX_FAIL: begin
+ //The test has failed but the sender still has packets en route
+ //Consume all of them before asserting done. Packets could be
+ //malformed so just blindly consume lines and count cycles of
+ //gaps. If non-valid cycles are more than 2^ERR_TIMEOUT_LOG2 then stop.
+ o_tready <= 1'b1;
+ if (~o_tvalid) begin
+ if (err_timeout == {ERR_TIMEOUT_LOG2{1'b1}}) begin
+ rx_state <= RX_DONE;
+ end
+ err_timeout <= err_timeout + 1;
+ end
+ end
+
+ RX_DONE: begin
+ o_tready <= 1'b0;
+ done <= 1'b1;
+ //The only way to exit this state is by asserting bist_clear
+ end
+ endcase // case (rx_state)
+ end
+ end
+
+ //-------------------------------------------------------
+ // Status Monitor
+ //-------------------------------------------------------
+ always @(posedge clk) begin
+ if (reset)
+ running <= 1'b0;
+ else if (tx_state == TX_START)
+ running <= 1'b1;
+ else if (rx_state == RX_DONE)
+ running <= 1'b0;
+ end
+
+ always @(posedge clk) begin
+ if (reset | bist_clear)
+ rearm_test <= 1'b0;
+ else if (bist_start & bist_cont)
+ rearm_test <= 1'b1;
+ else if (rx_state == RX_FAIL)
+ rearm_test <= 1'b0;
+ end
+
+ //-------------------------------------------------------
+ // Bandwidth Counter
+ //-------------------------------------------------------
+ generate if (BW_COUNTER) begin
+ reg [47:0] word_count, cyc_count;
+ assign bw_ratio = {word_count, cyc_count};
+
+ //Count number of lines transferred
+ always @(posedge clk) begin
+ if (reset| (bist_clear & ~rearm_test) | bist_start)
+ word_count <= 48'd0;
+ else if (o_tvalid && rx_state == RX_ACTIVE)
+ word_count <= word_count + 48'd1;
+ end
+
+ //Count cycles as long as test is running
+ always @(posedge clk) begin
+ if (reset| (bist_clear & ~rearm_test) | bist_start)
+ cyc_count <= 48'd0;
+ else if (rx_state == RX_ACTIVE || rx_state == RX_WAIT)
+ cyc_count <= cyc_count + 48'd1;
+ end
+ end else begin
+ assign bw_ratio = 96'h0;
+ end endgenerate
+
+endmodule