diff --git a/fpga/sim/tb_jls_near_ctrl.sv b/fpga/sim/tb_jls_near_ctrl.sv index 4e28749..4123f99 100644 --- a/fpga/sim/tb_jls_near_ctrl.sv +++ b/fpga/sim/tb_jls_near_ctrl.sv @@ -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 diff --git a/fpga/sim/tb_jls_scan_ctrl.sv b/fpga/sim/tb_jls_scan_ctrl.sv index f8047d9..1856577 100644 --- a/fpga/sim/tb_jls_scan_ctrl.sv +++ b/fpga/sim/tb_jls_scan_ctrl.sv @@ -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 diff --git a/fpga/verilog/jls_near_ctrl.sv b/fpga/verilog/jls_near_ctrl.sv index 8659a88..c52dccf 100644 --- a/fpga/verilog/jls_near_ctrl.sv +++ b/fpga/verilog/jls_near_ctrl.sv @@ -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 diff --git a/fpga/verilog/jls_scan_ctrl.sv b/fpga/verilog/jls_scan_ctrl.sv index 3d4a2f0..4684abc 100644 --- a/fpga/verilog/jls_scan_ctrl.sv +++ b/fpga/verilog/jls_scan_ctrl.sv @@ -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 diff --git a/img/reference/charls/omaha-w6144-h256-s0-b16-r2.charlsjls b/img/reference/charls/omaha-w6144-h256-s0-b16-r2.charlsjls index 1ca7d96..f952ba2 100644 Binary files a/img/reference/charls/omaha-w6144-h256-s0-b16-r2.charlsjls and b/img/reference/charls/omaha-w6144-h256-s0-b16-r2.charlsjls differ