Add patent-style non-zero initial NEAR for first strip

This commit is contained in:
2026-04-17 09:13:56 +08:00
parent 2e06705c86
commit 50539f4abb
5 changed files with 93 additions and 74 deletions

View File

@@ -70,7 +70,8 @@ module tb_jls_near_ctrl;
rst = 1'b0;
// ratio=2 targets 1/4 of source bits. A 256-pixel 8-bit strip has
// 2048 source bits and 512 target bits.
// 2048 source bits and 512 target bits. The patent-inspired controller
// now starts the first strip from a non-zero initial NEAR for ratio=2.
@(posedge clk);
image_ratio = 4'd2;
image_start_valid = 1'b1;
@@ -84,7 +85,7 @@ module tb_jls_near_ctrl;
strip_done_valid = 1'b0;
@(posedge clk);
#1;
if (current_near !== 6'd4 || actual_bits_cumulative !== 48'd800 ||
if (current_near !== 8'd64 || actual_bits_cumulative !== 48'd800 ||
target_bits_cumulative !== 48'd512) begin
$fatal(1, "ratio=2 first strip update mismatch");
end
@@ -96,7 +97,7 @@ module tb_jls_near_ctrl;
strip_done_valid = 1'b0;
@(posedge clk);
#1;
if (current_near !== 6'd8 || actual_bits_cumulative !== 48'd1120 ||
if (current_near !== 8'd127 || actual_bits_cumulative !== 48'd1120 ||
target_bits_cumulative !== 48'd1024) begin
$fatal(1, "ratio=2 second strip update mismatch");
end
@@ -108,7 +109,7 @@ module tb_jls_near_ctrl;
strip_done_valid = 1'b0;
@(posedge clk);
#1;
if (current_near !== 6'd4 || actual_bits_cumulative !== 48'd1200 ||
if (current_near !== 8'd64 || actual_bits_cumulative !== 48'd1200 ||
target_bits_cumulative !== 48'd1536) begin
$fatal(1, "ratio=2 third strip update mismatch");
end

View File

@@ -32,7 +32,7 @@ module tb_jls_scan_ctrl;
logic image_last_pixel;
logic [12:0] active_pic_col;
logic [3:0] active_ratio;
logic [5:0] current_near;
logic [7:0] current_near;
// Forwarded encode pixel event.
logic enc_pixel_valid;
@@ -50,7 +50,7 @@ module tb_jls_scan_ctrl;
logic original_image_first_strip;
logic [12:0] strip_width;
logic [12:0] strip_height;
logic [5:0] strip_near;
logic [7:0] strip_near;
logic strip_finish_valid;
logic strip_finish_ready;
logic original_image_last_strip;
@@ -122,7 +122,7 @@ module tb_jls_scan_ctrl;
image_last_pixel = 1'b0;
active_pic_col = 13'd4;
active_ratio = 4'd2;
current_near = 6'd7;
current_near = 8'd7;
enc_pixel_ready = 1'b1;
strip_start_ready = 1'b1;
strip_finish_ready = 1'b1;
@@ -178,7 +178,7 @@ module tb_jls_scan_ctrl;
if (original_image_first_strip !== 1'b1) begin
$fatal(1, "original_image_first_strip should be high in this smoke");
end
if (strip_width !== 13'd4 || strip_height !== 13'd4 || strip_near !== 6'd0) begin
if (strip_width !== 13'd4 || strip_height !== 13'd4 || strip_near !== 8'd16) begin
$fatal(1, "strip start fields mismatch");
end
end

View File

@@ -99,14 +99,14 @@ module jls_near_ctrl #(
logic [47:0] pending_actual_bits_sum;
logic [47:0] pending_target_bits_sum;
logic pending_ratio_is_lossless_or_invalid;
logic pending_first_strip_update;
// Ratio classification.
logic ratio_is_lossless_or_invalid;
// Shift-add thresholds for the first-strip coarse jump. These are chosen to
// approximate the project review buckets while avoiding wide constant
// multipliers in the 250 MHz strip-control path.
// Patent-inspired non-zero initial NEAR lookup.
logic [3:0] ratio_for_initial_lookup;
logic [3:0] initial_near_level_next;
// Shift-add thresholds for the cumulative micro-adjustment path.
logic [47:0] target_plus_one_eighth;
logic [47:0] target_plus_one_thirtysecond;
logic [47:0] target_plus_one_quarter;
@@ -116,7 +116,6 @@ module jls_near_ctrl #(
logic [47:0] target_times_two;
logic [47:0] target_times_three;
logic [47:0] target_times_five;
logic [3:0] first_strip_level_next;
// Cumulative micro-adjust thresholds for later strips. +/-1/16 is the hold
// band; beyond +/-1/4 the controller skips one NEAR rung.
@@ -277,6 +276,46 @@ module jls_near_ctrl #(
endcase
end
always_comb begin
ratio_for_initial_lookup = active_ratio;
if (image_start_valid) begin
ratio_for_initial_lookup = image_ratio;
end
end
always_comb begin
initial_near_level_next = NEAR_LEVEL_0;
case (ratio_for_initial_lookup)
RATIO_1_TO_2: begin
if (PIX_WIDTH <= 8) begin
initial_near_level_next = NEAR_LEVEL_1;
end else begin
initial_near_level_next = NEAR_LEVEL_2;
end
end
RATIO_1_TO_4: begin
if (PIX_WIDTH <= 8) begin
initial_near_level_next = NEAR_LEVEL_16;
end else begin
initial_near_level_next = NEAR_LEVEL_255;
end
end
RATIO_1_TO_8: begin
if (PIX_WIDTH <= 8) begin
initial_near_level_next = NEAR_LEVEL_64;
end else begin
initial_near_level_next = NEAR_LEVEL_255;
end
end
default: begin
initial_near_level_next = NEAR_LEVEL_0;
end
endcase
end
always_comb begin
target_plus_one_thirtysecond = pending_target_bits_sum +
{5'b00000, pending_target_bits_sum[47:5]};
@@ -293,57 +332,6 @@ module jls_near_ctrl #(
target_times_five = pending_target_bits_sum + {pending_target_bits_sum[45:0], 2'b00};
end
always_comb begin
first_strip_level_next = NEAR_LEVEL_255;
case (active_ratio)
RATIO_1_TO_4, RATIO_1_TO_8: begin
if (pending_actual_bits_sum <= target_plus_one_eighth) begin
first_strip_level_next = NEAR_LEVEL_0;
end else if (pending_actual_bits_sum <= target_plus_one_quarter) begin
first_strip_level_next = NEAR_LEVEL_1;
end else if (pending_actual_bits_sum <= target_plus_one_half) begin
first_strip_level_next = NEAR_LEVEL_2;
end else if (pending_actual_bits_sum <= target_plus_three_quarters) begin
first_strip_level_next = NEAR_LEVEL_4;
end else if (pending_actual_bits_sum <= target_times_two_plus_quarter) begin
first_strip_level_next = NEAR_LEVEL_8;
end else if (pending_actual_bits_sum <= target_times_three) begin
first_strip_level_next = NEAR_LEVEL_32;
end else if (pending_actual_bits_sum <= {pending_target_bits_sum[45:0], 2'b00}) begin
first_strip_level_next = NEAR_LEVEL_64;
end else if (pending_actual_bits_sum <= ({pending_target_bits_sum[45:0], 2'b00} +
{pending_target_bits_sum[46:0], 1'b0})) begin
first_strip_level_next = NEAR_LEVEL_127;
end
end
default: begin
if (pending_actual_bits_sum <= target_plus_one_eighth) begin
first_strip_level_next = NEAR_LEVEL_0;
end else if (pending_actual_bits_sum <= target_plus_one_quarter) begin
first_strip_level_next = NEAR_LEVEL_1;
end else if (pending_actual_bits_sum <= target_plus_one_half) begin
first_strip_level_next = NEAR_LEVEL_2;
end else if (pending_actual_bits_sum <= target_times_two) begin
first_strip_level_next = NEAR_LEVEL_4;
end else if (pending_actual_bits_sum <= target_times_three) begin
first_strip_level_next = NEAR_LEVEL_8;
end else if (pending_actual_bits_sum <= target_times_five) begin
first_strip_level_next = NEAR_LEVEL_16;
end else if (pending_actual_bits_sum <= ({pending_target_bits_sum[45:0], 2'b00} +
{pending_target_bits_sum[46:0], 1'b0})) begin
first_strip_level_next = NEAR_LEVEL_32;
end else if (pending_actual_bits_sum <= ({pending_target_bits_sum[44:0], 3'b000} +
pending_target_bits_sum)) begin
first_strip_level_next = NEAR_LEVEL_64;
end else if (pending_actual_bits_sum <= ({pending_target_bits_sum[44:0], 3'b000} +
{pending_target_bits_sum[46:0], 1'b0})) begin
first_strip_level_next = NEAR_LEVEL_127;
end
end
endcase
end
always_comb begin
target_plus_sixteenth = pending_target_bits_sum + {4'b0000, pending_target_bits_sum[47:4]};
target_minus_sixteenth = pending_target_bits_sum - {4'b0000, pending_target_bits_sum[47:4]};
@@ -609,11 +597,10 @@ module jls_near_ctrl #(
pending_actual_bits_sum <= 48'd0;
pending_target_bits_sum <= 48'd0;
pending_ratio_is_lossless_or_invalid <= 1'b1;
pending_first_strip_update <= 1'b0;
end else begin
if (image_start_valid) begin
active_ratio <= image_ratio;
current_near_level <= NEAR_LEVEL_0;
current_near_level <= initial_near_level_next;
actual_bits_cumulative <= 48'd0;
target_bits_cumulative <= 48'd0;
target_miss_at_max_near <= 1'b0;
@@ -621,15 +608,12 @@ module jls_near_ctrl #(
pending_actual_bits_sum <= 48'd0;
pending_target_bits_sum <= 48'd0;
pending_ratio_is_lossless_or_invalid <= 1'b1;
pending_first_strip_update <= 1'b0;
end else if (pending_update_valid) begin
actual_bits_cumulative <= pending_actual_bits_sum;
target_bits_cumulative <= pending_target_bits_sum;
if (pending_ratio_is_lossless_or_invalid) begin
current_near_level <= NEAR_LEVEL_0;
end else if (pending_first_strip_update) begin
current_near_level <= first_strip_level_next;
end else begin
current_near_level <= adjusted_near_level_next;
end
@@ -644,8 +628,6 @@ module jls_near_ctrl #(
pending_actual_bits_sum <= actual_bits_sum;
pending_target_bits_sum <= target_bits_sum;
pending_ratio_is_lossless_or_invalid <= ratio_is_lossless_or_invalid;
pending_first_strip_update <= (actual_bits_cumulative == 48'd0) &&
(target_bits_cumulative == 48'd0);
end
end
end

View File

@@ -162,8 +162,11 @@ module jls_scan_ctrl #(
logic input_row_last_pixel;
// First-strip NEAR must be zero even if jls_near_ctrl has not yet reset on
// the same SOF pixel cycle.
// the same SOF pixel cycle. With the patent-inspired controller, the first
// strip may start from a non-zero initial NEAR chosen from active_ratio and
// PIX_WIDTH, so this logic computes the same initial rung locally.
logic [7:0] selected_strip_near;
logic [7:0] initial_strip_near;
always_comb begin
input_start_path_ready = 1'b1;
@@ -272,10 +275,43 @@ module jls_scan_ctrl #(
strip_height = SCAN_ROWS_VALUE;
end
always_comb begin
initial_strip_near = 8'd0;
case (active_ratio)
4'd1: begin
if (PIX_WIDTH <= 8) begin
initial_strip_near = 8'd1;
end else begin
initial_strip_near = 8'd2;
end
end
4'd2: begin
if (PIX_WIDTH <= 8) begin
initial_strip_near = 8'd16;
end else begin
initial_strip_near = 8'd255;
end
end
4'd3: begin
if (PIX_WIDTH <= 8) begin
initial_strip_near = 8'd64;
end else begin
initial_strip_near = 8'd255;
end
end
default: begin
initial_strip_near = 8'd0;
end
endcase
end
always_comb begin
selected_strip_near = current_near;
if (image_first_pixel) begin
selected_strip_near = 8'd0;
selected_strip_near = initial_strip_near;
end
end