// Captures one burst of sampled bits into block RAM for offline analysis. Keeps every // decimation-th sample and packs it MSB first into bytes: one bit per sample from // source A, or in pair mode two bits per sample (A then B) so both sources are recorded // at the same instants. module raw_capture #( parameter ADDR_WIDTH = 15 // 2^15 bytes = 256 Kbit per burst ) ( input wire clk, input wire reset, input wire bit_a, input wire bit_b, input wire pair_mode, input wire [15:0] decimation, // 0 and 1 both mean every sample input wire start, output reg busy, output reg done, input wire [ADDR_WIDTH-1:0] read_addr, output reg [7:0] read_data ); reg [7:0] buffer [0:(1 << ADDR_WIDTH) - 1]; reg [15:0] sample_count; reg [3:0] bit_count; reg [7:0] partial_byte; reg [ADDR_WIDTH-1:0] next_addr; reg write_enable; reg [ADDR_WIDTH-1:0] write_addr; reg [7:0] write_data; wire keep_sample = (sample_count == 16'd0); wire count_wraps = (decimation <= 16'd1) || (sample_count == decimation - 16'd1); wire [7:0] shifted = pair_mode ? {partial_byte[5:0], bit_a, bit_b} : {partial_byte[6:0], bit_a}; wire [3:0] new_count = bit_count + (pair_mode ? 4'd2 : 4'd1); always @(posedge clk) begin write_enable <= 1'b0; if (reset) begin busy <= 1'b0; done <= 1'b0; end else if (start) begin busy <= 1'b1; done <= 1'b0; sample_count <= 16'd0; bit_count <= 4'd0; next_addr <= {ADDR_WIDTH{1'b0}}; end else if (busy) begin sample_count <= count_wraps ? 16'd0 : sample_count + 16'd1; if (keep_sample) begin partial_byte <= shifted; if (new_count == 4'd8) begin bit_count <= 4'd0; write_enable <= 1'b1; write_addr <= next_addr; write_data <= shifted; next_addr <= next_addr + 1'b1; if (&next_addr) begin busy <= 1'b0; done <= 1'b1; end end else begin bit_count <= new_count; end end end end // Two read registers: the first becomes the RAM's address register, the second its output // register, which keeps the wide block-RAM output multiplexer off the SPI timing path. reg [7:0] read_data_ram; always @(posedge clk) begin if (write_enable) buffer[write_addr] <= write_data; read_data_ram <= buffer[read_addr]; read_data <= read_data_ram; end endmodule