Expand JPEG-LS parameter helpers toward NEAR 255
This commit is contained in:
@@ -6,9 +6,10 @@
|
||||
// Trace : docs/jls_traceability.md#jls-coding-parameters
|
||||
// Example : PIX_WIDTH=8,NEAR=0 gives RANGE=256,qbpp=8,LIMIT=32.
|
||||
//
|
||||
// JPEG-LS coding parameter lookup. RANGE and qbpp depend on NEAR, but NEAR is
|
||||
// limited to 0..31 in this project. A lookup table avoids a synthesized
|
||||
// runtime divider and keeps this strip-level control path timing friendly.
|
||||
// JPEG-LS coding parameter helper. RANGE depends on NEAR through
|
||||
// RANGE = floor((MAXVAL + 2*NEAR)/(2*NEAR+1)) + 1. This is a strip-level
|
||||
// control path, so the generic arithmetic is acceptable here and keeps the
|
||||
// pixel pipeline free from runtime division logic.
|
||||
|
||||
`default_nettype none
|
||||
|
||||
@@ -17,7 +18,7 @@ module jls_coding_params #(
|
||||
parameter int PIX_WIDTH = 16
|
||||
) (
|
||||
// JPEG-LS NEAR parameter for the current strip frame.
|
||||
input var logic [5:0] NEAR,
|
||||
input var logic [7:0] NEAR,
|
||||
|
||||
// JPEG-LS RANGE parameter.
|
||||
output logic [16:0] RANGE,
|
||||
@@ -29,221 +30,120 @@ module jls_coding_params #(
|
||||
output logic [6:0] LIMIT
|
||||
);
|
||||
|
||||
// Defensive clamp even though upstream NEAR is already limited to 31.
|
||||
logic [5:0] near_clamped;
|
||||
logic [16:0] range_next;
|
||||
logic [4:0] qbpp_next;
|
||||
logic [6:0] limit_next;
|
||||
integer maximum_sample_value_int;
|
||||
integer maximum_near_int;
|
||||
integer near_clamped_int;
|
||||
integer denominator_int;
|
||||
integer range_int;
|
||||
integer qbpp_int;
|
||||
integer limit_int;
|
||||
|
||||
always_comb begin
|
||||
near_clamped = NEAR;
|
||||
if (NEAR > 6'd31) begin
|
||||
near_clamped = 6'd31;
|
||||
end
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
range_next = 17'd65536;
|
||||
qbpp_next = 5'd16;
|
||||
limit_next = 7'd64;
|
||||
|
||||
maximum_sample_value_int = 65535;
|
||||
limit_int = 64;
|
||||
case (PIX_WIDTH)
|
||||
8: begin
|
||||
limit_next = 7'd32;
|
||||
case (near_clamped)
|
||||
6'd0: begin range_next = 17'd256; qbpp_next = 5'd8; end
|
||||
6'd1: begin range_next = 17'd86; qbpp_next = 5'd7; end
|
||||
6'd2: begin range_next = 17'd52; qbpp_next = 5'd6; end
|
||||
6'd3: begin range_next = 17'd38; qbpp_next = 5'd6; end
|
||||
6'd4: begin range_next = 17'd30; qbpp_next = 5'd5; end
|
||||
6'd5: begin range_next = 17'd25; qbpp_next = 5'd5; end
|
||||
6'd6: begin range_next = 17'd21; qbpp_next = 5'd5; end
|
||||
6'd7: begin range_next = 17'd18; qbpp_next = 5'd5; end
|
||||
6'd8: begin range_next = 17'd16; qbpp_next = 5'd4; end
|
||||
6'd9: begin range_next = 17'd15; qbpp_next = 5'd4; end
|
||||
6'd10: begin range_next = 17'd14; qbpp_next = 5'd4; end
|
||||
6'd11: begin range_next = 17'd13; qbpp_next = 5'd4; end
|
||||
6'd12: begin range_next = 17'd12; qbpp_next = 5'd4; end
|
||||
6'd13: begin range_next = 17'd11; qbpp_next = 5'd4; end
|
||||
6'd14: begin range_next = 17'd10; qbpp_next = 5'd4; end
|
||||
6'd15: begin range_next = 17'd10; qbpp_next = 5'd4; end
|
||||
6'd16: begin range_next = 17'd9; qbpp_next = 5'd4; end
|
||||
6'd17: begin range_next = 17'd9; qbpp_next = 5'd4; end
|
||||
6'd18: begin range_next = 17'd8; qbpp_next = 5'd3; end
|
||||
6'd19: begin range_next = 17'd8; qbpp_next = 5'd3; end
|
||||
6'd20: begin range_next = 17'd8; qbpp_next = 5'd3; end
|
||||
6'd21: begin range_next = 17'd7; qbpp_next = 5'd3; end
|
||||
6'd22: begin range_next = 17'd7; qbpp_next = 5'd3; end
|
||||
6'd23: begin range_next = 17'd7; qbpp_next = 5'd3; end
|
||||
6'd24: begin range_next = 17'd7; qbpp_next = 5'd3; end
|
||||
6'd25: begin range_next = 17'd6; qbpp_next = 5'd3; end
|
||||
6'd26: begin range_next = 17'd6; qbpp_next = 5'd3; end
|
||||
6'd27: begin range_next = 17'd6; qbpp_next = 5'd3; end
|
||||
6'd28: begin range_next = 17'd6; qbpp_next = 5'd3; end
|
||||
6'd29: begin range_next = 17'd6; qbpp_next = 5'd3; end
|
||||
6'd30: begin range_next = 17'd6; qbpp_next = 5'd3; end
|
||||
default: begin range_next = 17'd6; qbpp_next = 5'd3; end
|
||||
endcase
|
||||
maximum_sample_value_int = 255;
|
||||
limit_int = 32;
|
||||
end
|
||||
|
||||
10: begin
|
||||
limit_next = 7'd40;
|
||||
case (near_clamped)
|
||||
6'd0: begin range_next = 17'd1024; qbpp_next = 5'd10; end
|
||||
6'd1: begin range_next = 17'd342; qbpp_next = 5'd9; end
|
||||
6'd2: begin range_next = 17'd206; qbpp_next = 5'd8; end
|
||||
6'd3: begin range_next = 17'd148; qbpp_next = 5'd8; end
|
||||
6'd4: begin range_next = 17'd115; qbpp_next = 5'd7; end
|
||||
6'd5: begin range_next = 17'd94; qbpp_next = 5'd7; end
|
||||
6'd6: begin range_next = 17'd80; qbpp_next = 5'd7; end
|
||||
6'd7: begin range_next = 17'd70; qbpp_next = 5'd7; end
|
||||
6'd8: begin range_next = 17'd62; qbpp_next = 5'd6; end
|
||||
6'd9: begin range_next = 17'd55; qbpp_next = 5'd6; end
|
||||
6'd10: begin range_next = 17'd50; qbpp_next = 5'd6; end
|
||||
6'd11: begin range_next = 17'd46; qbpp_next = 5'd6; end
|
||||
6'd12: begin range_next = 17'd42; qbpp_next = 5'd6; end
|
||||
6'd13: begin range_next = 17'd39; qbpp_next = 5'd6; end
|
||||
6'd14: begin range_next = 17'd37; qbpp_next = 5'd6; end
|
||||
6'd15: begin range_next = 17'd34; qbpp_next = 5'd6; end
|
||||
6'd16: begin range_next = 17'd32; qbpp_next = 5'd5; end
|
||||
6'd17: begin range_next = 17'd31; qbpp_next = 5'd5; end
|
||||
6'd18: begin range_next = 17'd29; qbpp_next = 5'd5; end
|
||||
6'd19: begin range_next = 17'd28; qbpp_next = 5'd5; end
|
||||
6'd20: begin range_next = 17'd26; qbpp_next = 5'd5; end
|
||||
6'd21: begin range_next = 17'd25; qbpp_next = 5'd5; end
|
||||
6'd22: begin range_next = 17'd24; qbpp_next = 5'd5; end
|
||||
6'd23: begin range_next = 17'd23; qbpp_next = 5'd5; end
|
||||
6'd24: begin range_next = 17'd22; qbpp_next = 5'd5; end
|
||||
6'd25: begin range_next = 17'd22; qbpp_next = 5'd5; end
|
||||
6'd26: begin range_next = 17'd21; qbpp_next = 5'd5; end
|
||||
6'd27: begin range_next = 17'd20; qbpp_next = 5'd5; end
|
||||
6'd28: begin range_next = 17'd19; qbpp_next = 5'd5; end
|
||||
6'd29: begin range_next = 17'd19; qbpp_next = 5'd5; end
|
||||
6'd30: begin range_next = 17'd18; qbpp_next = 5'd5; end
|
||||
default: begin range_next = 17'd18; qbpp_next = 5'd5; end
|
||||
endcase
|
||||
maximum_sample_value_int = 1023;
|
||||
limit_int = 40;
|
||||
end
|
||||
|
||||
12: begin
|
||||
limit_next = 7'd48;
|
||||
case (near_clamped)
|
||||
6'd0: begin range_next = 17'd4096; qbpp_next = 5'd12; end
|
||||
6'd1: begin range_next = 17'd1366; qbpp_next = 5'd11; end
|
||||
6'd2: begin range_next = 17'd820; qbpp_next = 5'd10; end
|
||||
6'd3: begin range_next = 17'd586; qbpp_next = 5'd10; end
|
||||
6'd4: begin range_next = 17'd456; qbpp_next = 5'd9; end
|
||||
6'd5: begin range_next = 17'd374; qbpp_next = 5'd9; end
|
||||
6'd6: begin range_next = 17'd316; qbpp_next = 5'd9; end
|
||||
6'd7: begin range_next = 17'd274; qbpp_next = 5'd9; end
|
||||
6'd8: begin range_next = 17'd242; qbpp_next = 5'd8; end
|
||||
6'd9: begin range_next = 17'd217; qbpp_next = 5'd8; end
|
||||
6'd10: begin range_next = 17'd196; qbpp_next = 5'd8; end
|
||||
6'd11: begin range_next = 17'd180; qbpp_next = 5'd8; end
|
||||
6'd12: begin range_next = 17'd165; qbpp_next = 5'd8; end
|
||||
6'd13: begin range_next = 17'd153; qbpp_next = 5'd8; end
|
||||
6'd14: begin range_next = 17'd143; qbpp_next = 5'd8; end
|
||||
6'd15: begin range_next = 17'd134; qbpp_next = 5'd8; end
|
||||
6'd16: begin range_next = 17'd126; qbpp_next = 5'd7; end
|
||||
6'd17: begin range_next = 17'd118; qbpp_next = 5'd7; end
|
||||
6'd18: begin range_next = 17'd112; qbpp_next = 5'd7; end
|
||||
6'd19: begin range_next = 17'd106; qbpp_next = 5'd7; end
|
||||
6'd20: begin range_next = 17'd101; qbpp_next = 5'd7; end
|
||||
6'd21: begin range_next = 17'd97; qbpp_next = 5'd7; end
|
||||
6'd22: begin range_next = 17'd92; qbpp_next = 5'd7; end
|
||||
6'd23: begin range_next = 17'd89; qbpp_next = 5'd7; end
|
||||
6'd24: begin range_next = 17'd85; qbpp_next = 5'd7; end
|
||||
6'd25: begin range_next = 17'd82; qbpp_next = 5'd7; end
|
||||
6'd26: begin range_next = 17'd79; qbpp_next = 5'd7; end
|
||||
6'd27: begin range_next = 17'd76; qbpp_next = 5'd7; end
|
||||
6'd28: begin range_next = 17'd73; qbpp_next = 5'd7; end
|
||||
6'd29: begin range_next = 17'd71; qbpp_next = 5'd7; end
|
||||
6'd30: begin range_next = 17'd69; qbpp_next = 5'd7; end
|
||||
default: begin range_next = 17'd66; qbpp_next = 5'd7; end
|
||||
endcase
|
||||
maximum_sample_value_int = 4095;
|
||||
limit_int = 48;
|
||||
end
|
||||
|
||||
14: begin
|
||||
limit_next = 7'd56;
|
||||
case (near_clamped)
|
||||
6'd0: begin range_next = 17'd16384; qbpp_next = 5'd14; end
|
||||
6'd1: begin range_next = 17'd5462; qbpp_next = 5'd13; end
|
||||
6'd2: begin range_next = 17'd3278; qbpp_next = 5'd12; end
|
||||
6'd3: begin range_next = 17'd2342; qbpp_next = 5'd12; end
|
||||
6'd4: begin range_next = 17'd1822; qbpp_next = 5'd11; end
|
||||
6'd5: begin range_next = 17'd1491; qbpp_next = 5'd11; end
|
||||
6'd6: begin range_next = 17'd1262; qbpp_next = 5'd11; end
|
||||
6'd7: begin range_next = 17'd1094; qbpp_next = 5'd11; end
|
||||
6'd8: begin range_next = 17'd965; qbpp_next = 5'd10; end
|
||||
6'd9: begin range_next = 17'd864; qbpp_next = 5'd10; end
|
||||
6'd10: begin range_next = 17'd782; qbpp_next = 5'd10; end
|
||||
6'd11: begin range_next = 17'd714; qbpp_next = 5'd10; end
|
||||
6'd12: begin range_next = 17'd657; qbpp_next = 5'd10; end
|
||||
6'd13: begin range_next = 17'd608; qbpp_next = 5'd10; end
|
||||
6'd14: begin range_next = 17'd566; qbpp_next = 5'd10; end
|
||||
6'd15: begin range_next = 17'd530; qbpp_next = 5'd10; end
|
||||
6'd16: begin range_next = 17'd498; qbpp_next = 5'd9; end
|
||||
6'd17: begin range_next = 17'd470; qbpp_next = 5'd9; end
|
||||
6'd18: begin range_next = 17'd444; qbpp_next = 5'd9; end
|
||||
6'd19: begin range_next = 17'd422; qbpp_next = 5'd9; end
|
||||
6'd20: begin range_next = 17'd401; qbpp_next = 5'd9; end
|
||||
6'd21: begin range_next = 17'd382; qbpp_next = 5'd9; end
|
||||
6'd22: begin range_next = 17'd366; qbpp_next = 5'd9; end
|
||||
6'd23: begin range_next = 17'd350; qbpp_next = 5'd9; end
|
||||
6'd24: begin range_next = 17'd336; qbpp_next = 5'd9; end
|
||||
6'd25: begin range_next = 17'd323; qbpp_next = 5'd9; end
|
||||
6'd26: begin range_next = 17'd311; qbpp_next = 5'd9; end
|
||||
6'd27: begin range_next = 17'd299; qbpp_next = 5'd9; end
|
||||
6'd28: begin range_next = 17'd289; qbpp_next = 5'd9; end
|
||||
6'd29: begin range_next = 17'd279; qbpp_next = 5'd9; end
|
||||
6'd30: begin range_next = 17'd270; qbpp_next = 5'd9; end
|
||||
default: begin range_next = 17'd262; qbpp_next = 5'd9; end
|
||||
endcase
|
||||
maximum_sample_value_int = 16383;
|
||||
limit_int = 56;
|
||||
end
|
||||
|
||||
default: begin
|
||||
limit_next = 7'd64;
|
||||
case (near_clamped)
|
||||
6'd0: begin range_next = 17'd65536; qbpp_next = 5'd16; end
|
||||
6'd1: begin range_next = 17'd21846; qbpp_next = 5'd15; end
|
||||
6'd2: begin range_next = 17'd13108; qbpp_next = 5'd14; end
|
||||
6'd3: begin range_next = 17'd9364; qbpp_next = 5'd14; end
|
||||
6'd4: begin range_next = 17'd7283; qbpp_next = 5'd13; end
|
||||
6'd5: begin range_next = 17'd5959; qbpp_next = 5'd13; end
|
||||
6'd6: begin range_next = 17'd5043; qbpp_next = 5'd13; end
|
||||
6'd7: begin range_next = 17'd4370; qbpp_next = 5'd13; end
|
||||
6'd8: begin range_next = 17'd3856; qbpp_next = 5'd12; end
|
||||
6'd9: begin range_next = 17'd3451; qbpp_next = 5'd12; end
|
||||
6'd10: begin range_next = 17'd3122; qbpp_next = 5'd12; end
|
||||
6'd11: begin range_next = 17'd2851; qbpp_next = 5'd12; end
|
||||
6'd12: begin range_next = 17'd2623; qbpp_next = 5'd12; end
|
||||
6'd13: begin range_next = 17'd2429; qbpp_next = 5'd12; end
|
||||
6'd14: begin range_next = 17'd2261; qbpp_next = 5'd12; end
|
||||
6'd15: begin range_next = 17'd2116; qbpp_next = 5'd12; end
|
||||
6'd16: begin range_next = 17'd1987; qbpp_next = 5'd11; end
|
||||
6'd17: begin range_next = 17'd1874; qbpp_next = 5'd11; end
|
||||
6'd18: begin range_next = 17'd1773; qbpp_next = 5'd11; end
|
||||
6'd19: begin range_next = 17'd1682; qbpp_next = 5'd11; end
|
||||
6'd20: begin range_next = 17'd1600; qbpp_next = 5'd11; end
|
||||
6'd21: begin range_next = 17'd1526; qbpp_next = 5'd11; end
|
||||
6'd22: begin range_next = 17'd1458; qbpp_next = 5'd11; end
|
||||
6'd23: begin range_next = 17'd1396; qbpp_next = 5'd11; end
|
||||
6'd24: begin range_next = 17'd1339; qbpp_next = 5'd11; end
|
||||
6'd25: begin range_next = 17'd1286; qbpp_next = 5'd11; end
|
||||
6'd26: begin range_next = 17'd1238; qbpp_next = 5'd11; end
|
||||
6'd27: begin range_next = 17'd1193; qbpp_next = 5'd11; end
|
||||
6'd28: begin range_next = 17'd1151; qbpp_next = 5'd11; end
|
||||
6'd29: begin range_next = 17'd1112; qbpp_next = 5'd11; end
|
||||
6'd30: begin range_next = 17'd1076; qbpp_next = 5'd11; end
|
||||
default: begin range_next = 17'd1042; qbpp_next = 5'd11; end
|
||||
endcase
|
||||
maximum_sample_value_int = 65535;
|
||||
limit_int = 64;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
RANGE = range_next;
|
||||
qbpp = qbpp_next;
|
||||
LIMIT = limit_next;
|
||||
maximum_near_int = maximum_sample_value_int / 2;
|
||||
if (maximum_near_int > 255) begin
|
||||
maximum_near_int = 255;
|
||||
end
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
near_clamped_int = NEAR;
|
||||
if (near_clamped_int > maximum_near_int) begin
|
||||
near_clamped_int = maximum_near_int;
|
||||
end
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
denominator_int = (2 * near_clamped_int) + 1;
|
||||
range_int = ((maximum_sample_value_int + (2 * near_clamped_int)) / denominator_int) + 1;
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
qbpp_int = 0;
|
||||
if (range_int > 1) begin
|
||||
qbpp_int = 1;
|
||||
if (range_int > 2) begin
|
||||
qbpp_int = 2;
|
||||
end
|
||||
if (range_int > 4) begin
|
||||
qbpp_int = 3;
|
||||
end
|
||||
if (range_int > 8) begin
|
||||
qbpp_int = 4;
|
||||
end
|
||||
if (range_int > 16) begin
|
||||
qbpp_int = 5;
|
||||
end
|
||||
if (range_int > 32) begin
|
||||
qbpp_int = 6;
|
||||
end
|
||||
if (range_int > 64) begin
|
||||
qbpp_int = 7;
|
||||
end
|
||||
if (range_int > 128) begin
|
||||
qbpp_int = 8;
|
||||
end
|
||||
if (range_int > 256) begin
|
||||
qbpp_int = 9;
|
||||
end
|
||||
if (range_int > 512) begin
|
||||
qbpp_int = 10;
|
||||
end
|
||||
if (range_int > 1024) begin
|
||||
qbpp_int = 11;
|
||||
end
|
||||
if (range_int > 2048) begin
|
||||
qbpp_int = 12;
|
||||
end
|
||||
if (range_int > 4096) begin
|
||||
qbpp_int = 13;
|
||||
end
|
||||
if (range_int > 8192) begin
|
||||
qbpp_int = 14;
|
||||
end
|
||||
if (range_int > 16384) begin
|
||||
qbpp_int = 15;
|
||||
end
|
||||
if (range_int > 32768) begin
|
||||
qbpp_int = 16;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
RANGE = range_int[16:0];
|
||||
qbpp = qbpp_int[4:0];
|
||||
LIMIT = limit_int[6:0];
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
@@ -20,8 +20,8 @@ package jls_common_pkg;
|
||||
// Output FIFO byte plus original-image-start sideband bit.
|
||||
localparam int JLS_OFIFO_WIDTH = 9;
|
||||
|
||||
// JPEG-LS NEAR is clamped to 0..31 in this IP.
|
||||
localparam int JLS_NEAR_WIDTH = 6;
|
||||
// JPEG-LS NEAR transport width. The standard valid range is 0..min(255,MAXVAL/2).
|
||||
localparam int JLS_NEAR_WIDTH = 8;
|
||||
|
||||
// JPEG marker byte used by SOI/SOF55/LSE/SOS/EOI marker generation.
|
||||
localparam logic [7:0] JLS_MARKER_PREFIX = 8'hFF;
|
||||
|
||||
@@ -4,14 +4,11 @@
|
||||
// Table : N/A
|
||||
// Pseudocode : product = multiplicand * (2 * NEAR + 1)
|
||||
// Trace : docs/jls_traceability.md#regular-error-quantization
|
||||
// Example : multiplicand=5 and near_scale=5 gives 25.
|
||||
// Example : multiplicand=5 and near_scale=9 gives 45.
|
||||
//
|
||||
// The JPEG-LS NEAR scale is always an odd 6-bit positive value in the range
|
||||
// 1..63. Vivado tended to map these narrow-scale multiplies into cascaded
|
||||
// DSP48E1 structures, which put PCOUT->PCIN on the top timing path. This
|
||||
// helper keeps the operation in carry chains with a fixed three-adder shape:
|
||||
// one partial sum for bits [2:0], one partial sum for bits [5:3], then a final
|
||||
// add. The caller provides the surrounding pipeline registers.
|
||||
// The JPEG-LS NEAR scale is always an odd positive value in the range 1..511.
|
||||
// This helper keeps the multiply in carry-chain style by grouping the odd-scale
|
||||
// bits into three 3-bit slices: [2:0], [5:3], and [8:6].
|
||||
|
||||
`default_nettype none
|
||||
|
||||
@@ -20,7 +17,7 @@ module jls_near_scale_mul #(
|
||||
parameter int OUTPUT_WIDTH = 41
|
||||
) (
|
||||
input var logic signed [INPUT_WIDTH-1:0] multiplicand_i,
|
||||
input var logic [5:0] near_scale_i,
|
||||
input var logic [8:0] near_scale_i,
|
||||
output logic signed [OUTPUT_WIDTH-1:0] product_o
|
||||
);
|
||||
|
||||
@@ -32,7 +29,11 @@ module jls_near_scale_mul #(
|
||||
logic signed [OUTPUT_WIDTH-1:0] multiplicand_shift_3;
|
||||
logic signed [OUTPUT_WIDTH-1:0] multiplicand_shift_4;
|
||||
logic signed [OUTPUT_WIDTH-1:0] multiplicand_shift_5;
|
||||
logic signed [OUTPUT_WIDTH-1:0] multiplicand_shift_6;
|
||||
logic signed [OUTPUT_WIDTH-1:0] multiplicand_shift_7;
|
||||
logic signed [OUTPUT_WIDTH-1:0] multiplicand_shift_8;
|
||||
logic signed [OUTPUT_WIDTH-1:0] partial_lo;
|
||||
logic signed [OUTPUT_WIDTH-1:0] partial_mid;
|
||||
logic signed [OUTPUT_WIDTH-1:0] partial_hi;
|
||||
|
||||
always_comb begin
|
||||
@@ -42,6 +43,9 @@ module jls_near_scale_mul #(
|
||||
multiplicand_shift_3 = multiplicand_ext <<< 3;
|
||||
multiplicand_shift_4 = multiplicand_ext <<< 4;
|
||||
multiplicand_shift_5 = multiplicand_ext <<< 5;
|
||||
multiplicand_shift_6 = multiplicand_ext <<< 6;
|
||||
multiplicand_shift_7 = multiplicand_ext <<< 7;
|
||||
multiplicand_shift_8 = multiplicand_ext <<< 8;
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
@@ -59,19 +63,32 @@ module jls_near_scale_mul #(
|
||||
|
||||
always_comb begin
|
||||
case (near_scale_i[5:3])
|
||||
3'b000: partial_hi = {OUTPUT_WIDTH{1'b0}};
|
||||
3'b001: partial_hi = multiplicand_shift_3;
|
||||
3'b010: partial_hi = multiplicand_shift_4;
|
||||
3'b011: partial_hi = multiplicand_shift_3 + multiplicand_shift_4;
|
||||
3'b100: partial_hi = multiplicand_shift_5;
|
||||
3'b101: partial_hi = multiplicand_shift_3 + multiplicand_shift_5;
|
||||
3'b110: partial_hi = multiplicand_shift_4 + multiplicand_shift_5;
|
||||
default: partial_hi = multiplicand_shift_3 + multiplicand_shift_4 + multiplicand_shift_5;
|
||||
3'b000: partial_mid = {OUTPUT_WIDTH{1'b0}};
|
||||
3'b001: partial_mid = multiplicand_shift_3;
|
||||
3'b010: partial_mid = multiplicand_shift_4;
|
||||
3'b011: partial_mid = multiplicand_shift_3 + multiplicand_shift_4;
|
||||
3'b100: partial_mid = multiplicand_shift_5;
|
||||
3'b101: partial_mid = multiplicand_shift_3 + multiplicand_shift_5;
|
||||
3'b110: partial_mid = multiplicand_shift_4 + multiplicand_shift_5;
|
||||
default: partial_mid = multiplicand_shift_3 + multiplicand_shift_4 + multiplicand_shift_5;
|
||||
endcase
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
product_o = partial_lo + partial_hi;
|
||||
case (near_scale_i[8:6])
|
||||
3'b000: partial_hi = {OUTPUT_WIDTH{1'b0}};
|
||||
3'b001: partial_hi = multiplicand_shift_6;
|
||||
3'b010: partial_hi = multiplicand_shift_7;
|
||||
3'b011: partial_hi = multiplicand_shift_6 + multiplicand_shift_7;
|
||||
3'b100: partial_hi = multiplicand_shift_8;
|
||||
3'b101: partial_hi = multiplicand_shift_6 + multiplicand_shift_8;
|
||||
3'b110: partial_hi = multiplicand_shift_7 + multiplicand_shift_8;
|
||||
default: partial_hi = multiplicand_shift_6 + multiplicand_shift_7 + multiplicand_shift_8;
|
||||
endcase
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
product_o = partial_lo + partial_mid + partial_hi;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
@@ -2,18 +2,15 @@
|
||||
// Clause : Annex C.2.4.1.1 preset coding parameters
|
||||
// Figure : C.3 clamping function, referenced by default threshold rules
|
||||
// Table : Table C.1 valid preset parameters, Table C.2 RESET, Table C.3 defaults
|
||||
// Pseudocode : Default threshold calculation for MAXVAL >= 128
|
||||
// Pseudocode : Default threshold calculation with MAXVAL and NEAR
|
||||
// Trace : docs/jls_traceability.md#jls-preset-defaults
|
||||
// Example : PIX_WIDTH=8, NEAR=0 gives MAXVAL=255, T1=3, T2=7, T3=21.
|
||||
//
|
||||
// JPEG-LS default preset coding parameter helper. The first RTL version only
|
||||
// supports 8/10/12/14/16-bit grayscale samples and NEAR is clamped to 0..31.
|
||||
// For all supported sample precisions MAXVAL >= 128. With NEAR <= 31 the
|
||||
// default thresholds do not hit MAXVAL, so the standard C.2.4.1.1 equations
|
||||
// reduce to shallow shift-add expressions:
|
||||
// T1 = FACTOR * 1 + 2 + 3*NEAR
|
||||
// T2 = FACTOR * 4 + 3 + 5*NEAR
|
||||
// T3 = FACTOR * 17 + 4 + 7*NEAR
|
||||
// JPEG-LS default preset coding parameter helper. This version follows the
|
||||
// full CharLS/ISO formula and supports NEAR up to min(255, MAXVAL/2). The
|
||||
// work is strip-level control, not per-pixel, so one combinational divide is
|
||||
// acceptable here and keeps the pixel pipeline independent of the wider NEAR
|
||||
// range.
|
||||
|
||||
`default_nettype none
|
||||
|
||||
@@ -21,8 +18,8 @@ module jls_preset_defaults #(
|
||||
// Compile-time grayscale sample precision. Legal values: 8, 10, 12, 14, 16.
|
||||
parameter int PIX_WIDTH = 16
|
||||
) (
|
||||
// Requested NEAR value. Values above 31 are clamped defensively.
|
||||
input var logic [5:0] near,
|
||||
// Requested NEAR value. Values above min(255, MAXVAL/2) are clamped.
|
||||
input var logic [7:0] near,
|
||||
|
||||
// JPEG-LS LSE MAXVAL preset coding parameter.
|
||||
output logic [15:0] preset_maxval,
|
||||
@@ -40,97 +37,137 @@ module jls_preset_defaults #(
|
||||
output logic [15:0] preset_reset
|
||||
);
|
||||
|
||||
// Default RESET value from T.87 Table C.2.
|
||||
localparam logic [15:0] DEFAULT_RESET_VALUE = 16'd64;
|
||||
localparam int DEFAULT_RESET_VALUE = 64;
|
||||
localparam int BASIC_T1 = 3;
|
||||
localparam int BASIC_T2 = 7;
|
||||
localparam int BASIC_T3 = 21;
|
||||
|
||||
// Defensive NEAR clamp for the project maximum.
|
||||
logic [5:0] near_clamped;
|
||||
|
||||
// Shift-add terms for 3*NEAR, 5*NEAR, and 7*NEAR.
|
||||
logic [15:0] near_ext;
|
||||
logic [15:0] near_times_2;
|
||||
logic [15:0] near_times_3;
|
||||
logic [15:0] near_times_4;
|
||||
logic [15:0] near_times_5;
|
||||
logic [15:0] near_times_7;
|
||||
|
||||
// Base threshold values after applying the standard FACTOR term.
|
||||
logic [15:0] base_t1;
|
||||
logic [15:0] base_t2;
|
||||
logic [15:0] base_t3;
|
||||
integer maximum_sample_value_int;
|
||||
integer maximum_near_int;
|
||||
integer near_clamped_int;
|
||||
integer factor_int;
|
||||
integer threshold1_candidate;
|
||||
integer threshold2_candidate;
|
||||
integer threshold3_candidate;
|
||||
integer threshold1_int;
|
||||
integer threshold2_int;
|
||||
integer threshold3_int;
|
||||
|
||||
always_comb begin
|
||||
near_clamped = near;
|
||||
if (near > 6'd31) begin
|
||||
near_clamped = 6'd31;
|
||||
end
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
near_ext = {10'd0, near_clamped};
|
||||
near_times_2 = {near_ext[14:0], 1'b0};
|
||||
near_times_3 = near_times_2 + near_ext;
|
||||
near_times_4 = {near_ext[13:0], 2'b00};
|
||||
near_times_5 = near_times_4 + near_ext;
|
||||
near_times_7 = near_times_4 + near_times_2 + near_ext;
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
preset_maxval = 16'hFFFF;
|
||||
base_t1 = 16'd18;
|
||||
base_t2 = 16'd67;
|
||||
base_t3 = 16'd276;
|
||||
|
||||
maximum_sample_value_int = 65535;
|
||||
case (PIX_WIDTH)
|
||||
8: begin
|
||||
preset_maxval = 16'd255;
|
||||
base_t1 = 16'd3;
|
||||
base_t2 = 16'd7;
|
||||
base_t3 = 16'd21;
|
||||
maximum_sample_value_int = 255;
|
||||
end
|
||||
|
||||
10: begin
|
||||
preset_maxval = 16'd1023;
|
||||
base_t1 = 16'd6;
|
||||
base_t2 = 16'd19;
|
||||
base_t3 = 16'd72;
|
||||
maximum_sample_value_int = 1023;
|
||||
end
|
||||
|
||||
12: begin
|
||||
preset_maxval = 16'd4095;
|
||||
base_t1 = 16'd18;
|
||||
base_t2 = 16'd67;
|
||||
base_t3 = 16'd276;
|
||||
maximum_sample_value_int = 4095;
|
||||
end
|
||||
|
||||
14: begin
|
||||
preset_maxval = 16'd16383;
|
||||
base_t1 = 16'd18;
|
||||
base_t2 = 16'd67;
|
||||
base_t3 = 16'd276;
|
||||
end
|
||||
|
||||
16: begin
|
||||
preset_maxval = 16'hFFFF;
|
||||
base_t1 = 16'd18;
|
||||
base_t2 = 16'd67;
|
||||
base_t3 = 16'd276;
|
||||
maximum_sample_value_int = 16383;
|
||||
end
|
||||
|
||||
default: begin
|
||||
preset_maxval = 16'hFFFF;
|
||||
base_t1 = 16'd18;
|
||||
base_t2 = 16'd67;
|
||||
base_t3 = 16'd276;
|
||||
maximum_sample_value_int = 65535;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
preset_t1 = base_t1 + near_times_3;
|
||||
preset_t2 = base_t2 + near_times_5;
|
||||
preset_t3 = base_t3 + near_times_7;
|
||||
preset_reset = DEFAULT_RESET_VALUE;
|
||||
maximum_near_int = maximum_sample_value_int / 2;
|
||||
if (maximum_near_int > 255) begin
|
||||
maximum_near_int = 255;
|
||||
end
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
near_clamped_int = near;
|
||||
if (near_clamped_int > maximum_near_int) begin
|
||||
near_clamped_int = maximum_near_int;
|
||||
end
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
factor_int = 1;
|
||||
if (maximum_sample_value_int >= 128) begin
|
||||
factor_int = maximum_sample_value_int;
|
||||
if (factor_int > 4095) begin
|
||||
factor_int = 4095;
|
||||
end
|
||||
factor_int = (factor_int + 128) / 256;
|
||||
|
||||
threshold1_candidate = (factor_int * (BASIC_T1 - 2)) + 2 + (3 * near_clamped_int);
|
||||
if ((threshold1_candidate > maximum_sample_value_int) ||
|
||||
(threshold1_candidate < (near_clamped_int + 1))) begin
|
||||
threshold1_int = near_clamped_int + 1;
|
||||
end else begin
|
||||
threshold1_int = threshold1_candidate;
|
||||
end
|
||||
|
||||
threshold2_candidate = (factor_int * (BASIC_T2 - 3)) + 3 + (5 * near_clamped_int);
|
||||
if ((threshold2_candidate > maximum_sample_value_int) ||
|
||||
(threshold2_candidate < threshold1_int)) begin
|
||||
threshold2_int = threshold1_int;
|
||||
end else begin
|
||||
threshold2_int = threshold2_candidate;
|
||||
end
|
||||
|
||||
threshold3_candidate = (factor_int * (BASIC_T3 - 4)) + 4 + (7 * near_clamped_int);
|
||||
if ((threshold3_candidate > maximum_sample_value_int) ||
|
||||
(threshold3_candidate < threshold2_int)) begin
|
||||
threshold3_int = threshold2_int;
|
||||
end else begin
|
||||
threshold3_int = threshold3_candidate;
|
||||
end
|
||||
end else begin
|
||||
factor_int = 256 / (maximum_sample_value_int + 1);
|
||||
|
||||
threshold1_candidate = (BASIC_T1 / factor_int) + (3 * near_clamped_int);
|
||||
if (threshold1_candidate < 2) begin
|
||||
threshold1_candidate = 2;
|
||||
end
|
||||
if ((threshold1_candidate > maximum_sample_value_int) ||
|
||||
(threshold1_candidate < (near_clamped_int + 1))) begin
|
||||
threshold1_int = near_clamped_int + 1;
|
||||
end else begin
|
||||
threshold1_int = threshold1_candidate;
|
||||
end
|
||||
|
||||
threshold2_candidate = (BASIC_T2 / factor_int) + (5 * near_clamped_int);
|
||||
if (threshold2_candidate < 3) begin
|
||||
threshold2_candidate = 3;
|
||||
end
|
||||
if ((threshold2_candidate > maximum_sample_value_int) ||
|
||||
(threshold2_candidate < threshold1_int)) begin
|
||||
threshold2_int = threshold1_int;
|
||||
end else begin
|
||||
threshold2_int = threshold2_candidate;
|
||||
end
|
||||
|
||||
threshold3_candidate = (BASIC_T3 / factor_int) + (7 * near_clamped_int);
|
||||
if (threshold3_candidate < 4) begin
|
||||
threshold3_candidate = 4;
|
||||
end
|
||||
if ((threshold3_candidate > maximum_sample_value_int) ||
|
||||
(threshold3_candidate < threshold2_int)) begin
|
||||
threshold3_int = threshold2_int;
|
||||
end else begin
|
||||
threshold3_int = threshold3_candidate;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
preset_maxval = maximum_sample_value_int[15:0];
|
||||
preset_t1 = threshold1_int[15:0];
|
||||
preset_t2 = threshold2_int[15:0];
|
||||
preset_t3 = threshold3_int[15:0];
|
||||
preset_reset = DEFAULT_RESET_VALUE[15:0];
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
Reference in New Issue
Block a user