// Per-second trials in the format of Global Consciousness Project (GCP) style network analyses, // running alongside the other outputs. Every TRIAL_MS milliseconds (one second) each generator // yields: // - the sum of the first SAMPLE_BITS bits of the second, the GCP trial (expected 100, sd 7.07); // - the sum of all its bits during the second, for a full-rate z-score. // Both use XOR-masked bits: bit i of the second is inverted when i is odd, so a constant bias // cancels. All generators deliver in lockstep, so one bit count serves them all; generators that // were not healthy for the whole second are flagged in the snapshot, not excluded from counting. // // Snapshot layout (big-endian), latched at the end of each second: // 0-3 sequence number, starting at 1 (0: no second completed yet) // 4 generators healthy during the whole second (bit g) // 5 SAMPLE_BITS // 6-7 0 // 8-11 bits per generator during the second // 12+5g generator g: sample sum (1), masked ones during the second (4) // 32-35 sequence number again; a mismatch with bytes 0-3 means a torn read module gcp_block #( parameter GENERATORS = 4, parameter SAMPLE_BITS = 200, parameter TRIAL_MS = 1000, parameter TICK_CYCLES = 120000 // clk cycles per millisecond ) ( input wire clk, input wire reset, input wire [GENERATORS-1:0] gen_bit, input wire gen_valid, input wire [GENERATORS-1:0] healthy, input wire [7:0] read_index, output reg [7:0] read_byte, // one cycle after read_index output reg trial_end // pulse: a new snapshot is available ); localparam SNAPSHOT_BYTES = 12 + 5 * GENERATORS + 4; localparam [7:0] SAMPLE_SIZE = SAMPLE_BITS; // Trial timing reg [16:0] tick_count; reg [15:0] ms_count; wire tick = (tick_count == TICK_CYCLES - 1); always @(posedge clk) begin trial_end <= 1'b0; if (reset) begin tick_count <= 17'd0; ms_count <= 16'd0; end else begin tick_count <= tick ? 17'd0 : tick_count + 17'd1; if (tick && ms_count == TRIAL_MS - 1) begin ms_count <= 16'd0; trial_end <= 1'b1; end else if (tick) begin ms_count <= ms_count + 16'd1; end end end // Counters. As in stats_block, the bit arriving in the trial_end cycle opens the next second. reg [31:0] bit_count; reg [7:0] sampled; // bits taken into the sample sums this second reg odd; // the next bit has an odd index in the second reg [7:0] sample_sum [0:GENERATORS-1]; reg [31:0] masked_ones [0:GENERATORS-1]; reg [31:0] sequence_number; reg [GENERATORS-1:0] healthy_during; wire mask = trial_end ? 1'b0 : odd; wire in_sample = trial_end || sampled < SAMPLE_BITS; wire [GENERATORS-1:0] masked = gen_bit ^ {GENERATORS{mask}}; reg [8*SNAPSHOT_BYTES-1:0] snapshot_next; reg [7:0] snapshot [0:SNAPSHOT_BYTES-1]; integer k; always @(*) begin snapshot_next = {SNAPSHOT_BYTES{8'h00}}; snapshot_next[8*SNAPSHOT_BYTES-1 -: 96] = {sequence_number, {8-GENERATORS{1'b0}}, healthy_during & healthy, SAMPLE_SIZE, 16'd0, bit_count}; for (k = 0; k < GENERATORS; k = k + 1) snapshot_next[8*SNAPSHOT_BYTES-1-96-40*k -: 40] = {sample_sum[k], masked_ones[k]}; snapshot_next[31:0] = sequence_number; end integer g, b; always @(posedge clk) begin if (reset) begin bit_count <= 32'd0; sampled <= 8'd0; odd <= 1'b0; sequence_number <= 32'd1; healthy_during <= {GENERATORS{1'b1}}; for (g = 0; g < GENERATORS; g = g + 1) begin sample_sum[g] <= 8'd0; masked_ones[g] <= 32'd0; end end else begin if (gen_valid) begin bit_count <= (trial_end ? 32'd0 : bit_count) + 32'd1; sampled <= in_sample ? (trial_end ? 8'd0 : sampled) + 8'd1 : sampled; odd <= ~mask; for (g = 0; g < GENERATORS; g = g + 1) begin sample_sum[g] <= (trial_end ? 8'd0 : sample_sum[g]) + (in_sample && masked[g]); masked_ones[g] <= (trial_end ? 32'd0 : masked_ones[g]) + masked[g]; end end else if (trial_end) begin bit_count <= 32'd0; sampled <= 8'd0; odd <= 1'b0; for (g = 0; g < GENERATORS; g = g + 1) begin sample_sum[g] <= 8'd0; masked_ones[g] <= 32'd0; end end if (trial_end) begin for (b = 0; b < SNAPSHOT_BYTES; b = b + 1) snapshot[b] <= snapshot_next[8*(SNAPSHOT_BYTES-1-b) +: 8]; sequence_number <= sequence_number + 32'd1; healthy_during <= healthy; end else begin healthy_during <= healthy_during & healthy; end end end always @(posedge clk) read_byte <= (read_index < SNAPSHOT_BYTES) ? snapshot[read_index] : 8'h00; endmodule