x393  1.0
FPGAcodeforElphelNC393camera
mult_saxi_wr_pointers.v
Go to the documentation of this file.
1 
39 `timescale 1ns/1ps
40 
42  parameter MULT_SAXI_BSLOG0 = 4, // number of bits to represent burst size (4 - b.s. = 16, 0 - b.s = 1)
43  parameter MULT_SAXI_BSLOG1 = 4,
44  parameter MULT_SAXI_BSLOG2 = 4,
45  parameter MULT_SAXI_BSLOG3 = 4
46 )(
47  input mclk, // system clock
48  input aclk, // global clock to run s_axi (@150MHz?)
49  input [3:0] chn_en_mclk, // enable this channle ( 0 - reset)
50  input [29:0] sa_len_di, // input data to write pointers address/data
51  input [ 2:0] sa_len_wa, // channel address to write sa/lengths
52  input sa_len_we, // write enable sa/length data
53  input [ 1:0] chn, // selected channel number, valid with start
54  input start, // start address generation/pointer increment
55  output busy, // suspend new accesses (check latencies)
56  // provide address and burst length for AXI @aclk, will stay until ackn
57  output reg [29:0] axi_addr,
58  output reg [3:0] axi_len,
59  // write data to external pointre memory (to be read out by PIO) @ aclk
60  // alternatively - read out directly from ptr_ram?
61  output [29:0] pntr_wd, // @aclk
62  output [1:0] pntr_wa,
63  output pntr_we
64 );
65  reg [3:0] chn_en_mclk_r;
66  reg [3:0] chn_en_aclk;
67  wire rst = !(|chn_en_mclk); // just for simulation
68  wire rst_aclk = !(|chn_en_aclk); // just for simulation
69  wire [3:0] chn_wr_mclk = {(sa_len_wa[2:1]==3),(sa_len_wa[2:1]==2),(sa_len_wa[2:1]==1),(sa_len_wa[2:1]==0)};
71  wire [3:0] rst_pntr_aclk;
73  reg [1:0] resetting; // resetting chunk_pointer and eof_pointer
74  reg busy_r;
75  reg [3:0] reset_rq; // request to reset pointers when ready
76  reg [3:0] reset_rq_pri; // one-hot reset rq
77  wire [1:0] reset_rq_enc; // encoded reset_rq_pri
79  reg [1:0] chn_r; // registered channel being processed (or reset)
80  reg [1:0] seq; // 1-hot sequence of address generation
81  wire [29:0] sa_len_ram_out;
82  wire [29:0] ptr_ram_out;
83  wire [2:0] sa_len_ra;
84  reg ptr_we; // write to the pointer memory
85  reg [29:0] ptr_inc; // incremented pointer
86  reg [30:0] ptr_rollover;
87  reg [4:0] burst_size; // ROM
88  wire [29:0] ptr_wd;
89 
90  assign reset_rq_enc = {reset_rq_pri[3] | reset_rq_pri[2],
91  reset_rq_pri[3] | reset_rq_pri[1]};
92 
93  assign start_resetting_w = en_aclk && !busy_r && !resetting[0] && (|reset_rq);
94  assign busy = busy_r; //?
95  assign ptr_wd = resetting[1] ? 30'b0 : (ptr_rollover[30]? ptr_inc : ptr_rollover[29:0]);
96 
97  assign pntr_wd = ptr_wd;
98  assign pntr_we = ptr_we;
99  assign pntr_wa = chn_r;
100 
101  assign sa_len_ra = {chn_r,seq[1]};
102  always @ (posedge mclk) begin
104  end
105 
106 // 8x30 RAM for address/length
107  reg [29:0] sa_len_ram[0:7]; // start chunk/num cunks in a buffer (write port @mclk)
108  always @ (posedge mclk) begin
110  end
112 
113 // 4 x 30 RAM for current pointers
114  reg [29:0] ptr_ram[0:3]; // start chunk/num cunks in a buffer (write port @mclk)
115  always @ (posedge aclk) begin
116  if (ptr_we) ptr_ram[chn_r] <= ptr_wd;
117  end
118  assign ptr_ram_out = ptr_ram[chn_r];
119 
120  always @ (posedge aclk) if (start) case (chn) // small ROM
121  'h0 : burst_size <= 1 << MULT_SAXI_BSLOG0;
122  'h1 : burst_size <= 1 << MULT_SAXI_BSLOG1;
123  'h2 : burst_size <= 1 << MULT_SAXI_BSLOG2;
124  'h3 : burst_size <= 1 << MULT_SAXI_BSLOG3;
125  endcase
126 
127  always @ (posedge aclk) begin
129  reset_rq <= rst_pntr_aclk | (reset_rq & ~({4{resetting[0] &~ resetting[1]}} & reset_rq_pri));
130  if (start_resetting_w) reset_rq_pri <= {reset_rq[3] & ~(|reset_rq[2:0]),
131  reset_rq[2] & ~(|reset_rq[1:0]),
132  reset_rq[1] & ~reset_rq[0],
133  reset_rq[0]};
134  if (rst_aclk) resetting <= 0;
135  else resetting <= {resetting[0], start_resetting_w | (resetting[0] & ~resetting[1])};
136 
137  if (rst_aclk) busy_r <= 0;
138  else if (start_resetting_w || start) busy_r <= 1;
139  else if (ptr_we) busy_r <= 0;
140 
141  if (rst_aclk) seq <= 0;
142  else seq <= {seq[0],start};
143 
144  if (resetting == 2'b1) chn_r[1:0] <= reset_rq_enc; // during reset pointers
145  else if (start) chn_r[1:0] <= chn; // during normal address generation
146 
147  if (seq[0]) axi_addr <= sa_len_ram_out + ptr_ram_out;
148  if (seq[0]) case (chn_r) // small ROM
149  'h0 : axi_len <= (1 << MULT_SAXI_BSLOG0) - 1;
150  'h1 : axi_len <= (1 << MULT_SAXI_BSLOG1) - 1;
151  'h2 : axi_len <= (1 << MULT_SAXI_BSLOG2) - 1;
152  'h3 : axi_len <= (1 << MULT_SAXI_BSLOG3) - 1;
153  endcase
154 
155  if (seq[0]) ptr_inc <= ptr_ram_out + burst_size;
156 
157  if (seq[1]) ptr_rollover <= {1'b0, ptr_inc} -sa_len_ram_out; //sa_len_ram_out is now length
158 
159  ptr_we <= resetting[0] || seq[1];
160 
161  // add one extra register layer here?
162 
163  end
164 
165  pulse_cross_clock #(.EXTRA_DLY(1)) rst_pntr_aclk0_i (.rst(rst), .src_clk(mclk), .dst_clk(aclk), .in_pulse(rst_pntr_mclk[0]), .out_pulse(rst_pntr_aclk[0]),.busy());
166  pulse_cross_clock #(.EXTRA_DLY(1)) rst_pntr_aclk1_i (.rst(rst), .src_clk(mclk), .dst_clk(aclk), .in_pulse(rst_pntr_mclk[1]), .out_pulse(rst_pntr_aclk[1]),.busy());
167  pulse_cross_clock #(.EXTRA_DLY(1)) rst_pntr_aclk2_i (.rst(rst), .src_clk(mclk), .dst_clk(aclk), .in_pulse(rst_pntr_mclk[2]), .out_pulse(rst_pntr_aclk[2]),.busy());
168  pulse_cross_clock #(.EXTRA_DLY(1)) rst_pntr_aclk3_i (.rst(rst), .src_clk(mclk), .dst_clk(aclk), .in_pulse(rst_pntr_mclk[3]), .out_pulse(rst_pntr_aclk[3]),.busy());
169 
170 endmodule
171 
rst_pntr_aclk3_i pulse_cross_clock