x393  1.0
FPGAcodeforElphelNC393camera
cmprs_afi_mux_ptr.v
Go to the documentation of this file.
1 
40 `timescale 1ns/1ps
41 
43  input hclk, // global clock to run axi_hp @ 150MHz, shared by all compressor channels
44  // Write dual port 8x27 channel start address/length RAM
45  input [26:0] sa_len_di, // data to write per-channle buffer sa/length in chunks
46  input [ 2:0] sa_len_wa, // channel address to write sa/lengths
47  input sa_len_we, // write enable sa/length data
48 
49  input en, // 0 - resets, 0->1 resets all pointers. While reset allows write response
50  input [ 3:0] reset_pointers, // per-channel - reset pointers
51  input pre_busy_w, // combinatorial signal - one before busy[0] (depends on ptr_resetting)
52  input [ 1:0] pre_winner_channel, // channel that won arbitration for AXI access, valid 1 cycle ahead of @ pre_busy_w
53 // input [ 1:0] winner_channel, // channel that won arbitration for AXI access, valid @ pre_busy_w
54  input need_to_bother, // wants to start access if address and data FIFO permit
55  input [1:0] chunk_inc_want_m1, // how much to increment chunk pointer (0..3) +1 - valid with busy[0] (w/o rollover)
56 
57  input last_burst_in_frame, // valid with busy[0] (last_burst_in_frame<=last_chunk_w[winner2])
58  // last_burst_in_frame is invalid when rollover splits burst in 2
59  input [ 3:0] busy, // one cycle less than sending 1-4 bursts, [1] - delayed by 1, [2] - by 2
60  output ptr_resetting, // pointers will be reset next cycle (2-cycle-long pulse)
61  output reg [26:0] chunk_addr, // chunk absolute address, valid with busy[1]
62  input [ 2:0] chunk_ptr_ra, // chunk pointer read address {eof, chn[1:0]}
63  output [26:0] chunk_ptr_rd, // chunk pointer read data (non-registered
64 // output [ 2:0] max_inc // maximal increment to rollover (limited by 4)
65  output [ 2:0] max_wlen // maximal wlen[3:2], MSB - limited by rollover
66 
67 );
68  reg [3:0] reset_rq; // request to reset pointers when ready
69  reg [3:0] reset_rq_pri; // one-hot reset rq
70  wire [1:0] reset_rq_enc; // encoded reset_rq_pri
72  reg [1:0] resetting; // resetting chunk_pointer and eof_pointer
73  reg [2:0] ptr_wa; // pointer memory write port address, msb - eof/current, 2 LSB - channel
74  reg ptr_we; // pointer memory write enable
75  reg [26:0] ptr_ram[0:7]; // pointer (current and eof) memory (in 32-byte chunks
76  wire [26:0] ptr_ram_di; // data to be written to ptr_ram
77  reg [26:0] sa_len_ram[0:7]; // start chunk/num cunks in a buffer (write port @mclk)
78  reg [26:0] chunk_ptr_inc; // incremented by 1..4 chunk pointer
79 // reg [27:0] rollover_r; // incremented chunk pointer, decremented by length (MSB - sign)
80  reg en_d; //enable delayed by 1 cycle
81  wire [ 2:0] sa_len_ra; // start/len read address (0..3 - start addresses, 4..7 - lengths)
82 
83  reg [ 2:0] max_inc_ram[0:3]; // maximal increment to rollover (limited by 4)
84  wire [ 1:0] pre_chunk_inc_m1;
85  reg [ 2:0] chunk_inc;
86  wire [26:0] chunks_to_rollover;
87 
88  reg [3:0] chunks_to_rollover_r; // [3] >=8
89 // SuppressWarnings VEditor unused
93  reg [1:0] max_inc_ram_wa;
94  wire rollover_w; // this cycle causes rollover - valid at pre_busy_w
95  reg rollover_r; // this cycle causes rollover - valid at busy[0] and late
96  reg [ 1:0] winner_channel; // channel that won arbitration for AXI access, valid @ pre_busy_w
97 
98 
99  wire ptr_ram_wa = ptr_ram[ptr_wa]; // SuppressThisWarning VEditor debug - just to view
100 // wire [2:0] max_wlen_di; // data to write to max_inc_ram and bypass register
101  reg [2:0] max_wlen_r; // memory registered output
102  reg [2:0] max_wlen_same; // used to bypass max_inc_ram for the same channel
103 // reg use_same_max_wlen; // valid @ pre_busy_w
104  reg [1:0] last_max_written; // channel for which max_wlen was written to RAM
105 
106  assign ptr_resetting = resetting[0];
107  assign sa_len_ra= {busy[1],ptr_wa[1:0]};
108 
109  assign reset_rq_enc = {reset_rq_pri[3] | reset_rq_pri[2],
110  reset_rq_pri[3] | reset_rq_pri[1]};
111  assign ptr_ram_di= (resetting[1] ||rollover_r) ? 27'b0 : chunk_ptr_inc ;
112 
114  assign start_resetting_w = en && !busy[0] && !resetting[0] && (|reset_rq) && !need_to_bother;
115 
116 /// assign max_wlen = max_inc_ram[winner_channel]; // valid @pre_busy_w
117 // assign max_wlen = (last_max_written == winner_channel) ? (max_inc_ram_we? max_wlen_di: max_wlen_same) :max_wlen_r ; // valid @pre_busy_w
118  assign max_wlen = (last_max_written == winner_channel) ? max_wlen_same :max_wlen_r ; // valid @pre_busy_w
119 
120 //chunk_inc_want_m1
122  assign rollover_w = !max_wlen[2] && (max_wlen[1:0] <= chunk_inc_want_m1);
123 
126 // assign max_wlen_di = (|chunks_to_rollover_m1[3:2])?3'h7:{1'b0,chunks_to_rollover_m1[1:0]};
127  // 1 cycle ahead of chunks_to_rollover_m1
129  always @ (posedge hclk) begin
131  max_wlen_r <= max_inc_ram[pre_winner_channel]; // valid @pre_busy_w
132  if (!en) last_max_written <= 0;
133  else if (ptr_we & ~ptr_wa[2]) last_max_written <= ptr_wa[1:0];
134 
135  en_d <= en;
136  // ===== calculate and rollover channel addresses ====
137  // clear (during "resetting" or update 8x27 RAM that holds chunk pointers for the current burst and currenty frame
138  // uses (reads) additional memory with per-channel start addresses and lengths (both measured in 32-byte chunks
139  // read port of the ptr_ram will be used to monitor pointers through the status network
140  // TODO: Make sure correct RAM modules are inferred
141  // write length RAM
143  if (start_resetting_w) reset_rq_pri <= {reset_rq[3] & ~(|reset_rq[2:0]),
144  reset_rq[2] & ~(|reset_rq[1:0]),
145  reset_rq[1] & ~reset_rq[0],
146  reset_rq[0]};
147 
148  if (en && !en_d) reset_rq <= 4'hf;
149  else reset_rq <= reset_pointers | (reset_rq & ~({4{resetting[0] &~ resetting[1]}} & reset_rq_pri));
150 
151  if (!en) resetting <= 0;
152  else resetting <= {resetting[0], start_resetting_w | (resetting[0] & ~resetting[1])};
153 
154  if (resetting == 2'b1) ptr_wa[1:0] <= reset_rq_enc;
155  else if (pre_busy_w) ptr_wa[1:0] <= winner_channel;
156 
157  if (start_resetting_w || pre_busy_w) ptr_wa[2] <= 0;
158  else if (ptr_we) ptr_wa[2] <= 1;
159 
160  ptr_we <= resetting[0] || // a pair of cycles to reset chunk pointer and frame chunk pointer
161  (busy[1] && !busy[2]) || // always update chunk pointer
162  (busy[2] && !busy[3] && last_burst_in_frame); // optionally update frame chunk pointer (same value)
163 
164  if (busy[0] && !busy[1]) begin // first clock of busy
165  // calculate full address for current AXI burst (valid 1 clk after busy)
168  end
169 // if (busy[1] && !busy[2]) begin // first clock of busy
170 // chunk_ptr_rovr <={1'b0,chunk_ptr_inc} - {1'b0,sa_len_ram[sa_len_ra]}; // sa_len_ra now points at length
171 // end
172  // write to ptr_ram (1 or 2 locations - if eof)
173  if (ptr_we) ptr_ram[ptr_wa] <= ptr_ram_di;
174 
175  if (pre_busy_w) chunk_inc <= {1'b0, pre_chunk_inc_m1} + 1;
176 
178 
179 // wire [26:0] chunks_to_rollover;
180 
181 // reg [3:0] chunks_to_rollover_r; // [3] >=8
183 
184  max_inc_ram_we <= ptr_we & ~ptr_wa[2];
185  max_inc_ram_wa <= ptr_wa[1:0];
186 
187  // set 1 cycle earlier
188  if (ptr_we & ~ptr_wa[2]) max_wlen_same <= (|pre_chunks_to_rollover_m1[3:2])?3'h7:{1'b0,pre_chunks_to_rollover_m1[1:0]};
189 
190  if (max_inc_ram_we) begin
191  max_inc_ram[max_inc_ram_wa] <= max_wlen_same; // max_wlen_di; // (|chunks_to_rollover_m1[3:2])?3'h7:{1'b0,chunks_to_rollover_m1[1:0]};
192 // max_wlen_same <= max_wlen_di;
193  end
194 
195 
196  end
197 endmodule
198 
199 
[ 1:0] 262pre_winner_channel
[0:3] 285max_inc_ramreg[2:0]
289chunks_to_rollover_rreg[3:0]
[0:7] 279ptr_ramreg[26:0]
288chunks_to_rolloverwire[26:0]
291pre_chunks_to_rollover_m1wire[3:0]
[0:7] 281sa_len_ramreg[26:0]
290chunks_to_rollover_m1wire[3:0]
286pre_chunk_inc_m1wire[1:0]
reg [26:0] 268chunk_addr