Files
templates/hdl/logic-analyzer/rtl/la_run_encoder.v
T

93 lines
3.5 KiB
Verilog

`timescale 1ns / 1ps
// Triggered, lossless encoding of constant digital runs. Each run emits the
// sample byte followed by its duration minus one (1..256 sample ticks).
// The small queue absorbs clusters of edges. Overflow latches a fault
// instead of slowing the sampling clock or silently dropping edges.
module la_run_encoder (
input wire clk, reset, arm, stop, tick,
input wire [7:0] sample, channel_mask,
input wire [7:0] level_mask, level_value, edge_mask, edge_value, any_edge_mask,
output wire stored,
output reg overflow,
output wire valid,
output wire [7:0] data,
input wire ready
);
reg [7:0] channels, levels, values, directed, direction, edges;
reg [7:0] previous, run_sample, run_length, run_input;
reg previous_valid, triggered, run_tick, run_started;
wire [7:0] selected = sample & channels;
wire level_hit = (selected & levels) == values;
wire edge_hit = edges == 0 || (previous_valid &&
((selected ^ previous) & edges) == edges && (selected & directed) == direction);
assign stored = tick && !overflow && (triggered || (level_hit && edge_hit));
(* ram_style = "distributed" *) reg [15:0] runs [0:31];
reg [5:0] wr_ptr, rd_ptr;
reg [15:0] output_run;
reg output_valid, high_byte;
wire full = wr_ptr == {~rd_ptr[5], rd_ptr[4:0]};
wire emit = run_tick && !overflow && run_started &&
(run_input != run_sample || run_length == 255);
assign valid = output_valid && !overflow;
assign data = high_byte ? output_run[15:8] : output_run[7:0];
always @(posedge clk) begin
if (reset || stop || arm) begin
channels <= channel_mask;
levels <= level_mask & channel_mask;
values <= level_value & level_mask & channel_mask;
directed <= edge_mask & channel_mask;
direction <= edge_value & edge_mask & channel_mask;
edges <= (edge_mask | any_edge_mask) & channel_mask;
previous_valid <= 0;
triggered <= 0;
run_tick <= 0;
run_started <= 0;
overflow <= 0;
wr_ptr <= 0;
rd_ptr <= 0;
output_valid <= 0;
high_byte <= 0;
end else begin
// The trigger comparison and the run encoder each get a full cycle.
run_tick <= stored;
run_input <= selected;
if (tick) begin
previous <= selected;
previous_valid <= 1;
end
if (stored)
triggered <= 1;
if (run_tick && !overflow) begin
run_started <= 1;
if (!run_started || emit) begin
run_sample <= run_input;
run_length <= 0;
end else begin
run_length <= run_length + 1'b1;
end
end
if (emit) begin
if (full)
overflow <= 1;
else
wr_ptr <= wr_ptr + 1'b1;
end
if (!output_valid && rd_ptr != wr_ptr) begin
output_run <= runs[rd_ptr[4:0]];
rd_ptr <= rd_ptr + 1'b1;
output_valid <= 1;
end else if (valid && ready) begin
high_byte <= !high_byte;
if (high_byte)
output_valid <= 0;
end
end
end
always @(posedge clk)
if (!reset && !arm && !stop && emit && !full)
runs[wr_ptr[4:0]] <= {run_length, run_sample};
endmodule