123 lines
5 KiB
Verilog
123 lines
5 KiB
Verilog
// One amplifier path: the generator streams are merged into one stream, which then passes
|
|
// three stages in series. Merging before amplifying is equivalent to amplifying each stream
|
|
// with the same first stage and merging after (the random walk is distributive), and needs a
|
|
// third of the stages. Amplified bits are tallied per sub-trial and per trial.
|
|
module amp_path #(
|
|
parameter GENERATORS = 4
|
|
) (
|
|
input wire clk,
|
|
input wire restart,
|
|
input wire [GENERATORS-1:0] in_valid,
|
|
input wire [GENERATORS-1:0] in_bit,
|
|
input wire [2:0] stage_mode,
|
|
input wire [47:0] stage_param, // stage s at [16*s +: 16]
|
|
input wire sub_end, // pulse: close the current sub-trial
|
|
input wire [3:0] sub_index, // sub-trial being closed
|
|
input wire trial_end, // pulse: start a new trial (after the last sub_end)
|
|
output reg [31:0] trial_bits, // amplified bits in the current trial
|
|
output reg [31:0] trial_ones,
|
|
output reg [15:0] votes, // bit i: sub-trial i voted 1
|
|
output reg [15:0] voted, // bit i: sub-trial i had a majority
|
|
output reg [4:0] vote_count, // sub-trials that voted (registered from voted)
|
|
output reg [4:0] one_votes, // of those, voted 1
|
|
output reg overflow // a merge input arrived before the last was taken
|
|
);
|
|
|
|
// Merge: each generator's latest bit waits in its own slot; one slot is drained per clock,
|
|
// lowest index first. Generators deliver at most one bit per `temporal` (>= 1, default 5)
|
|
// clocks in lockstep, so with up to 4 generators the slots never overflow at temporal >= 4
|
|
// (flagged if they do).
|
|
|
|
reg [GENERATORS-1:0] pending, pending_bit, take;
|
|
reg merged_valid, merged_bit;
|
|
integer i;
|
|
|
|
always @(*) begin
|
|
take = {GENERATORS{1'b0}};
|
|
for (i = 0; i < GENERATORS; i = i + 1)
|
|
if (pending[i] && take == {GENERATORS{1'b0}}) take[i] = 1'b1;
|
|
end
|
|
|
|
always @(posedge clk) begin
|
|
merged_valid <= |take && !restart;
|
|
for (i = 0; i < GENERATORS; i = i + 1)
|
|
if (take[i]) merged_bit <= pending_bit[i];
|
|
|
|
if (restart) begin
|
|
pending <= {GENERATORS{1'b0}};
|
|
overflow <= 1'b0;
|
|
end else begin
|
|
for (i = 0; i < GENERATORS; i = i + 1) begin
|
|
if (in_valid[i]) begin
|
|
if (pending[i] && !take[i]) overflow <= 1'b1;
|
|
pending[i] <= 1'b1;
|
|
pending_bit[i] <= in_bit[i];
|
|
end else if (take[i]) begin
|
|
pending[i] <= 1'b0;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
// Stages
|
|
|
|
wire first_valid, first_bit, second_valid, second_bit, out_valid, out_bit;
|
|
|
|
amp_stage first (
|
|
.clk(clk), .restart(restart), .mode(stage_mode[0]), .param(stage_param[15:0]),
|
|
.in_valid(merged_valid), .in_bit(merged_bit), .out_valid(first_valid), .out_bit(first_bit)
|
|
);
|
|
|
|
amp_stage second (
|
|
.clk(clk), .restart(restart), .mode(stage_mode[1]), .param(stage_param[31:16]),
|
|
.in_valid(first_valid), .in_bit(first_bit), .out_valid(second_valid), .out_bit(second_bit)
|
|
);
|
|
|
|
amp_stage third (
|
|
.clk(clk), .restart(restart), .mode(stage_mode[2]), .param(stage_param[47:32]),
|
|
.in_valid(second_valid), .in_bit(second_bit), .out_valid(out_valid), .out_bit(out_bit)
|
|
);
|
|
|
|
// Tallies. A bit arriving in a sub_end or trial_end cycle counts towards the next one, so
|
|
// the trial count and the sum of its sub-trial counts can differ by one bit.
|
|
|
|
reg [23:0] sub_bits, sub_ones;
|
|
|
|
function [4:0] count_ones(input [15:0] value);
|
|
integer b;
|
|
begin
|
|
count_ones = 5'd0;
|
|
for (b = 0; b < 16; b = b + 1) count_ones = count_ones + value[b];
|
|
end
|
|
endfunction
|
|
|
|
always @(posedge clk) begin
|
|
if (restart || trial_end) begin
|
|
trial_bits <= out_valid ? 32'd1 : 32'd0;
|
|
trial_ones <= (out_valid && out_bit) ? 32'd1 : 32'd0;
|
|
votes <= 16'd0;
|
|
voted <= 16'd0;
|
|
end else if (out_valid) begin
|
|
trial_bits <= trial_bits + 32'd1;
|
|
trial_ones <= trial_ones + out_bit;
|
|
end
|
|
|
|
if (restart || sub_end) begin
|
|
sub_bits <= out_valid ? 24'd1 : 24'd0;
|
|
sub_ones <= (out_valid && out_bit) ? 24'd1 : 24'd0;
|
|
end else if (out_valid) begin
|
|
sub_bits <= sub_bits + 24'd1;
|
|
sub_ones <= sub_ones + out_bit;
|
|
end
|
|
|
|
// Registered counts, ready one cycle after the last vote of a trial
|
|
vote_count <= count_ones(voted);
|
|
one_votes <= count_ones(votes & voted);
|
|
|
|
if (!restart && sub_end && sub_bits != 0 && {sub_ones, 1'b0} != sub_bits) begin
|
|
voted[sub_index] <= 1'b1;
|
|
votes[sub_index] <= {sub_ones, 1'b0} > sub_bits;
|
|
end
|
|
end
|
|
|
|
endmodule
|