1//
2// Copyright 2019 Ettus Research, a National Instruments Company
3//
4// SPDX-License-Identifier: LGPL-3.0-or-later
5//
6// Module: axi_ram_fifo_bist_regs
7//
8// Description:
9//
10//   Implements the registers for the RAM FIFO BIST logic.
11//
12// Parameters:
13//
14//   DATA_W   : The width of the data port to use for the AXI4-Stream
15//              interface.
16//
17//   COUNT_W  : Width of internal counters. This must be wide enough so that
18//              word, cycle, and and error counters don't overflow during a
19//              test.
20//
21//   CLK_RATE : The frequency of clk in Hz
22//
23
24module axi_ram_fifo_bist_regs #(
25  parameter DATA_W    = 64,
26  parameter COUNT_W   = 48,
27  parameter CLK_RATE  = 200e6
28) (
29  input clk,
30  input rst,
31
32  //--------------------------------------------------------------------------
33  // CTRL Port
34  //--------------------------------------------------------------------------
35
36  input  wire        s_ctrlport_req_wr,
37  input  wire        s_ctrlport_req_rd,
38  input  wire [19:0] s_ctrlport_req_addr,
39  input  wire [31:0] s_ctrlport_req_data,
40  output reg         s_ctrlport_resp_ack,
41  output reg  [31:0] s_ctrlport_resp_data,
42
43  //--------------------------------------------------------------------------
44  // Control and Status
45  //--------------------------------------------------------------------------
46
47  input wire [COUNT_W-1:0] tx_count,
48  input wire [COUNT_W-1:0] rx_count,
49  input wire [COUNT_W-1:0] error_count,
50  input wire [COUNT_W-1:0] cycle_count,
51
52  output wire [COUNT_W-1:0] num_words,
53
54  output reg                start,
55  output reg                stop,
56  output reg                clear,
57  output reg                continuous,
58  input wire                running
59);
60
61  `include "axi_ram_fifo_regs.vh"
62
63  localparam BYTES_PER_WORD = DATA_W/8;
64  localparam WORD_SHIFT     = $clog2(BYTES_PER_WORD);
65
66  // Make sure DATA_W is a power of 2, or else the word/byte count conversion
67  // logic won't be correct.
68  if (2**$clog2(DATA_W) != DATA_W) begin
69    DATA_W_must_be_a_power_of_2();
70  end
71
72  // The register logic currently assumes that COUNT_W is at least 33 bits.
73  if (COUNT_W <= 32) begin
74    COUNT_W_must_be_larger_than_32();
75  end
76
77  wire [19:0] word_addr;
78  wire [63:0] tx_byte_count;
79  wire [63:0] rx_byte_count;
80  reg  [63:0] num_bytes = 0;
81
82  reg [31:0] tx_byte_count_hi = 0;
83  reg [31:0] rx_byte_count_hi = 0;
84  reg [31:0] error_count_hi   = 0;
85  reg [31:0] cycle_count_hi   = 0;
86
87  // Only use the word address to simplify address decoding logic
88  assign word_addr = {s_ctrlport_req_addr[19:2], 2'b00 };
89
90  // Convert between words and bytes
91  assign tx_byte_count = tx_count  << WORD_SHIFT;
92  assign rx_byte_count = rx_count  << WORD_SHIFT;
93  assign num_words     = num_bytes >> WORD_SHIFT;
94
95
96  always @(posedge clk) begin
97    if (rst) begin
98      s_ctrlport_resp_ack <= 0;
99      start               <= 0;
100      stop                <= 0;
101      continuous          <= 0;
102      clear               <= 0;
103      num_bytes           <= 0;
104    end else begin
105      // Default values
106      s_ctrlport_resp_ack <= 0;
107      start <= 0;
108      stop  <= 0;
109      clear <= 0;
110
111      //-----------------------------------------------------------------------
112      // Read Logic
113      //-----------------------------------------------------------------------
114
115      if (s_ctrlport_req_rd) begin
116        case (word_addr)
117          REG_BIST_CTRL : begin
118            s_ctrlport_resp_data                       <= 0;
119            s_ctrlport_resp_data[REG_BIST_RUNNING_POS] <= running;
120            s_ctrlport_resp_data[REG_BIST_CONT_POS]    <= continuous;
121            s_ctrlport_resp_ack                        <= 1;
122          end
123          REG_BIST_CLK_RATE : begin
124            s_ctrlport_resp_data <= CLK_RATE;
125            s_ctrlport_resp_ack  <= 1;
126          end
127          REG_BIST_NUM_BYTES_LO : begin
128            s_ctrlport_resp_data <= num_bytes[31:0];
129            s_ctrlport_resp_ack  <= 1;
130          end
131          REG_BIST_NUM_BYTES_HI : begin
132            s_ctrlport_resp_data <= num_bytes[63:32];
133            s_ctrlport_resp_ack  <= 1;
134          end
135          REG_BIST_TX_BYTE_COUNT_LO : begin
136            s_ctrlport_resp_data <= tx_byte_count[31:0];
137            tx_byte_count_hi     <= tx_byte_count[63:32];
138            s_ctrlport_resp_ack  <= 1;
139          end
140          REG_BIST_TX_BYTE_COUNT_HI : begin
141            s_ctrlport_resp_data <= tx_byte_count_hi;
142            s_ctrlport_resp_ack  <= 1;
143          end
144          REG_BIST_RX_BYTE_COUNT_LO : begin
145            s_ctrlport_resp_data           <= rx_byte_count[31:0];
146            rx_byte_count_hi[COUNT_W-33:0] <= rx_byte_count[COUNT_W-1:32];
147            s_ctrlport_resp_ack            <= 1;
148          end
149          REG_BIST_RX_BYTE_COUNT_HI : begin
150            s_ctrlport_resp_data <= rx_byte_count_hi;
151            s_ctrlport_resp_ack  <= 1;
152          end
153          REG_BIST_ERROR_COUNT_LO : begin
154            s_ctrlport_resp_data         <= error_count[31:0];
155            error_count_hi[COUNT_W-33:0] <= error_count[COUNT_W-1:32];
156            s_ctrlport_resp_ack          <= 1;
157          end
158          REG_BIST_ERROR_COUNT_HI : begin
159            s_ctrlport_resp_data <= 0;
160            s_ctrlport_resp_data <= error_count_hi;
161            s_ctrlport_resp_ack  <= 1;
162          end
163          REG_BIST_CYCLE_COUNT_LO : begin
164            s_ctrlport_resp_data         <= cycle_count[31:0];
165            cycle_count_hi[COUNT_W-33:0] <= cycle_count[COUNT_W-1:32];
166            s_ctrlport_resp_ack          <= 1;
167          end
168          REG_BIST_CYCLE_COUNT_HI : begin
169            s_ctrlport_resp_data <= 0;
170            s_ctrlport_resp_data <= cycle_count_hi;
171            s_ctrlport_resp_ack  <= 1;
172          end
173        endcase
174      end
175
176
177      //-----------------------------------------------------------------------
178      // Write Logic
179      //-----------------------------------------------------------------------
180
181      if (s_ctrlport_req_wr) begin
182        case (word_addr)
183          REG_BIST_CTRL : begin
184            start      <= s_ctrlport_req_data[REG_BIST_START_POS];
185            stop       <= s_ctrlport_req_data[REG_BIST_STOP_POS];
186            clear      <= s_ctrlport_req_data[REG_BIST_CLEAR_POS];
187            continuous <= s_ctrlport_req_data[REG_BIST_CONT_POS];
188            s_ctrlport_resp_ack <= 1;
189          end
190          REG_BIST_NUM_BYTES_LO : begin
191            // Update only the word-count portion
192            num_bytes[31:WORD_SHIFT] <= s_ctrlport_req_data[31:WORD_SHIFT];
193            s_ctrlport_resp_ack <= 1;
194          end
195          REG_BIST_NUM_BYTES_HI : begin
196            num_bytes[COUNT_W-1:32] <= s_ctrlport_req_data[COUNT_W-33:0];
197            s_ctrlport_resp_ack <= 1;
198          end
199        endcase
200      end
201
202    end
203  end
204
205endmodule
206
207