x393  1.0
FPGAcodeforElphelNC393camera
cmprs_afi_mux_ptr_wresp.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 4x27 channel length RAM (shadows 1/2 of the similar RAM for main pointers)
45  input [26:0] length_di, // data to write per-channle buffer length in chunks
46  input [ 1:0] length_wa, // channel address to write lengths
47  input length_we, // write enable 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 
52  input [ 2:0] chunk_ptr_ra, // chunk pointer read address {eof, chn[1:0]}
53  output [26:0] chunk_ptr_rd, // chunk pointer read data (non-registered
54 
55  output reg [ 3:0] eof_written, // per-channel end of frame confirmed written to system memory by write response
56 
57  // AFI write response channels
58  input afi_bvalid,
59  output afi_bready,
60  input [ 5:0] afi_bid // encodes channel, eof, and burst size minus 1 in chunks (0..3)
61 
62 );
63  reg [3:0] reset_rq; // request to reset pointers when ready
64  reg [3:0] reset_rq_pri; // one-hot reset rq
65  wire [1:0] reset_rq_enc; // encoded reset_rq_pri
67  reg [1:0] resetting; // resetting chunk_pointer and eof_pointer
68  wire [2:0] ptr_wa; // pointer memory write port address, msb - eof/current, 2 LSB - channel
69  reg ptr_we; // pointer memory write enable
70  reg [26:0] ptr_ram[0:7]; // pointer (current and eof) memory (in 32-byte chunks
71  wire [26:0] ptr_ram_di; // data to be written to ptr_ram
72  reg [26:0] len_ram[0:3]; // start chunk/num cunks in a buffer (write port @mclk)
73  reg [26:0] chunk_ptr_inc; // incremented by 1..4 chunk pointer
74  reg [27:0] chunk_ptr_rovr; // incremented chunk pointer, decremented by length (MSB - sign)
75  reg [ 4:0] busy; // one-hot busy stages (usually end with [4]
76 
77  reg [ 4:0] id_r; // registered ID data - MSB is unused
78  reg [1:0] chn; // selected channel valid @busy[2]
79  reg eof; // eof register being written
80  reg last_burst_in_frame; // this response is for eof
81  reg [2:0] chunk_inc;
82  reg afi_bready_r; //
83  reg afi_bvalid_r; // make it slow;
84  wire pre_busy;
85  wire pre_we;
86  reg en_d; //enable delayed by 1 cycle
87 
88  assign reset_rq_enc = {reset_rq_pri[3] | reset_rq_pri[2],
89  reset_rq_pri[3] | reset_rq_pri[1]};
90  assign ptr_ram_di= resetting[1] ? 27'b0 : (chunk_ptr_rovr[27] ? chunk_ptr_inc : chunk_ptr_rovr[26:0]);
91 
92  assign ptr_wa = {eof,chn}; // valid @busy[2]
93  assign afi_bready = afi_bready_r;
94 
95  assign pre_we= resetting[0] || // a pair of cycles to reset chunk pointer and frame chunk pointer
96  busy[3] || // always update chunk pointer
97  (busy[4] && last_burst_in_frame); // optionally update frame chunk pointer (same value)
98  assign pre_busy= afi_bvalid_r && en && !(|busy[2:0]) && !pre_we;
99  assign start_resetting_w = !afi_bvalid_r && en && !(|busy[2:0]) && !pre_we && (|reset_rq);
100 
102 
103  always @ (posedge hclk) begin
104  en_d <= en;
105  // write length RAM
108 
109  afi_bready_r <= !en || pre_busy; // (!busy[0] && !pre_busy && !resetting[0] && !start_resetting_w);
110  busy <= {busy[3:0], pre_busy}; // adjust bits
111 
112 // if (afi_bready && afi_bvalid) id_r <= afi_bid[4:0]; // id_r[5] is never used - revoved
113  if (afi_bvalid && pre_busy) id_r <= afi_bid[4:0]; // id_r[5] is never used - revoved
114 
115  if (start_resetting_w) reset_rq_pri <= {reset_rq[3] & ~(|reset_rq[2:0]),
116  reset_rq[2] & ~(|reset_rq[1:0]),
117  reset_rq[1] & ~reset_rq[0],
118  reset_rq[0]};
119 
120  if (en && !en_d) reset_rq <= 4'hf; // request reset all
121  else reset_rq <= reset_pointers | (reset_rq & ~({4{resetting[0] &~ resetting[1]}} & reset_rq_pri));
122 
123  if (!en) resetting <= 0;
124  else resetting <= {resetting[0], start_resetting_w | (resetting[0] & ~resetting[1])};
125 
126  if (resetting == 2'b01) chn <= reset_rq_enc;
127  else if (busy[1]) chn <= id_r[0 +: 2];
128 
129  if (busy[1]) begin // first busy cycle
130  last_burst_in_frame <= id_r[2];
131  chunk_inc <= {1'b0,id_r[3 +:2]} + 1;
132  end
133 
134  ptr_we <= pre_we;
135 
136  if ((resetting == 2'b01) || busy[0]) eof <= 0;
137  else if (ptr_we) eof <= 1; // always second write cycle
138 
139  if (busy[2]) chunk_ptr_inc <= ptr_ram[ptr_wa] + chunk_inc; // second clock of busy
140  if (busy[3]) chunk_ptr_rovr <={1'b0,chunk_ptr_inc} - {1'b0,len_ram[chn]}; // third clock of busy
141 
142  // write to ptr_ram (1 or 2 locations - if eof)
143  if (ptr_we) ptr_ram[ptr_wa] <= ptr_ram_di;
144 
145  // Watch write response channel, detect EOF IDs, generate eof_written* output signals
146  eof_written[0] <= afi_bvalid_r && afi_bready_r && (id_r[2:0]== 3'h4);
147  eof_written[1] <= afi_bvalid_r && afi_bready_r && (id_r[2:0]== 3'h5);
148  eof_written[2] <= afi_bvalid_r && afi_bready_r && (id_r[2:0]== 3'h6);
149  eof_written[3] <= afi_bvalid_r && afi_bready_r && (id_r[2:0]== 3'h7);
150 
151 
152 
153  end
154 endmodule
155