-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathcsi_rx_align_word.sv
181 lines (164 loc) · 6.94 KB
/
csi_rx_align_word.sv
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
//========================================================================
// openeye-CamSI * NLnet-sponsored open-source core for Camera I/F with ISP
//------------------------------------------------------------------------
// Copyright (C) 2024 Chili.CHIPS*ba
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// https://opensource.org/license/bsd-3-clause
//------------------------------------------------------------------------
// Description: This modules receives aligned bytes with their valid flags
// to then COMPENSATE FOR UP TO 2 CLOCK CYCLES OF SKEW BETWEEN LANES.
//
// It also resets byte aligners' sync stat us (via 'packet_done_out')
// when SYNC pattern is not found by byte aligners on all lanes.
//
// Similarly to the byte aligner, it locks the alignment taps when a
// valid word is found and until 'packet_done' is asserted.
//
//------------------------------------------------------------------------
// Here is an illustration of 2-lane case with 2-clock-cycle skew between
// them. This RTL is written to work for any number of lanes.
//
// clk | 1 | 2 | |n-1| n |
// |___|___|_________| | |
// lane0 vld_in __| |_____________
// data_in |<===============> |
// |
// |<--2-->|_________________
// lane1 vld_in __________| |_____
// data_in <===============>
// | | |
// taps 0 1 2
// _________
// vld_in_all __________| |_____________
//
// In this case, taps[0]=2, taps[1]=0, i.e. take:
// - lane0 byte after delay by 2 clocks
// - lane1 byte without any delay
//========================================================================
module csi_rx_align_word
import top_pkg::*;
(
input logic byte_clock, // byte clock in
input logic reset, // active-1 synchronous reset
input logic enable, // active-1 enable
input logic packet_done, // packet done input from packet handler entity
input logic wait_for_sync, // whether or not to be looking for an alignment
input lane_data_t word_in, // unaligned word from the byte aligners
input lane_vld_t valid_in, // valid flags from byte aligners
output logic packet_done_out, // 'packet_done' output to byte aligners
output lane_data_t word_out, // aligned word out to packet handler
output logic valid_out // goes high once alignment is valid: First word
); // with 'valid_out=1' is the CSI packet header
//--------------------------------
logic [(NUM_LANE*8)-1:0] word_dly_0;
logic [(NUM_LANE*8)-1:0] word_dly_1;
logic [(NUM_LANE*8)-1:0] word_dly_2;
logic [NUM_LANE-1:0] valid_dly_0;
logic [NUM_LANE-1:0] valid_dly_1;
logic [NUM_LANE-1:0] valid_dly_2;
`ifdef ICARUS
typedef logic [NUM_LANE-1:0] [4] taps_t;
`else
typedef logic [NUM_LANE-1:0] taps_t [4];
`endif
taps_t taps;
taps_t next_taps;
logic valid = 1'b0;
logic next_valid;
logic invalid_start = 1'b0;
logic [(NUM_LANE*8)-1:0] aligned_word;
// Process handling the word_clock
always_ff @(posedge byte_clock) begin
if (reset == 1'b1) begin
valid <= 0;
`ifdef ICARUS
taps = '0; // Reset taps
`else
taps = '{2'b00, 2'b00, 2'b00, 2'b00}; // Reset taps
`endif
end else if (enable == 1'b1) begin
word_dly_0 <= word_in;
valid_dly_0 <= valid_in;
word_dly_1 <= word_dly_0;
valid_dly_1 <= valid_dly_0;
word_dly_2 <= word_dly_1;
valid_dly_2 <= valid_dly_1;
valid_out <= valid;
word_out <= aligned_word;
if ({next_valid, valid, wait_for_sync} == 3'b101) begin
valid <= 1'b1;
taps <= next_taps;
end else if (packet_done == 1'b1) begin
valid <= 1'b0;
end
end
end
// Process handling valid delay logic and tap calculation
always_comb begin
logic next_valid_int;
logic is_triggered = 1'b0;
next_valid_int = &valid_dly_0;
is_triggered = 1'b0;
for (int i = 0; i <= NUM_LANE-1; i++) begin
if ({valid_dly_0[i], valid_dly_1[i], valid_dly_2[i]} == 3'b111) begin
is_triggered = 1'b1;
end
end
invalid_start <= (!next_valid_int) && is_triggered;
next_valid <= next_valid_int;
for (int i = 0; i <= NUM_LANE-1; i++) begin
if (valid_dly_2[i]) begin
next_taps[i] = 2'b10;
end else if (valid_dly_1[i]) begin
next_taps[i] = 2'b01;
end else begin
next_taps[i] = 2'b00;
end
end
end
// Process handling word alignment
always_comb begin
for (int i = 0; i <= NUM_LANE-1; i++) begin
case (taps[i])
2'b10: aligned_word[(8*i)+7 -: 8] = word_dly_2[(8*i)+7 -: 8];
2'b01: aligned_word[(8*i)+7 -: 8] = word_dly_1[(8*i)+7 -: 8];
default: aligned_word[(8*i)+7 -: 8] = word_dly_0[(8*i)+7 -: 8];
endcase
end
end
// Update packet_done_out
assign packet_done_out = packet_done || invalid_start;
endmodule: csi_rx_align_word
/*
------------------------------------------------------------------------------
Version History:
------------------------------------------------------------------------------
2024/2/18 Armin Zunic: Initial creation
*/