|
| 1 | +// *************************************************************************** |
| 2 | +// *************************************************************************** |
| 3 | +// Copyright (C) 2025 Analog Devices, Inc. All rights reserved. |
| 4 | +// |
| 5 | +// In this HDL repository, there are many different and unique modules, consisting |
| 6 | +// of various HDL (Verilog or VHDL) components. The individual modules are |
| 7 | +// developed independently, and may be accompanied by separate and unique license |
| 8 | +// terms. |
| 9 | +// |
| 10 | +// The user should read each of these license terms, and understand the |
| 11 | +// freedoms and responsibilities that he or she has by using this source/core. |
| 12 | +// |
| 13 | +// This core is distributed in the hope that it will be useful, but WITHOUT ANY |
| 14 | +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR |
| 15 | +// A PARTICULAR PURPOSE. |
| 16 | +// |
| 17 | +// Redistribution and use of source or resulting binaries, with or without modification |
| 18 | +// of this file, are permitted under one of the following two license terms: |
| 19 | +// |
| 20 | +// 1. The GNU General Public License version 2 as published by the |
| 21 | +// Free Software Foundation, which can be found in the top level directory |
| 22 | +// of this repository (LICENSE_GPL2), and also online at: |
| 23 | +// <https://www.gnu.org/licenses/old-licenses/gpl-2.0.html> |
| 24 | +// |
| 25 | +// OR |
| 26 | +// |
| 27 | +// 2. An ADI specific BSD license, which can be found in the top level directory |
| 28 | +// of this repository (LICENSE_ADIBSD), and also on-line at: |
| 29 | +// https://github.com/analogdevicesinc/hdl/blob/main/LICENSE_ADIBSD |
| 30 | +// This will allow to generate bit files and not release the source code, |
| 31 | +// as long as it attaches to an ADI device. |
| 32 | +// |
| 33 | +// *************************************************************************** |
| 34 | +// *************************************************************************** |
| 35 | + |
| 36 | +`timescale 1ns/100ps |
| 37 | + |
1 | 38 | module spi_engine_execution_shiftreg_data_assemble #(
|
2 |
| - parameter ALL_ACTIVE_LANE_MASK = 8'hFF, |
3 |
| - parameter DATA_WIDTH = 8, |
4 |
| - parameter NUM_OF_SDIO = 1, |
5 |
| - parameter [2:0] CMD_WRITE = 3'b010 |
| 39 | + |
| 40 | + parameter ALL_ACTIVE_LANE_MASK = 8'hFF, |
| 41 | + parameter DATA_WIDTH = 8, |
| 42 | + parameter NUM_OF_SDIO = 1, |
| 43 | + parameter [2:0] CMD_WRITE = 3'b010 |
6 | 44 | ) (
|
7 |
| - input clk, |
8 |
| - input resetn, |
9 |
| - input [(DATA_WIDTH)-1:0] data, |
10 |
| - input data_ready, |
11 |
| - input data_valid, |
12 |
| - input [15:0] current_cmd, |
13 |
| - input exec_sdo_lane_cmd, |
14 |
| - input [7:0] lane_mask, |
15 |
| - input idle_state, |
16 |
| - input [7:0] left_aligned, |
17 |
| - input transfer_active, |
18 |
| - input trigger_tx, |
19 |
| - input first_bit, |
20 |
| - input sdo_enabled, |
21 |
| - output [(NUM_OF_SDIO * DATA_WIDTH)-1:0] data_assembled, |
22 |
| - output last_handshake |
| 45 | + input clk, |
| 46 | + input resetn, |
| 47 | + input [(DATA_WIDTH)-1:0] data, |
| 48 | + input data_ready, |
| 49 | + input data_valid, |
| 50 | + input [15:0] current_cmd, |
| 51 | + input exec_sdo_lane_cmd, |
| 52 | + input [7:0] lane_mask, |
| 53 | + input idle_state, |
| 54 | + input [7:0] left_aligned, |
| 55 | + input transfer_active, |
| 56 | + input trigger_tx, |
| 57 | + input first_bit, |
| 58 | + input sdo_enabled, |
| 59 | + output [(NUM_OF_SDIO * DATA_WIDTH)-1:0] data_assembled, |
| 60 | + output last_handshake |
23 | 61 | );
|
24 | 62 |
|
25 |
| -// This module is responsible to align data for different lane masks |
26 |
| -// if lane_mask has all of its SDOs activated, then it allows prefetch data |
27 |
| -// if not, non activated serial lines have their data fulfilled with idle_state and buffer the remaining activated lines |
28 |
| -// also, in this mode it is not possible to prefetch data |
29 |
| - |
30 |
| -reg last_handshake_int; |
31 |
| -reg [(NUM_OF_SDIO * DATA_WIDTH)-1:0] aligned_data; |
32 |
| -reg [ (DATA_WIDTH)-1:0] data_reg; |
33 |
| -reg [ 3:0] count_active_lanes = 0; |
| 63 | + // This module is responsible to align data for different lane masks |
| 64 | + // if lane_mask has all of its SDOs activated, then it allows prefetch data |
| 65 | + // if not, non activated serial lines have their data fulfilled with idle_state and buffer the remaining activated lines |
| 66 | + // also, in this mode it is not possible to prefetch data |
34 | 67 |
|
35 |
| -wire sdo_toshiftreg = (transfer_active && trigger_tx && first_bit && sdo_enabled); |
| 68 | + reg last_handshake_int; |
| 69 | + reg [(NUM_OF_SDIO * DATA_WIDTH)-1:0] aligned_data; |
| 70 | + reg [ (DATA_WIDTH)-1:0] data_reg; |
| 71 | + reg [ 3:0] count_active_lanes = 0; |
| 72 | + reg [ 3:0] num_active_lanes = NUM_OF_SDIO; |
| 73 | + reg [ 3:0] lane_index = 0; |
| 74 | + reg [ 3:0] lane_index_d = 0; |
| 75 | + reg [ 3:0] valid_indices [0:7]; |
36 | 76 |
|
37 |
| -reg [3:0] num_active_lanes = NUM_OF_SDIO; |
38 |
| -reg [3:0] lane_index = 0; |
39 |
| -reg [3:0] lane_index_d = 0; |
40 |
| -integer valid_index = 0; |
41 |
| -reg [3:0] valid_indices [0:7]; |
| 77 | + wire sdo_toshiftreg = (transfer_active && trigger_tx && first_bit && sdo_enabled); |
| 78 | + integer valid_index = 0; |
42 | 79 |
|
43 |
| -assign data_assembled = aligned_data; |
44 |
| -assign last_handshake = last_handshake_int; |
| 80 | + assign data_assembled = aligned_data; |
| 81 | + assign last_handshake = last_handshake_int; |
45 | 82 |
|
46 |
| -// register data |
47 |
| -always @(posedge clk) begin |
| 83 | + // register data |
| 84 | + always @(posedge clk) begin |
48 | 85 | if (resetn == 1'b0) begin
|
49 |
| - data_reg <= {DATA_WIDTH{idle_state}}; |
| 86 | + data_reg <= {DATA_WIDTH{idle_state}}; |
50 | 87 | end else begin
|
51 |
| - if (data_ready && data_valid) begin |
52 |
| - data_reg <= data; |
53 |
| - end |
| 88 | + if (data_ready && data_valid) begin |
| 89 | + data_reg <= data; |
| 90 | + end |
54 | 91 | end
|
55 |
| -end |
| 92 | + end |
56 | 93 |
|
57 |
| -// Align data to have its bits on the MSB bits |
58 |
| -// data is left shifted left_aligned times, where left_aligned equals to DATA_WIDTH - word_length |
59 |
| -// word_length comes from the dynamic transfer length register |
60 |
| -always @(posedge clk) begin |
| 94 | + // Align data to have its bits on the MSB bits |
| 95 | + // data is left shifted left_aligned times, where left_aligned equals to DATA_WIDTH - word_length |
| 96 | + // word_length comes from the dynamic transfer length register |
| 97 | + always @(posedge clk) begin |
61 | 98 | if (resetn == 1'b0) begin
|
62 |
| - aligned_data <= {(NUM_OF_SDIO * DATA_WIDTH){idle_state}}; |
| 99 | + aligned_data <= {(NUM_OF_SDIO * DATA_WIDTH){idle_state}}; |
63 | 100 | end else begin
|
64 |
| - aligned_data[valid_index * DATA_WIDTH+:DATA_WIDTH] <= data_reg << left_aligned; |
| 101 | + aligned_data[valid_index * DATA_WIDTH+:DATA_WIDTH] <= data_reg << left_aligned; |
65 | 102 | end
|
66 |
| -end |
| 103 | + end |
67 | 104 |
|
68 |
| -// data line counter and stores activated lines |
69 |
| -// it returns valid_indices array necessary for correct buffering of data |
70 |
| -reg [3:0] i; |
71 |
| -reg [3:0] j; |
72 |
| -reg [3:0] mask_index; |
73 |
| -always @(posedge clk) begin |
| 105 | + // data line counter and stores activated lines |
| 106 | + // it returns valid_indices array necessary for correct buffering of data |
| 107 | + reg [3:0] i; |
| 108 | + reg [3:0] j; |
| 109 | + reg [3:0] mask_index; |
| 110 | + always @(posedge clk) begin |
74 | 111 | if (resetn == 1'b0) begin
|
75 |
| - num_active_lanes <= NUM_OF_SDIO; |
76 |
| - mask_index <= 0; |
77 |
| - j <= 0; |
| 112 | + num_active_lanes <= NUM_OF_SDIO; |
| 113 | + mask_index <= 0; |
| 114 | + j <= 0; |
78 | 115 | end else begin
|
79 |
| - if (exec_sdo_lane_cmd) begin |
80 |
| - count_active_lanes = 0; |
81 |
| - i = 0; |
82 |
| - j <= 0; |
83 |
| - mask_index <= 0; |
84 |
| - for (i = 0; i < NUM_OF_SDIO; i = i + 1) begin |
85 |
| - count_active_lanes = count_active_lanes + current_cmd[i]; |
86 |
| - end |
87 |
| - num_active_lanes <= count_active_lanes; |
88 |
| - end else begin |
89 |
| - if (j < NUM_OF_SDIO) begin |
90 |
| - if (lane_mask[j]) begin |
91 |
| - valid_indices[mask_index] <= j; |
92 |
| - mask_index <= mask_index + 1; |
93 |
| - end |
94 |
| - j <= j + 1; |
95 |
| - end |
| 116 | + if (exec_sdo_lane_cmd) begin |
| 117 | + count_active_lanes = 0; |
| 118 | + i = 0; |
| 119 | + j <= 0; |
| 120 | + mask_index <= 0; |
| 121 | + for (i = 0; i < NUM_OF_SDIO; i = i + 1) begin |
| 122 | + count_active_lanes = count_active_lanes + current_cmd[i]; |
| 123 | + end |
| 124 | + num_active_lanes <= count_active_lanes; |
| 125 | + end else begin |
| 126 | + if (j < NUM_OF_SDIO) begin |
| 127 | + if (lane_mask[j]) begin |
| 128 | + valid_indices[mask_index] <= j; |
| 129 | + mask_index <= mask_index + 1; |
| 130 | + end |
| 131 | + j <= j + 1; |
96 | 132 | end
|
| 133 | + end |
97 | 134 | end
|
98 |
| -end |
| 135 | + end |
99 | 136 |
|
100 |
| -// handshake counter |
101 |
| -// it will increment up to num_active_lanes |
102 |
| -// The last handshake is used by external logic to enable sdo_io_ready |
103 |
| -// retrieves the correct lane_index used to align data |
104 |
| -always @(posedge clk) begin |
| 137 | + // handshake counter |
| 138 | + // it will increment up to num_active_lanes |
| 139 | + // The last handshake is used by external logic to enable sdo_io_ready |
| 140 | + // retrieves the correct lane_index used to align data |
| 141 | + always @(posedge clk) begin |
105 | 142 | if (resetn == 1'b0) begin
|
106 |
| - lane_index <= 0; |
107 |
| - lane_index_d <= 0; |
108 |
| - valid_index <= 0; |
109 |
| - last_handshake_int <= 1'b0; |
| 143 | + lane_index <= 0; |
| 144 | + lane_index_d <= 0; |
| 145 | + valid_index <= 0; |
| 146 | + last_handshake_int <= 1'b0; |
110 | 147 | end else begin
|
111 |
| - if (data_ready && data_valid) begin |
112 |
| - last_handshake_int <= (lane_index == (num_active_lanes-1)) ? 1'b1 : 1'b0; |
113 |
| - if (lane_index < (num_active_lanes-1)) begin |
114 |
| - lane_index <= lane_index + 1; |
115 |
| - end else begin |
116 |
| - lane_index <= 0; |
117 |
| - end |
118 |
| - lane_index_d <= lane_index; |
119 |
| - valid_index <= (lane_mask == ALL_ACTIVE_LANE_MASK) ? lane_index : valid_indices[lane_index_d]; |
120 |
| - end else if (sdo_toshiftreg) begin |
121 |
| - last_handshake_int <= 1'b0; |
| 148 | + if (data_ready && data_valid) begin |
| 149 | + last_handshake_int <= (lane_index == (num_active_lanes-1)) ? 1'b1 : 1'b0; |
| 150 | + if (lane_index < (num_active_lanes-1)) begin |
| 151 | + lane_index <= lane_index + 1; |
| 152 | + end else begin |
| 153 | + lane_index <= 0; |
122 | 154 | end
|
| 155 | + lane_index_d <= lane_index; |
| 156 | + valid_index <= (lane_mask == ALL_ACTIVE_LANE_MASK) ? lane_index : valid_indices[lane_index_d]; |
| 157 | + end else if (sdo_toshiftreg) begin |
| 158 | + last_handshake_int <= 1'b0; |
| 159 | + end |
123 | 160 | end
|
124 |
| -end |
| 161 | + end |
125 | 162 |
|
126 |
| -endmodule |
| 163 | + endmodule |
0 commit comments