Attention

This documentation is a work in progress. Expect to see errors and unfinished things.

circle_buf_serial Source File

  1`timescale 1ns / 1ns
  2
  3/** CIRCLE_BUF_SERIAL **
  4    Double-buffered circular buffer wrapper with channel selector.
  5    This module takes a conveyor belt carrying multiple channels as an input
  6    and writes the channels selected by chan_mask into the Circular Buffer.
  7    Circular buffer can be read out at a different clock rate through the local bus.
  8
  9          +------------------------+
 10          | +-----+    +--------+  |
 11  sr_in+---->     |    |        <-----+ rd_addr/val
 12          | |fchan+----> Circle |  |
 13  mask +----> sel |    | Buf    |  |
 14          | |     |    |        +-----> d_out
 15          | +-----+    +--------+  |
 16          +------------------------+
 17*/
 18
 19module circle_buf_serial #(
 20   // Channel selector parameters
 21   parameter n_chan=12,
 22   parameter lsb_mask=0,      // lsb_mask=0: chan_mask is LEFT-to-RIGHT; MSB=CH0
 23                              // lsb_mask=1: chan_mask is RIGHT-to-LEFT; LSB=CH0
 24
 25   // Circular Buffer parameters
 26   parameter buf_dw=16,
 27   parameter buf_aw=13,
 28   parameter buf_stat_w=16,
 29   parameter buf_auto_flip=1  // auto_flip=1: Double buffers will be flipped when
 30                              //              last read address is reached
 31                              // auto_flip=0: Buffers must be explicitly flipped by
 32                              //              using stb_out as a pulse and not a strobe
 33) (
 34   // Incoming stream
 35   input                    iclk,
 36   input                    reset,
 37   input [buf_dw-1:0]       sr_in, // Conveyor belt carrying n_chan channels
 38   input                    sr_stb,
 39
 40   // Channel selector controls
 41   input [n_chan-1:0]       chan_mask, // Bitmask of channels to record. See lsb_mask parameter
 42   // Selected waveform data in iclk domain
 43   output                   wave_gate,
 44   output                   wave_dval,
 45   output                   [buf_dw-1:0] wave_data,
 46
 47   // Circular Buffer control and statistics
 48   // all of these signals are also in the iclk domain
 49   output                   buf_sync,        // single-cycle when buffer starts/ends
 50   output                   buf_transferred, // single-cycle when a buffer has been
 51                                             // handed over for reading;
 52                                             // one cycle delayed from buf_sync
 53   input                    buf_stop,        // single-cycle - interrupts cbuf writing
 54   output [buf_stat_w-1:0]  buf_count,
 55   output [buf_aw-1:0]      buf_stat2,       // includes fault bit
 56   output [buf_stat_w-1:0]  buf_stat,        // includes fault bit, and (if set) the last valid location
 57   output [buf_aw+4:0]      debug_stat,      // {stb_in, boundary, btest, wbank, rbank, wr_addr}
 58
 59   // Circular Buffer data readout
 60   input                    oclk,
 61   input                    stb_out,
 62   output                   enable,
 63   input  [buf_aw-1:0]      read_addr, // nominally 8192 locations
 64   output [buf_dw-1:0]      d_out
 65);
 66
 67   // ------
 68   // Interleaved channel selector
 69   // ------
 70   wire              fchan_time_error; // For debug only - will pulse if gate-per-trigger ratio is broken
 71   wire              wave_trig;
 72   assign            wave_dval = ~wave_trig;
 73
 74   fchan_subset #(
 75      .KEEP_OLD (lsb_mask),
 76      .a_dw     (buf_dw),
 77      .o_dw     (buf_dw),
 78      .len      (n_chan))
 79   i_fchan_subset (
 80      .clk      (iclk),
 81      .reset    (reset),
 82      .keep     (chan_mask),
 83      .a_data   (sr_in),
 84      .a_gate   (sr_stb),
 85      .a_trig   (~sr_stb),
 86      .o_data   (wave_data),
 87      .o_gate   (wave_gate),
 88      .o_trig   (wave_trig),
 89      .time_err (fchan_time_error)
 90   );
 91
 92`ifdef SIMULATE
 93   always @(negedge iclk) if (fchan_time_error) begin
 94      $display("ERROR: Gate-per-Trigger ratio violated in fchan_selector.");
 95      $finish;
 96   end
 97   // Output file (if any) for dumping the results
 98   integer out_file;
 99   reg [255:0] out_file_name;
100   wire signed [buf_dw/2-1:0] wave_i = wave_data[buf_dw-1:buf_dw/2];
101   wire signed [buf_dw/2-1:0] wave_q = wave_data[buf_dw/2-1:0];
102   reg needs_cr=0;
103   initial begin
104      out_file = 0;
105      if ($value$plusargs("conveyor_file=%s", out_file_name))
106         out_file = $fopen(out_file_name,"w");
107   end
108   always @(negedge iclk) if (out_file != 0) begin
109      if (wave_trig && needs_cr) begin
110         $fwrite(out_file, "\n");
111         needs_cr <= 0;
112      end
113      if (wave_gate) begin
114         $fwrite(out_file, " %d %d", wave_i, wave_q);
115         needs_cr <= 1;
116      end
117   end
118`endif
119
120   // ------
121   // Double-buffered circular buffer
122   // ------
123
124   circle_buf #(
125      .aw        (buf_aw),
126      .dw        (buf_dw),
127      .auto_flip (buf_auto_flip))
128   i_circle_buf (
129      .iclk            (iclk),
130      .d_in            (wave_data),
131      .stb_in          (wave_gate),
132      .boundary        (wave_trig),
133      .stop            (buf_stop),
134      .buf_sync        (buf_sync),
135      .buf_transferred (buf_transferred),
136      .oclk            (oclk),
137      .enable          (enable),
138      .read_addr       (read_addr),
139      .d_out           (d_out),
140      .stb_out         (stb_out),
141      .buf_count       (buf_count),
142      .buf_stat        (buf_stat),
143      .debug_stat      (debug_stat),
144      .buf_stat2       (buf_stat2)
145   );
146
147endmodule