NVC code coverage report

File:  ../../Sources/openjls_top.vhd

     0:   ------------------------------------------------------------------------------------------------------------- 
     1:   -- Engineer:    Vitor Mendes Camilo 
     2:   -- 
     3:   -- Module Name: openjls_top - rtl 
     4:   -- Description: JPEG-LS T.87 lossless encoder top level. 
     5:   -- 
     6:   --          The architecture is a 14 stage pipeline with: 
     7:   --          1 input stage + 6 processing stages + 7 output stages. 
     8:   --          The output stages are internally registered in the IPs, while the processing 
     9:   --          stages are purely combinational and the inter-stage registers are placed in 
    10:   --          this top-level wrapper 
    11:   -- 
    12:   -------------------------------------------------------------------------------------------- 
    13:   -- PIPELINE 
    14:   -------------------------------------------------------------------------------------------- 
    15:   -- 
    16:   --   Input Stage : Wire 
    17:   -- 
    18:   -- RegInput ------- 
    19:   -- 
    20:   --   Stage 1     : A.1 gradients + A.3 mode select 
    21:   --                 line_buffer 
    22:   -- 
    23:   -- Reg1 ----------- 
    24:   -- 
    25:   --   Stage 2     : regular {A.4, A.4.1, A.4.2} | run {A.14, A.15/16, A.17, A.18} 
    26:   --                 context_ram 
    27:   -- 
    28:   -- Reg2 ----------- 
    29:   -- 
    30:   --   Stage 3     : regular {A.5, speculative 3×{A.6..A.9}} | RI {A.19, A.20} 
    31:   --                 feed-forward logic for speculation and Q3==Q4 forwarding 
    32:   -- 
    33:   -- Reg3 ----------- 
    34:   -- 
    35:   --   Stage 4     : shared {A.10} | regular {A.12, A.13} | RI {A.23}; 
    36:   --                 context writeback 
    37:   -- 
    38:   -- Reg4 ----------- 
    39:   -- 
    40:   --   Stage 5     : regular {A.11} | RI {A.21, A.22}; 
    41:   --                 mux select mapped errval 
    42:   -- 
    43:   -- Reg5 ----------- 
    44:   -- 
    45:   --   Stage 6    : A.11.1 Golomb encoder 
    46:   -- 
    47:   -- Reg6 ----------- 
    48:   -- 
    49:   --   Output Stages (internally registered): 
    50:   -- 
    51:   --                bit_packer 
    52:   --                byte_stuffer 
    53:   --                jls_framer 
    54:   -- 
    55:   ------------------------------------------------------------------------------------------------------------- 
    56:    
    57:   library ieee; 
    58:     use ieee.std_logic_1164.all; 
    59:     use ieee.numeric_std.all; 
    60:     use work.openjls_pkg.all; 
    61:    
    62:   library work; 
    63:     use work.olo_base_pkg_math.log2ceil; 
    64:    
    65:   entity openjls_top is 
    66:     generic ( 
    67:       BITNESS          : positive range 8 to 16    := 12; 
    68:       MAX_IMAGE_WIDTH  : positive range 4 to 65535 := 4096; 
    69:       MAX_IMAGE_HEIGHT : positive range 1 to 65535 := 4096; 
    70:       OUT_WIDTH        : positive range 48 to 1024 := CO_OUT_WIDTH_STD 
    71:     ); 
    72:     port ( 
    73:       iClk             : in    std_logic; 
    74:       iRst             : in    std_logic; 
    75:       iValid           : in    std_logic; 
    76:       iPixel           : in    std_logic_vector(BITNESS - 1 downto 0); 
    77:       oReady           : out   std_logic; 
    78:       -- Fixed 16-bit (not log2ceil-sized): Vivado's block-design port-width 
    79:       -- evaluator only handles literal arithmetic in port expressions. Values 
    80:       -- above MAX_IMAGE_WIDTH/HEIGHT are clamped at sample time as before. 
    81:       iImageWidth      : in    std_logic_vector(15 downto 0); 
    82:       iImageHeight     : in    std_logic_vector(15 downto 0); 
    83:       oData            : out   std_logic_vector(OUT_WIDTH - 1 downto 0); 
    84:       oValid           : out   std_logic; 
    85:       oKeep            : out   std_logic_vector(OUT_WIDTH / 8 - 1 downto 0); 
    86:       oLast            : out   std_logic; 
    87:       iReady           : in    std_logic 
    88:     ); 
    89:   end entity openjls_top; 
    90:    
    91:   architecture rtl of openjls_top is 
    92:    
    93:     constant DEBUG_MODE                       : boolean := false; 
    94:    
    95:     ------------------------------------------------------------------------------------------------------------- 
    96:     -- ENCODER PARAMETERS 
    97:     ------------------------------------------------------------------------------------------------------------- 
    98:     -- Derived constants 
    99:     constant MAX_VAL                          : natural := 2 ** BITNESS - 1; 
   100:     constant RANGE_P                          : natural := MAX_VAL + 1; 
   101:     constant QBPP                             : natural := log2ceil(RANGE_P); 
   102:     constant BPP                              : natural := math_max(2, log2ceil(MAX_VAL + 1)); 
   103:     constant LIMIT                            : natural := 2 * (BPP + math_max(8, BPP)); 
   104:    
   105:     -- Widths computed locally from generics 
   106:     constant ERROR_WIDTH                      : natural  := BITNESS + 1; 
   107:     constant MAPPED_ERROR_VAL_WIDTH           : natural  := BITNESS + 2; 
   108:     constant RAM_DEPTH                        : positive := 367;                                        -- 365 contexts + 2 RI-specific contexts 
   109:     constant RESET                            : natural  := 64;                                         -- T.87 
   110:     constant MAX_C                            : integer  := 127;                                        -- T.87 
   111:     constant MIN_C                            : integer  := - 128;                                      -- T.87 
   112:     constant ABS_MIN_C                        : natural  := - MIN_C; 
   113:     constant ABS_MAX_C                        : natural  := MAX_C; 
   114:    
   115:     -------------------------------------------------------------------------------------------- 
   116:     -- Context-variable widths. 
   117:     -------------------------------------------------------------------------------------------- 
   118:     -- Two tiers: 
   119:     --   _STORED : packed BRAM width (Murat 2018 Table I, "Optimal Bits to 
   120:     --             Represent"). Encoding tricks applied at the BRAM boundary. 
   121:     --   _WIDTH  : pipeline arithmetic width (mid-update headroom for A.12/A.13). 
   122:     --             Needed to compute intermediary values without overflow. 
   123:     -- 
   124:     -------------------------------------------------------------------------------------------- 
   125:     --   Var    Stored                          Encoding @ BRAM           Pipeline width 
   126:     -------------------------------------------------------------------------------------------- 
   127:     --   A      bpp - 1 + ⌈log2(RESET)⌉         zero-extend on read       _STORED + 1 
   128:     --   B      ⌈log2(RESET)⌉ (mag only)        B = -unsigned(stored)     BPP + 1 (signed) 
   129:     --   C      ⌈log2(max|MIN_C|,|MAX_C|)⌉+1    signed cast               = _STORED 
   130:     --   N      ⌈log2(RESET)⌉ (RESET↦0)         0 ⇒ RESET                 log2ceil(RESET+1) 
   131:     --   Nn     ⌈log2(RESET)⌉                   direct                    = _STORED 
   132:    
   133:     constant A_STORED                         : natural := BPP - 1 + log2ceil(RESET); 
   134:     constant B_STORED                         : natural := log2ceil(RESET); 
   135:     constant C_STORED                         : natural := log2ceil(math_max(ABS_MIN_C, ABS_MAX_C)) + 1; 
   136:     constant N_STORED                         : natural := log2ceil(RESET); 
   137:     constant NN_STORED                        : natural := log2ceil(RESET); 
   138:     constant A_WIDTH                          : natural := A_STORED + 1; 
   139:     constant B_WIDTH                          : natural := BPP + 1; 
   140:     constant C_WIDTH                          : natural := C_STORED; 
   141:     constant N_WIDTH                          : natural := log2ceil(RESET + 1); 
   142:     constant NN_WIDTH                         : natural := NN_STORED; 
   143:     constant MAX_K                            : natural := A_WIDTH;                                     -- A10 saturates Golomb k here (max k = bit-width of A) 
   144:     constant K_WIDTH                          : natural := log2ceil(MAX_K + 1);                         -- holds k in [0, MAX_K] 
   145:     constant TOTAL_WIDTH                      : natural := A_STORED + B_STORED + C_STORED + N_STORED; 
   146:    
   147:     -------------------------------------------------------------------------------------------- 
   148:     -- Golomb / Raw suffix output widths. 
   149:     -------------------------------------------------------------------------------------------- 
   150:     --   Raw  : oRawSuffixVal up to RUN_CNT_WIDTH bits, oRawSuffixLen up to 
   151:     --          J_MAX+1 = 16 distinct values (vJ+1, vJ ∈ [0..15] from T.87 J). 
   152:     --   Gol. : regular suffix = k low bits (k <= MAX_K), escape suffix = QBPP bits; 
   153:     --          both fit in MAX_K. Unary zeros <= LIMIT - QBPP - 1 (escape 
   154:     --          threshold; regular quotient is strictly smaller). 
   155:    
   156:     -- Run length bounded by image width (run cannot cross EOL). 
   157:     constant RUN_CNT_WIDTH                    : natural := log2ceil(MAX_IMAGE_WIDTH + 1); 
   158:     constant J_MAX_BITS                       : natural := 15;                                          -- T.87 A.2.1, J[31] = 15 
   159:     constant UNARY_WIDTH                      : natural := log2ceil(LIMIT - QBPP);                      -- regular quotient / escape threshold; max = LIMIT-QBPP-1 
   160:     constant SUFFIX_WIDTH                     : natural := math_max(MAX_K, RUN_CNT_WIDTH);              -- regular k bits / escape QBPP bits, both <= MAX_K 
   161:     constant SUFFIXLEN_WIDTH                  : natural := math_max(K_WIDTH, log2ceil(J_MAX_BITS + 2)); -- regular k / escape QBPP, both <= K_WIDTH 
   162:    
   163:     -------------------------------------------------------------------------------------------- 
   164:     -- Bit packer / byte stuffer / framer interface widths. 
   165:     -- byte_stuffer is sized for AVERAGE rate; bursts absorbed by its buffer, which 
   166:     -- asserts oAlmostFull and stalls upstream near full. OUT_BYTES_PER_CYCLE trades 
   167:     -- fmax vs throughput; BURST_DEPTH=64 covers natural images with margin. 
   168:     -------------------------------------------------------------------------------------------- 
   169:     constant BYTE_STUFFER_OUT_BYTES_PER_CYCLE : natural := 4;                                           -- Hardcoded, fixed 
   170:     constant BYTE_STUFFER_BURST_DEPTH         : natural := 64;                                          -- Can be tuned 
   171:     constant BYTE_STUFFER_OUT_WIDTH           : natural := BYTE_STUFFER_OUT_BYTES_PER_CYCLE * 8; 
   172:    
   173:     -------------------------------------------------------------------------------------------- 
   174:     -- Packed context RAM word slicing 
   175:     -------------------------------------------------------------------------------------------- 
   176:     -- Regular mode:  (A | B  | C | N) 
   177:     -- Run mode:      (A | NN | 0 | N) 
   178:     constant CTX_A_HI                         : natural := TOTAL_WIDTH - 1; 
   179:     constant CTX_A_LO                         : natural := TOTAL_WIDTH - A_STORED; 
   180:     constant CTX_B_HI                         : natural := CTX_A_LO - 1; 
   181:     constant CTX_B_LO                         : natural := CTX_A_LO - B_STORED; 
   182:     constant CTX_C_HI                         : natural := CTX_B_LO - 1; 
   183:     constant CTX_C_LO                         : natural := CTX_B_LO - C_STORED; 
   184:     constant CTX_N_HI                         : natural := CTX_C_LO - 1; 
   185:     constant CTX_N_LO                         : natural := 0; 
   186:     constant CTX_NN_HI                        : natural := CTX_B_LO + NN_STORED - 1; 
   187:     constant CTX_NN_LO                        : natural := CTX_B_LO; 
   188:    
   189:     ------------------------------------------------------------------------------------------------------------- 
   190:     -- PIPELINE TOKEN RECORD 
   191:     ------------------------------------------------------------------------------------------------------------- 
   192:     -- Fields cross inter-stage register boundaries; 
   193:     -- combinational stage-local wires are NOT in the record. 
   194:     -- 
   195:     -- Mode tag: 
   196:     --   TOKEN_NONE             : pipeline bubble — downstream stages NOP 
   197:     --   TOKEN_REGULAR          : regular-mode sample (Golomb only) 
   198:     --   TOKEN_RUN_INTERRUPTION : run break (Golomb + A.16 raw prefix) 
   199:     --   TOKEN_RAW              : mid-run boundary emit (raw only) 
   200:    
   201:     type t_token_mode is (token_none, token_regular, token_run, token_run_interruption, token_raw); 
   202:    
   203:     type t_pipeline_token is record 
   204:       mode       : t_token_mode; 
   205:       Ix         : unsigned(BITNESS - 1 downto 0); 
   206:       Ra         : unsigned(BITNESS - 1 downto 0); 
   207:       Rb         : unsigned(BITNESS - 1 downto 0); 
   208:       Rc         : unsigned(BITNESS - 1 downto 0); 
   209:       Q          : unsigned(8 downto 0); 
   210:       Sign       : std_logic; 
   211:       RiType     : std_logic; 
   212:       Aq         : unsigned(A_WIDTH - 1 downto 0); 
   213:       Bq         : signed(B_WIDTH - 1 downto 0); 
   214:       Cq         : signed(C_WIDTH - 1 downto 0); 
   215:       Nq         : unsigned(N_WIDTH - 1 downto 0); 
   216:       Nn         : unsigned(NN_WIDTH - 1 downto 0); 
   217:       Temp       : unsigned(A_WIDTH - 1 downto 0); 
   218:       Errval     : signed(ERROR_WIDTH - 1 downto 0); 
   219:       k          : unsigned(K_WIDTH - 1 downto 0); 
   220:       RawLen     : unsigned(SUFFIXLEN_WIDTH - 1 downto 0); 
   221:       RawVal     : unsigned(SUFFIX_WIDTH - 1 downto 0); 
   222:       RiRunIndex : unsigned(4 downto 0); 
   223:     end record t_pipeline_token; 
   224:    
   225:     constant CO_TOKEN_NONE                    : t_pipeline_token := 
   226:     ( 
   227:       mode       => token_none, 
   228:       Ix         => (others => '0'), 
   229:       Ra         => (others => '0'), 
   230:       Rb         => (others => '0'), 
   231:       Rc         => (others => '0'), 
   232:       Q          => (others => '0'), 
   233:       Sign       => '0', 
   234:       RiType     => '0', 
   235:       Aq         => (others => '0'), 
   236:       Bq         => (others => '0'), 
   237:       Cq         => (others => '0'), 
   238:       Nq         => (others => '0'), 
   239:       Nn         => (others => '0'), 
   240:       Temp       => (others => '0'), 
   241:       Errval     => (others => '0'), 
   242:       k          => (others => '0'), 
   243:       RawLen     => (others => '0'), 
   244:       RawVal     => (others => '0'), 
   245:       RiRunIndex => (others => '0') 
   246:     ); 
   247:     ------------------------------------------------------------------------------------------------------------- 
   248:    
   249:     -- Backpressure / clock-enable. sStall drives a single coarse pipeline freeze 
   250:     -- when the framer FIFO is approaching its nominal capacity. It also doubles 
   251:     -- as the idle-power gate together with each stage's valid bits: a register 
   252:     -- only updates when (NOT sStall) AND (current_valid OR upstream_valid), so a 
   253:     -- bubble propagates exactly once and then the register stops toggling. 
   254:     signal sFramerReady                       : std_logic; 
   255:     signal sBsAlmostFullReg                   : std_logic; 
   256:     signal sStall                             : std_logic; 
   257:     signal sStallDelay                        : std_logic; 
   258:     signal sStallUpstream                     : std_logic; 
   259:     signal sStallLogic                        : std_logic; 
   260:     signal sCE1                               : std_logic; 
   261:     signal sCE2                               : std_logic; 
   262:     signal sCE3                               : std_logic; 
   263:     signal sCE4                               : std_logic; 
   264:     signal sCE5,     sCE6                     : std_logic; 
   265:    
   266:     -- Pipeline tokens + sideband 
   267:     signal sReg1                              : t_pipeline_token; 
   268:     signal sReg2                              : t_pipeline_token; 
   269:     signal sReg3                              : t_pipeline_token; 
   270:     signal sReg4                              : t_pipeline_token; 
   271:     signal sReg1V                             : std_logic; 
   272:     signal sReg2V                             : std_logic; 
   273:     signal sReg3V                             : std_logic; 
   274:     signal sReg4V                             : std_logic; 
   275:     signal sReg1Eol                           : std_logic; 
   276:     signal sReg1Eoi                           : std_logic; 
   277:     signal sReg2Eoi                           : std_logic; 
   278:     signal sReg3Eoi                           : std_logic; 
   279:     signal sReg4Eoi                           : std_logic; 
   280:    
   281:     -- Per-image parity bit: 1 bit assigned at Reg1, flipped at each EOI, 
   282:     -- carried to the writeback stage. Avoid old image writing values into 
   283:     -- the context ram that belongs to the new image. 
   284:     signal sGenPar                            : std_logic; 
   285:     signal sReg1Par                           : std_logic; 
   286:     signal sReg2Par                           : std_logic; 
   287:     signal sReg3Par                           : std_logic; 
   288:     signal sCtxOwnerPar                       : std_logic;                                              -- sticky: parity owning the ctx RAM (held thru bubbles) 
   289:     signal sCtxRdPar                          : std_logic;                                              -- effective owner this cycle (combinational) 
   290:     signal sReg1ModeRun                       : std_logic; 
   291:     signal sReg1D1                            : signed(BITNESS downto 0); 
   292:     signal sReg1D2                            : signed(BITNESS downto 0); 
   293:     signal sReg1D3                            : signed(BITNESS downto 0); 
   294:    
   295:     -- Input stage 
   296:     signal sPixel                             : unsigned(BITNESS - 1 downto 0); 
   297:     signal sImageWidth                        : unsigned(log2ceil(MAX_IMAGE_WIDTH + 1) - 1 downto 0); 
   298:     signal sImageHeight                       : unsigned(log2ceil(MAX_IMAGE_HEIGHT + 1) - 1 downto 0); 
   299:     signal sValid                             : std_logic;                                              -- iValid & sReady 
   300:     signal sLbRa                              : unsigned(BITNESS - 1 downto 0); 
   301:     signal sLbRb                              : unsigned(BITNESS - 1 downto 0); 
   302:     signal sLbRc                              : unsigned(BITNESS - 1 downto 0); 
   303:     signal sLbRd                              : unsigned(BITNESS - 1 downto 0); 
   304:     signal sLbValid                           : std_logic; 
   305:     signal sLbEol                             : std_logic; 
   306:     signal sLbEoi                             : std_logic; 
   307:    
   308:     -- Stage 1 combinational 
   309:     signal sS1D1                              : signed(BITNESS downto 0); 
   310:     signal sS1D2                              : signed(BITNESS downto 0); 
   311:     signal sS1D3                              : signed(BITNESS downto 0); 
   312:     signal sS1ModeRun                         : std_logic; 
   313:     -- Sticky run flag: A15_16's next-state sInRun, fed back to stage 1 so the 
   314:     -- pixel currently in stage 1 inherits "still in run" from the prior pixel 
   315:     -- in stage 2. Without it, A.3's gradient-based decision can break runs. 
   316:     signal sS1InRunNext                       : std_logic; 
   317:    
   318:     -- Stage 2 — regular 
   319:     signal sS2Q1                              : signed(3 downto 0); 
   320:     signal sS2Q2                              : signed(3 downto 0); 
   321:     signal sS2Q3                              : signed(3 downto 0); 
   322:     signal sS2MQ1                             : signed(3 downto 0); 
   323:     signal sS2MQ2                             : signed(3 downto 0); 
   324:     signal sS2MQ3                             : signed(3 downto 0); 
   325:     signal sS2MSign                           : std_logic; 
   326:     signal sS2QReg                            : unsigned(8 downto 0); 
   327:    
   328:     -- Stage 2 — run 
   329:     signal sRunCntReg                         : unsigned(RUN_CNT_WIDTH - 1 downto 0); 
   330:     signal sS2RunCnt                          : unsigned(RUN_CNT_WIDTH - 1 downto 0); 
   331:     signal sS2RunHit                          : std_logic; 
   332:     signal sS2RunContinue                     : std_logic; 
   333:     signal sS2RItype                          : std_logic; 
   334:     signal sS2RawValid                        : std_logic; 
   335:     signal sS2RawLen                          : unsigned(4 downto 0); 
   336:     signal sS2RawVal                          : unsigned(RUN_CNT_WIDTH - 1 downto 0); 
   337:     signal sS2RiValid                         : std_logic; 
   338:     signal sS2RiIx                            : unsigned(BITNESS - 1 downto 0); 
   339:     signal sS2RiRa                            : unsigned(BITNESS - 1 downto 0); 
   340:     signal sS2RiRb                            : unsigned(BITNESS - 1 downto 0); 
   341:     signal sS2RiRunIndex                      : unsigned(4 downto 0); 
   342:     signal sS2RiErr18                         : signed(BITNESS downto 0); 
   343:    
   344:     -- Stage 2 — muxed 
   345:     signal sS2Q                               : unsigned(8 downto 0); 
   346:     signal sS2TokenMode                       : t_token_mode; 
   347:    
   348:     signal sS2Px                              : unsigned(BITNESS - 1 downto 0); 
   349:     signal sReg2Px                            : unsigned(BITNESS - 1 downto 0); 
   350:    
   351:     -- context_ram packed I/O 
   352:     signal sCtxRdData                         : std_logic_vector(TOTAL_WIDTH - 1 downto 0); 
   353:     signal sCtxWrData                         : std_logic_vector(TOTAL_WIDTH - 1 downto 0); 
   354:     signal sCtxWrEn                           : std_logic; 
   355:    
   356:     -- Stage 3 context (mux between BRAM regular read and RI cluster read) 
   357:     signal sS3Aq                              : unsigned(A_WIDTH - 1 downto 0); 
   358:     signal sS3Bq                              : signed(B_WIDTH - 1 downto 0); 
   359:     signal sS3Cq                              : signed(C_WIDTH - 1 downto 0); 
   360:     signal sS3Nq                              : unsigned(N_WIDTH - 1 downto 0); 
   361:     signal sS3Nn                              : unsigned(NN_WIDTH - 1 downto 0); 
   362:    
   363:     -- Stage 3 — regular prediction (speculative 3-chain) 
   364:     signal sS3Px                              : unsigned(BITNESS - 1 downto 0); 
   365:     signal sS3CqBase                          : signed(C_WIDTH - 1 downto 0); 
   366:     signal sS3CqP1                            : signed(C_WIDTH - 1 downto 0); 
   367:     signal sS3CqM1                            : signed(C_WIDTH - 1 downto 0); 
   368:     signal sS3PxC                             : unsigned(BITNESS - 1 downto 0); 
   369:     signal sS3PxP                             : unsigned(BITNESS - 1 downto 0); 
   370:     signal sS3PxM                             : unsigned(BITNESS - 1 downto 0); 
   371:     signal sS3Err7C                           : signed(BITNESS downto 0); 
   372:     signal sS3Err7P                           : signed(BITNESS downto 0); 
   373:     signal sS3Err7M                           : signed(BITNESS downto 0); 
   374:     signal sS3Err9C                           : signed(BITNESS downto 0); 
   375:     signal sS3Err9P                           : signed(BITNESS downto 0); 
   376:     signal sS3Err9M                           : signed(BITNESS downto 0); 
   377:     signal sS3Err9Sel                         : signed(BITNESS downto 0); 
   378:    
   379:     -- Q3==Q4 forwarding: one flag per mode. Q ranges are disjoint (regular 
   380:     -- 0..364, RI 365,366), so a Q match + the Stage-4 mode uniquely identifies 
   381:     -- which writeback path is live; Stage-2 mode is implied. 
   382:     signal sFwdRegHit                         : std_logic; 
   383:     signal sFwdRiHit                          : std_logic; 
   384:    
   385:     -- Speculation control (Cq only) 
   386:     signal sDeltaCq                           : signed(C_WIDTH - 1 downto 0); 
   387:     signal sSpecUseM                          : std_logic; 
   388:     signal sSpecUseP                          : std_logic; 
   389:    
   390:     -- Stage 3 — RI path 
   391:     signal sS3RiSign                          : std_logic; 
   392:     signal sS3RiErr19                         : signed(BITNESS downto 0); 
   393:     signal sS3RiTemp                          : unsigned(A_WIDTH - 1 downto 0); 
   394:    
   395:     -- Stage 4 
   396:     signal sS4K                               : unsigned(K_WIDTH - 1 downto 0); 
   397:     signal sS4AqSel                           : unsigned(A_WIDTH - 1 downto 0);                         -- iAq mux for shared A.10 
   398:     signal sS4AqNew                           : unsigned(A_WIDTH - 1 downto 0); 
   399:     signal sS4BqMid                           : signed(B_WIDTH - 1 downto 0); 
   400:     signal sS4NqNew                           : unsigned(N_WIDTH - 1 downto 0); 
   401:     signal sS4BqNew                           : signed(B_WIDTH - 1 downto 0); 
   402:     signal sS4CqNew                           : signed(C_WIDTH - 1 downto 0); 
   403:     signal sS4RiAqNew                         : unsigned(A_WIDTH - 1 downto 0); 
   404:     signal sS4RiNqNew                         : unsigned(N_WIDTH - 1 downto 0); 
   405:     signal sS4RiNnNew                         : unsigned(NN_WIDTH - 1 downto 0); 
   406:     -- BRAM-side encode helpers for the N 0↔RESET trick. 
   407:     signal sNqEncReg                          : unsigned(N_STORED - 1 downto 0); 
   408:     signal sNqEncRi                           : unsigned(N_STORED - 1 downto 0); 
   409:    
   410:     -- Stage 5 
   411:     signal sS5MErrval                         : unsigned(MAPPED_ERROR_VAL_WIDTH - 1 downto 0); 
   412:     signal sS5RiMap                           : std_logic; 
   413:     signal sS5RiEmErrval                      : unsigned(MAPPED_ERROR_VAL_WIDTH - 1 downto 0); 
   414:     signal sS5GolMErr                         : unsigned(MAPPED_ERROR_VAL_WIDTH - 1 downto 0); 
   415:    
   416:     signal sS5Unary                           : unsigned(UNARY_WIDTH - 1 downto 0); 
   417:     signal sS5SufLen                          : unsigned(SUFFIXLEN_WIDTH - 1 downto 0); 
   418:     signal sS5SufVal                          : unsigned(SUFFIX_WIDTH - 1 downto 0); 
   419:    
   420:     -- Stage 5 inter-stage registers: Reg5 in front of A.11_1, Reg6 after. 
   421:     signal sReg5,    sReg6                    : t_pipeline_token; 
   422:     signal sReg5V,   sReg6V                   : std_logic; 
   423:     signal sReg5Eoi, sReg6Eoi                 : std_logic; 
   424:     signal sReg5GolMErr                       : unsigned(MAPPED_ERROR_VAL_WIDTH - 1 downto 0); 
   425:     signal sReg6Unary                         : unsigned(UNARY_WIDTH - 1 downto 0); 
   426:     signal sReg6SufLen                        : unsigned(SUFFIXLEN_WIDTH - 1 downto 0); 
   427:     signal sReg6SufVal                        : unsigned(SUFFIX_WIDTH - 1 downto 0); 
   428:    
   429:     -- Output 
   430:     signal sBpRawV,  sBpGolV                  : std_logic; 
   431:     signal sBpWord                            : std_logic_vector(LIMIT - 1 downto 0); 
   432:     signal sBpWordV                           : std_logic; 
   433:     signal sBpValidLen                        : unsigned(log2ceil(LIMIT + 1) - 1 downto 0); 
   434:     signal sBsWord                            : std_logic_vector(BYTE_STUFFER_OUT_WIDTH - 1 downto 0); 
   435:     signal sBsWordV                           : std_logic; 
   436:     signal sBsValidB                          : unsigned(log2ceil(BYTE_STUFFER_OUT_WIDTH / 8 + 1) - 1 downto 0); 
   437:     signal sFramerVBytes                      : unsigned(log2ceil(OUT_WIDTH / 8 + 1) - 1 downto 0); 
   438:    
   439:     -- Flush / framer control 
   440:     signal sBsFlush                           : std_logic; 
   441:     signal sBsAlmostFull                      : std_logic; 
   442:     signal sBsFlushDone                       : std_logic; 
   443:     signal sFramerEoi                         : std_logic; 
   444:     signal sFirstPixel                        : std_logic; 
   445:     signal sFramerStart                       : std_logic; 
   446:     signal sReadyOut                          : std_logic; 
   447:    
   448:   begin 
   449:    
   450:     ------------------------------------------------------------------------------------------------------------- 
   451:     -- ASSERTIONS 
   452:     ------------------------------------------------------------------------------------------------------------- 
   453:    
   454:     assert B_WIDTH >= BITNESS + 1 -- for a single sum 
   455:       report "A12: B_WIDTH must be >= BITNESS + 1 to avoid truncation" 
   456:       severity failure; 
   457:    
   458:     assert A_WIDTH >= BITNESS + 1 -- for a single sum 
   459:       report "A12: A_WIDTH must be >= BITNESS + 1 to avoid truncation" 
   460:       severity failure; 
   461:    
   462:     assert B_WIDTH >= N_WIDTH 
   463:       report "A11 & A13: B_WIDTH must be >= N_WIDTH to avoid truncation" 
   464:       severity failure; 
   465:    
   466:     ------------------------------------------------------------------------------------------------------------- 
   467:     -- STALL, CLOCK-ENABLE, AND READY LOGIC 
   468:     ------------------------------------------------------------------------------------------------------------- 
   469:     p_stall_control : process (iClk) is 
   470:     begin 
   471:    
   472:       if rising_edge(iClk) then 
   473:         if (iRst = '1') then 
   474:           sBsAlmostFullReg <= '0'; 
   475:           sStallDelay      <= '0'; 
   476:           sStallLogic      <= '0'; 
   477:         else 
   478:           sBsAlmostFullReg <= sBsAlmostFull; 
   479:           sStallDelay      <= sStall; 
   480:           if (sStallDelay = '1' and sStall = '1') then 
   481:             sStallLogic <= '1'; 
   482:           else 
   483:             sStallLogic <= '0'; 
   484:           end if; 
   485:         end if; 
   486:       end if; 
   487:    
   488:     end process p_stall_control; 
   489:    
   490:     -- Pipeline stall is sourced only from byte_stuffer's FIFO (the main design 
   491:     -- buffer). Framer back-pressure is absorbed by the byte_stuffer FIFO via a 
   492:     -- local ready/valid handshake (sFramerReady -> byte_stuffer.iReady). 
   493:     sStall <= sBsAlmostFullReg; 
   494:     -- Gating oReady on sStall alone leaves a one-cycle window where oReady='1' 
   495:     -- but the latch is still frozen, which silently drops the pixel handshaken 
   496:     -- in that cycle. OR-ing both keeps oReady low until acceptance is truly 
   497:     -- re-enabled. 
   498:     sStallUpstream <= sStall or sStallLogic; 
   499:    
   500:     -- Per-stage clock-enable: update register only when not stalled AND there 
   501:     -- is a real token to load OR a real token to retire (transition to bubble). 
   502:     -- Once the register is sitting on a bubble with no upstream valid, CE=0 
   503:     -- holds it frozen so its combinational fan-out stops toggling. 
   504:    
   505:     sCE1 <= '1' when sStallLogic = '0' and (sReg1V = '1' or sValid = '1') else 
   506:             '0'; 
   507:     sCE2 <= '1' when sStallLogic = '0' and (sReg2V = '1' or sReg1V = '1') else 
   508:             '0'; 
   509:     sCE3 <= '1' when sStallLogic = '0' and (sReg3V = '1' or sReg2V = '1') else 
   510:             '0'; 
   511:     sCE4 <= '1' when sStallLogic = '0' and (sReg4V = '1' or sReg3V = '1') else 
   512:             '0'; 
   513:     sCE5 <= '1' when sStallLogic = '0' and (sReg5V = '1' or sReg4V = '1') else 
   514:             '0'; 
   515:     sCE6 <= '1' when sStallLogic = '0' and (sReg6V = '1' or sReg5V = '1') else 
   516:             '0'; 
   517:    
   518:     sReadyOut <= not iRst and not sStallUpstream; -- Stalls upstream 
   519:     oReady    <= sReadyOut; 
   520:    
   521:     -- Input-port AXI4-Stream slave contract (iValid/iPixel/oReady). 
   522:     -- psl default clock is rising_edge(iClk); 
   523:     -- psl assert always (iRst = '1' -> oReady = '0') report "openjls_top: reset must hold oReady low"; 
   524:     -- psl assert always ((iRst = '0' and sStallLogic = '1') -> oReady = '0') report "openjls_top: oReady must stay low while the input latch is frozen (no dropped beat)"; 
   525:     -- psl assert always ((iRst = '0' and iValid = '1' and oReady = '1') -> next (sValid = '1')) report "openjls_top: an accepted pixel (iValid and oReady) must be committed next cycle"; 
   526:    
   527:     ------------------------------------------------------------------------------------------------------------- 
   528:     -- Input Stage — Input register 
   529:     ------------------------------------------------------------------------------------------------------------- 
   530:     p_input_reg : process (iClk) is 
   531:    
   532:       variable vImageWidthUnsi  : unsigned (iImageWidth'range); 
   533:       variable vImageHeightUnsi : unsigned (iImageHeight'range); 
   534:    
   535:     begin 
   536:    
   537:       if rising_edge(iClk) then 
   538:         if (iRst = '1') then 
   539:           sValid <= '0'; 
   540:           sPixel <= (others => '0'); 
   541:    
   542:           vImageWidthUnsi  := unsigned(iImageWidth); 
   543:           vImageHeightUnsi := unsigned(iImageHeight); 
   544:    
   545:           -- Image resolution set to max value if invalid input 
   546:           -- if the user wants MAX_IMAGE_WIDTH/HEIGHT he can leave the inputs unwired (set to 0) 
   547:           if (vImageWidthUnsi < CO_MIN_IMAGE_WIDTH) then 
   548:             assert false 
   549:               report "iImageWidth smaller than the minimum allowed: " & integer'image(CO_MIN_IMAGE_WIDTH) & ", using max value instead: " & integer'image(MAX_IMAGE_WIDTH) 
   550:               severity warning; 
   551:    
   552:             sImageWidth <= to_unsigned(MAX_IMAGE_WIDTH, sImageWidth'length); 
   553:           elsif (vImageWidthUnsi > MAX_IMAGE_WIDTH) then 
   554:             assert false 
   555:               report "iImageWidth larger than the maximum allowed: " & integer'image(MAX_IMAGE_WIDTH) & ", using max value instead: " & integer'image(MAX_IMAGE_WIDTH) 
   556:               severity warning; 
   557:    
   558:             sImageWidth <= to_unsigned(MAX_IMAGE_WIDTH, sImageWidth'length); 
   559:           else 
   560:             sImageWidth <= resize(vImageWidthUnsi, sImageWidth'length); 
   561:           end if; 
   562:    
   563:           if (vImageHeightUnsi < CO_MIN_IMAGE_HEIGHT) then 
   564:             assert false 
   565:               report "iImageHeight smaller than the minimum allowed: " & integer'image(CO_MIN_IMAGE_HEIGHT) & ", using max value instead: " & integer'image(MAX_IMAGE_HEIGHT) 
   566:               severity warning; 
   567:    
   568:             sImageHeight <= to_unsigned(MAX_IMAGE_HEIGHT, sImageHeight'length); 
   569:           elsif (vImageHeightUnsi > MAX_IMAGE_HEIGHT) then 
   570:             assert false 
   571:               report "iImageHeight larger than the maximum allowed: " & integer'image(MAX_IMAGE_HEIGHT) & ", using max value instead: " & integer'image(MAX_IMAGE_HEIGHT) 
   572:               severity warning; 
   573:    
   574:             sImageHeight <= to_unsigned(MAX_IMAGE_HEIGHT, sImageHeight'length); 
   575:           else 
   576:             sImageHeight <= resize(vImageHeightUnsi, sImageHeight'length); 
   577:           end if; 
   578:         else 
   579:           if (iValid = '1' and sReadyOut = '1' and sStallLogic = '0') then -- handshake 
   580:             sPixel <= unsigned(iPixel); 
   581:             sValid <= '1'; 
   582:           else 
   583:             sPixel <= (others => '0'); 
   584:             sValid <= '0'; 
   585:           end if; 
   586:         end if; 
   587:       end if; 
   588:    
   589:     end process p_input_reg; 
   590:    
   591:     ------------------------------------------------------------------------------------------------------------- 
   592:     -- Stage 1 — Line buffer + A.1 gradients + A.3 mode selection 
   593:     ------------------------------------------------------------------------------------------------------------- 
   594:     u_line_buffer : entity work.line_buffer(behavioral) 
   595:       generic map ( 
   596:         MAX_IMAGE_WIDTH  => MAX_IMAGE_WIDTH, 
   597:         MAX_IMAGE_HEIGHT => MAX_IMAGE_HEIGHT, 
   598:         BITNESS          => BITNESS 
   599:       ) 
   600:       port map ( 
   601:         iClk             => iClk, 
   602:         iRst             => iRst, 
   603:         iImageWidth      => sImageWidth, 
   604:         iImageHeight     => sImageHeight, 
   605:         iValid           => sValid, 
   606:         iPixel           => sPixel, 
   607:         oA               => sLbRa, 
   608:         oB               => sLbRb, 
   609:         oC               => sLbRc, 
   610:         oD               => sLbRd, 
   611:         oValid           => sLbValid, 
   612:         oEol             => sLbEol, 
   613:         oEoi             => sLbEoi 
   614:       ); 
   615:    
   616:     u_a1 : entity work.a1_gradient_comp(behavioral) 
   617:       generic map ( 
   618:         BITNESS => BITNESS 
   619:       ) 
   620:       port map ( 
   621:         iA      => sLbRa, 
   622:         iB      => sLbRb, 
   623:         iC      => sLbRc, 
   624:         iD      => sLbRd, 
   625:         oD1     => sS1D1, 
   626:         oD2     => sS1D2, 
   627:         oD3     => sS1D3 
   628:       ); 
   629:    
   630:     u_a3 : entity work.a3_mode_selection(behavioral) 
   631:       generic map ( 
   632:         BITNESS  => BITNESS 
   633:       ) 
   634:       port map ( 
   635:         iD1      => sS1D1, 
   636:         iD2      => sS1D2, 
   637:         iD3      => sS1D3, 
   638:         oModeRun => sS1ModeRun 
   639:       ); 
   640:    
   641:     ------------------------------------------------------------------------------------------------------------- 
   642:     -- Register 1 (Stage 1 → Stage 2) 
   643:     ------------------------------------------------------------------------------------------------------------- 
   644:     p_reg1 : process (iClk) is 
   645:    
   646:       variable v : t_pipeline_token; 
   647:    
   648:     begin 
   649:    
   650:       if rising_edge(iClk) then 
   651:         if (iRst = '1') then 
   652:           sReg1    <= CO_TOKEN_NONE; 
   653:           sReg1V   <= '0'; 
   654:           sReg1Eol <= '0'; 
   655:           sReg1Eoi <= '0'; 
   656:           sReg1D1  <= (others => '0'); 
   657:           sReg1D2  <= (others => '0'); 
   658:           sReg1D3  <= (others => '0'); 
   659:           sGenPar  <= '0'; 
   660:           sReg1Par <= '0'; 
   661:         elsif (sCE1 = '1') then 
   662:           if (sLbValid = '1' and (sS1ModeRun = '1' or sS1InRunNext = '1')) then 
   663:             v.mode := token_run; 
   664:           elsif (sLbValid = '1') then 
   665:             v.mode := token_regular; 
   666:           else 
   667:             v := CO_TOKEN_NONE; 
   668:           end if; 
   669:    
   670:           if (sLbValid = '1') then 
   671:             v.Ix := sPixel; 
   672:             v.Ra := sLbRa; 
   673:             v.Rb := sLbRb; 
   674:             v.Rc := sLbRc; 
   675:           end if; 
   676:    
   677:           sReg1    <= v; 
   678:           sReg1V   <= sValid; 
   679:           sReg1Eol <= sLbValid and sLbEol; 
   680:           sReg1Eoi <= sLbValid and sLbEoi; 
   681:           -- Tag this token with the current parity; flip after an EOI so the next 
   682:           -- image's first token (and onward) carries the opposite parity. 
   683:           sReg1Par <= sGenPar; 
   684:           if (sLbValid = '1' and sLbEoi = '1') then 
   685:             sGenPar <= not sGenPar; 
   686:           end if; 
   687:           sReg1D1 <= sS1D1; 
   688:           sReg1D2 <= sS1D2; 
   689:           sReg1D3 <= sS1D3; 
   690:         end if; 
   691:       end if; 
   692:    
   693:     end process p_reg1; 
   694:    
   695:     ------------------------------------------------------------------------------------------------------------- 
   696:     -- Stage 2 — Regular: A.4 → A.4.1 → A.4.2 
   697:     ------------------------------------------------------------------------------------------------------------- 
   698:     u_a4 : entity work.a4_quantization_gradients(behavioral) 
   699:       generic map ( 
   700:         BITNESS => BITNESS, 
   701:         MAX_VAL => MAX_VAL 
   702:       ) 
   703:       port map ( 
   704:         iD1     => sReg1D1, 
   705:         iD2     => sReg1D2, 
   706:         iD3     => sReg1D3, 
   707:         oQ1     => sS2Q1, 
   708:         oQ2     => sS2Q2, 
   709:         oQ3     => sS2Q3 
   710:       ); 
   711:    
   712:     u_a4_1 : entity work.a4_1_quant_gradient_merging(behavioral) 
   713:       port map ( 
   714:         iQ1   => sS2Q1, 
   715:         iQ2   => sS2Q2, 
   716:         iQ3   => sS2Q3, 
   717:         oQ1   => sS2MQ1, 
   718:         oQ2   => sS2MQ2, 
   719:         oQ3   => sS2MQ3, 
   720:         oSign => sS2MSign 
   721:       ); 
   722:    
   723:     u_a4_2 : entity work.a4_2_q_mapping(behavioral) 
   724:       port map ( 
   725:         iQ1 => sS2MQ1, 
   726:         iQ2 => sS2MQ2, 
   727:         iQ3 => sS2MQ3, 
   728:         oQ  => sS2QReg 
   729:       ); 
   730:    
   731:     ------------------------------------------------------------------------------------------------------------- 
   732:     -- Stage 2 — Run: A.14, A.15/A.16 (FSM), A.17 
   733:     ------------------------------------------------------------------------------------------------------------- 
   734:     u_a14 : entity work.a14_run_length_determination(behavioral) 
   735:       generic map ( 
   736:         BITNESS       => BITNESS, 
   737:         RUN_CNT_WIDTH => RUN_CNT_WIDTH 
   738:       ) 
   739:       port map ( 
   740:         iRa           => sReg1.Ra(BITNESS - 1 downto 0), 
   741:         iIx           => sReg1.Ix(BITNESS - 1 downto 0), 
   742:         iRunCnt       => sRunCntReg, 
   743:         iEol          => sReg1Eol, 
   744:         oRunCnt       => sS2RunCnt, 
   745:         oRunHit       => sS2RunHit, 
   746:         oRunContinue  => sS2RunContinue 
   747:       ); 
   748:    
   749:     sReg1ModeRun <= '1' when sReg1.mode = token_run else 
   750:                     '0'; 
   751:    
   752:     u_a15_16 : entity work.a15_a16_encode_run(behavioral) 
   753:       generic map ( 
   754:         BITNESS       => BITNESS, 
   755:         RUN_CNT_WIDTH => RUN_CNT_WIDTH 
   756:       ) 
   757:       port map ( 
   758:         iClk          => iClk, 
   759:         iRst          => iRst, 
   760:         iCE           => not sStallLogic, 
   761:         iEoi          => sReg1Eoi, 
   762:         iRunCnt       => sS2RunCnt, 
   763:         iRunHit       => sS2RunHit, 
   764:         iRunContinue  => sS2RunContinue, 
   765:         iModeIsRun    => sReg1ModeRun, 
   766:         iIx           => sReg1.Ix(BITNESS - 1 downto 0), 
   767:         iRa           => sReg1.Ra(BITNESS - 1 downto 0), 
   768:         iRb           => sReg1.Rb(BITNESS - 1 downto 0), 
   769:         oRawValid     => sS2RawValid, 
   770:         oRawSuffixLen => sS2RawLen, 
   771:         oRawSuffixVal => sS2RawVal, 
   772:         oRiValid      => sS2RiValid, 
   773:         oRiIx         => sS2RiIx, 
   774:         oRiRa         => sS2RiRa, 
   775:         oRiRb         => sS2RiRb, 
   776:         oRiRunIndex   => sS2RiRunIndex, 
   777:         oInRunNext    => sS1InRunNext 
   778:       ); 
   779:    
   780:     u_a17 : entity work.a17_run_interruption_index(behavioral) 
   781:       generic map ( 
   782:         BITNESS => BITNESS 
   783:       ) 
   784:       port map ( 
   785:         iRa     => sReg1.Ra(BITNESS - 1 downto 0), 
   786:         iRb     => sReg1.Rb(BITNESS - 1 downto 0), 
   787:         oRItype => sS2RItype 
   788:       ); 
   789:    
   790:     u_a18 : entity work.a18_run_interruption_prediction_error(behavioral) 
   791:       generic map ( 
   792:         BITNESS => BITNESS 
   793:       ) 
   794:       port map ( 
   795:         iRItype => sS2RItype, 
   796:         iRa     => sS2RiRa, 
   797:         iRb     => sS2RiRb, 
   798:         iIx     => sS2RiIx, 
   799:         oErrval => sS2RiErr18 
   800:       ); 
   801:    
   802:     p_run_cnt : process (iClk) is 
   803:     begin 
   804:    
   805:       if rising_edge(iClk) then 
   806:         if (iRst = '1') then 
   807:           sRunCntReg <= (others => '0'); 
   808:         elsif (sStallLogic = '0' and sReg1.mode = token_run) then 
   809:           if (sS2RunContinue = '1') then 
   810:             sRunCntReg <= sS2RunCnt; 
   811:           else 
   812:             sRunCntReg <= (others => '0'); 
   813:           end if; 
   814:         end if; 
   815:       end if; 
   816:    
   817:     end process p_run_cnt; 
   818:    
   819:     -- Stage 2 mode selection. Precedence: RI break (Golomb+raw) > raw-only. 
   820:     sS2TokenMode <= token_regular when sReg1.mode = token_regular else 
   821:                     token_run_interruption when sS2RiValid = '1' else 
   822:                     token_raw when sS2RawValid = '1' else 
   823:                     token_none; 
   824:    
   825:     -- A.20.1 inline: regular Q from A.4.2; run Q = 366 if RItype else 365 
   826:     sS2Q <= sS2QReg when sReg1.mode = token_regular else 
   827:             to_unsigned(366, 9) when sS2RItype = '1' else 
   828:             to_unsigned(365, 9); 
   829:    
   830:     -- Sticky context-RAM owner: parity of the last valid token that issued a read, 
   831:     -- held across read bubbles. Effective owner = live Reg1 parity, else held. 
   832:     p_ctx_owner : process (iClk) is 
   833:     begin 
   834:    
   835:       if rising_edge(iClk) then 
   836:         if (iRst = '1') then 
   837:           sCtxOwnerPar <= '0'; 
   838:         elsif (sReg1V = '1') then 
   839:           sCtxOwnerPar <= sReg1Par; 
   840:         end if; 
   841:       end if; 
   842:    
   843:     end process p_ctx_owner; 
   844:    
   845:     sCtxRdPar <= sReg1Par when sReg1V = '1' else 
   846:                  sCtxOwnerPar; 
   847:    
   848:     -- Refuse a writeback whose parity no longer owns the context RAM: it is a 
   849:     -- straggler from a finished image and would corrupt the next image's contexts. 
   850:     sCtxWrEn <= sReg3V and 
   851:                 bool2bit(sReg3Par = sCtxRdPar) and 
   852:                 (bool2bit(sReg3.mode = token_regular) or 
   853:                  bool2bit(sReg3.mode = token_run_interruption)); 
   854:    
   855:     -- Pack writeback word by mode (Murat BRAM encoding): 
   856:     --   A : A_WIDTH → A_STORED (A.12 output fits; the iNq=RESET-1→RESET halving caps it). 
   857:     --   B : magnitude only (Bq ≤ 0 after A.13 clamp).   N : 0 ⇔ RESET. 
   858:     sCtxWrData <= std_logic_vector(resize(sS4AqNew, A_STORED)) & 
   859:                   std_logic_vector(resize(unsigned(-sS4BqNew), B_STORED)) & 
   860:                   std_logic_vector(sS4CqNew) & 
   861:                   std_logic_vector(sNqEncReg) 
   862:                   when sReg3.mode = token_regular else 
   863:                   std_logic_vector(resize(sS4RiAqNew, A_STORED)) & 
   864:                   std_logic_vector(sS4RiNnNew) & 
   865:                   std_logic_vector(to_signed(0, C_STORED)) & 
   866:                   std_logic_vector(sNqEncRi); 
   867:    
   868:     sNqEncReg <= (others => '0') when sS4NqNew = to_unsigned(RESET, N_WIDTH) else 
   869:                  resize(sS4NqNew, N_STORED); 
   870:    
   871:     sNqEncRi <= (others => '0') when sS4RiNqNew = to_unsigned(RESET, N_WIDTH) else 
   872:                 resize(sS4RiNqNew, N_STORED); 
   873:    
   874:     u_ctx_ram : entity work.context_ram(behavioral) 
   875:       generic map ( 
   876:         RANGE_P     => RANGE_P, 
   877:         RAM_DEPTH   => RAM_DEPTH, 
   878:         A_WIDTH     => A_STORED, 
   879:         B_WIDTH     => B_STORED, 
   880:         C_WIDTH     => C_STORED, 
   881:         N_WIDTH     => N_STORED, 
   882:         TOTAL_WIDTH => TOTAL_WIDTH 
   883:       ) 
   884:       port map ( 
   885:         iClk        => iClk, 
   886:         iRst        => iRst, 
   887:         iWrAddr     => std_logic_vector(sReg3.Q), 
   888:         iWrEn       => sCtxWrEn and sCE3, 
   889:         iWrData     => sCtxWrData, 
   890:         iRdAddr     => std_logic_vector(sS2Q), 
   891:         iRdEn       => sReg1V and sCE1 and (bool2bit(sS2TokenMode = TOKEN_REGULAR) or 
   892:         bool2bit(sS2TokenMode = TOKEN_RUN_INTERRUPTION)), 
   893:         iEndOfImage => sReg1Eoi, 
   894:         oRdData     => sCtxRdData 
   895:       ); 
   896:    
   897:     -- Unpack read port (RdLatency=1 → valid at Stage 3). Q3==Q4 forwarding: when 
   898:     -- Stage 4 writes back the Q Stage 3 is reading, use the live update outputs 
   899:     -- (BRAM read is stale). Decode mirrors encode: A zero-extend, B = -stored, N 0 ⇒ RESET. 
   900:     sS3Aq <= sS4AqNew when sFwdRegHit = '1' else 
   901:              sS4RiAqNew when sFwdRiHit = '1' else 
   902:              resize(unsigned(sCtxRdData(CTX_A_HI downto CTX_A_LO)), A_WIDTH); 
   903:    
   904:     -- Bq is regular-only (the B slot carries Nn for RI, handled below). 
   905:     sS3Bq <= sS4BqNew when sFwdRegHit = '1' else 
   906:              - signed(resize(unsigned(sCtxRdData(CTX_B_HI downto CTX_B_LO)), B_WIDTH)); 
   907:    
   908:     -- Cq forwarding is handled by the speculative 3-chain via sS3CqBase. 
   909:     sS3Cq <= sS4CqNew when sFwdRegHit = '1' else 
   910:              signed(sCtxRdData(CTX_C_HI downto CTX_C_LO)); 
   911:    
   912:     sS3Nq <= sS4NqNew when sFwdRegHit = '1' else 
   913:              sS4RiNqNew when sFwdRiHit = '1' else 
   914:              to_unsigned(RESET, N_WIDTH) when unsigned(sCtxRdData(CTX_N_HI downto CTX_N_LO)) = 0 else 
   915:              resize(unsigned(sCtxRdData(CTX_N_HI downto CTX_N_LO)), N_WIDTH); 
   916:    
   917:     -- Nn is only meaningful for RI; mask to zero for regular so downstream 
   918:     -- doesn't see Bq LSBs misinterpreted as Nn. 
   919:     sS3Nn <= sS4RiNnNew when sFwdRiHit = '1' else 
   920:              (others => '0') when sReg2.mode = token_regular else 
   921:              unsigned(sCtxRdData(CTX_NN_HI downto CTX_NN_LO)); 
   922:    
   923:     u_a5 : entity work.a5_edge_detecting_predictor(behavioral) 
   924:       generic map ( 
   925:         BITNESS => BITNESS 
   926:       ) 
   927:       port map ( 
   928:         iA      => sReg1.Ra(BITNESS - 1 downto 0), 
   929:         iB      => sReg1.Rb(BITNESS - 1 downto 0), 
   930:         iC      => sReg1.Rc(BITNESS - 1 downto 0), 
   931:         oPx     => sS2Px 
   932:       ); 
   933:    
   934:     ------------------------------------------------------------------------------------------------------------- 
   935:     -- Register 2 (Stage 2 → Stage 3) 
   936:     ------------------------------------------------------------------------------------------------------------- 
   937:     p_reg2 : process (iClk) is 
   938:    
   939:       variable v : t_pipeline_token; 
   940:    
   941:     begin 
   942:    
   943:       if rising_edge(iClk) then 
   944:         if (iRst = '1') then 
   945:           sReg2    <= CO_TOKEN_NONE; 
   946:           sReg2V   <= '0'; 
   947:           sReg2Eoi <= '0'; 
   948:           sReg2Px  <= (others => '0'); 
   949:           sReg2Par <= '0'; 
   950:         elsif (sCE2 = '1') then 
   951:           -- Build Reg2 per mode; unused fields stay at CO_TOKEN_NONE defaults so 
   952:           -- downstream never sees stale values. 
   953:           v      := CO_TOKEN_NONE; 
   954:           v.mode := sS2TokenMode; 
   955:           v.Q    := sS2Q; 
   956:    
   957:           case sS2TokenMode is 
   958:    
   959:             when token_regular => 
   960:    
   961:               v.Ix   := sReg1.Ix; 
   962:               v.Ra   := sReg1.Ra; 
   963:               v.Rb   := sReg1.Rb; 
   964:               v.Rc   := sReg1.Rc; 
   965:               v.Sign := sS2MSign; 
   966:    
   967:             when token_run_interruption => 
   968:    
   969:               v.Ix         := sS2RiIx; 
   970:               v.Ra         := sS2RiRa; 
   971:               v.Rb         := sS2RiRb; 
   972:               v.RiType     := sS2RItype; 
   973:               v.Errval     := resize(sS2RiErr18, v.Errval'length); 
   974:               v.RawLen     := resize(sS2RawLen, v.RawLen'length); 
   975:               v.RawVal     := resize(sS2RawVal, v.RawVal'length); 
   976:               v.RiRunIndex := sS2RiRunIndex; 
   977:    
   978:             when token_raw => 
   979:    
   980:               v.RawLen := resize(sS2RawLen, v.RawLen'length); 
   981:               v.RawVal := resize(sS2RawVal, v.RawVal'length); 
   982:    
   983:             when others => 
   984:    
   985:               v := CO_TOKEN_NONE; 
   986:    
   987:           end case; 
   988:    
   989:           if (sReg1V = '0' or sS2TokenMode = token_none) then 
   990:             v := CO_TOKEN_NONE; 
   991:           end if; 
   992:    
   993:           sReg2    <= v; 
   994:           sReg2V   <= sReg1V and bool2bit(sS2TokenMode /= token_none); 
   995:           sReg2Eoi <= sReg1Eoi; 
   996:           sReg2Px  <= sS2Px; 
   997:           sReg2Par <= sReg1Par; 
   998:         end if; 
   999:       end if; 
  1000:    
  1001:     end process p_reg2; 
  1002:    
  1003:     ------------------------------------------------------------------------------------------------------------- 
  1004:     -- Stage 3 — Regular: A.5 + speculative 3-chain A.6..A.9 
  1005:     ------------------------------------------------------------------------------------------------------------- 
  1006:    
  1007:     sS3Px <= sReg2Px; 
  1008:    
  1009:     -- Forwarding hits: Stage 2 read Q matches Stage 4 writeback Q. 
  1010:     -- Stage-4 mode selects which update output to forward; Stage-2 mode is 
  1011:     -- implied by the Q match (regular Q < 365, RI Q ∈ {365,366}). 
  1012:     -- Same-parity guard: never forward an update across an image boundary (the 
  1013:     -- two tokens can alias on the same Q — e.g. the run contexts — when one is a 
  1014:     -- straggler from the previous image). 
  1015:     sFwdRegHit <= '1' when sReg2V = '1' and sReg3V = '1' 
  1016:                            and sReg2Par = sReg3Par 
  1017:                            and sReg2.Q = sReg3.Q 
  1018:                            and sReg3.mode = token_regular else 
  1019:                   '0'; 
  1020:    
  1021:     sFwdRiHit <= '1' when sReg2V = '1' and sReg3V = '1' 
  1022:                           and sReg2Par = sReg3Par 
  1023:                           and sReg2.Q = sReg3.Q 
  1024:                           and sReg3.mode = token_run_interruption else 
  1025:                  '0'; 
  1026:    
  1027:     -- Speculative-chain Cq base: on a hit use the pre-update sReg3.Cq (DeltaCq picks 
  1028:     -- the ±1/0 candidate matching sS4CqNew); on a miss the BRAM read is already correct. 
  1029:     sS3CqBase <= sReg3.Cq when sFwdRegHit = '1' else 
  1030:                  sS3Cq; 
  1031:    
  1032:     -- Clamped ±1 variants 
  1033:     sS3CqP1 <= to_signed(MAX_C, C_WIDTH) when sS3CqBase = to_signed(MAX_C, C_WIDTH) else 
  1034:                sS3CqBase + 1; 
  1035:     sS3CqM1 <= to_signed(MIN_C, C_WIDTH) when sS3CqBase = to_signed(MIN_C, C_WIDTH) else 
  1036:                sS3CqBase - 1; 
  1037:    
  1038:     -- Central chain (DeltaCq = 0) 
  1039:     u_a6_c : entity work.a6_prediction_correction(behavioral) 
  1040:       generic map ( 
  1041:         BITNESS => BITNESS, MAX_VAL => MAX_VAL 
  1042:       ) 
  1043:       port map ( 
  1044:         iPx     => sS3Px, 
  1045:         iSign   => sReg2.Sign, 
  1046:         iCq     => sS3CqBase, 
  1047:         oPx     => sS3PxC 
  1048:       ); 
  1049:    
  1050:     u_a7_c : entity work.a7_prediction_error(behavioral) 
  1051:       generic map ( 
  1052:         BITNESS   => BITNESS 
  1053:       ) 
  1054:       port map ( 
  1055:         iIx       => sReg2.Ix(BITNESS - 1 downto 0), 
  1056:         iPx       => sS3PxC, 
  1057:         iSign     => sReg2.Sign, 
  1058:         oErrorVal => sS3Err7C 
  1059:       ); 
  1060:    
  1061:     u_a9_c : entity work.a9_modulo_reduction(behavioral) 
  1062:       generic map ( 
  1063:         BITNESS   => BITNESS, RANGE_P => RANGE_P 
  1064:       ) 
  1065:       port map ( 
  1066:         iErrorVal => sS3Err7C, 
  1067:         oErrorVal => sS3Err9C 
  1068:       ); 
  1069:    
  1070:     -- +1 chain (DeltaCq = +1) 
  1071:     u_a6_p : entity work.a6_prediction_correction(behavioral) 
  1072:       generic map ( 
  1073:         BITNESS => BITNESS, MAX_VAL => MAX_VAL 
  1074:       ) 
  1075:       port map ( 
  1076:         iPx     => sS3Px, 
  1077:         iSign   => sReg2.Sign, 
  1078:         iCq     => sS3CqP1, 
  1079:         oPx     => sS3PxP 
  1080:       ); 
  1081:    
  1082:     u_a7_p : entity work.a7_prediction_error(behavioral) 
  1083:       generic map ( 
  1084:         BITNESS   => BITNESS 
  1085:       ) 
  1086:       port map ( 
  1087:         iIx       => sReg2.Ix(BITNESS - 1 downto 0), 
  1088:         iPx       => sS3PxP, 
  1089:         iSign     => sReg2.Sign, 
  1090:         oErrorVal => sS3Err7P 
  1091:       ); 
  1092:    
  1093:     u_a9_p : entity work.a9_modulo_reduction(behavioral) 
  1094:       generic map ( 
  1095:         BITNESS   => BITNESS, RANGE_P => RANGE_P 
  1096:       ) 
  1097:       port map ( 
  1098:         iErrorVal => sS3Err7P, 
  1099:         oErrorVal => sS3Err9P 
  1100:       ); 
  1101:    
  1102:     -- −1 chain (DeltaCq = −1) 
  1103:     u_a6_m : entity work.a6_prediction_correction(behavioral) 
  1104:       generic map ( 
  1105:         BITNESS => BITNESS, MAX_VAL => MAX_VAL 
  1106:       ) 
  1107:       port map ( 
  1108:         iPx     => sS3Px, 
  1109:         iSign   => sReg2.Sign, 
  1110:         iCq     => sS3CqM1, 
  1111:         oPx     => sS3PxM 
  1112:       ); 
  1113:    
  1114:     u_a7_m : entity work.a7_prediction_error(behavioral) 
  1115:       generic map ( 
  1116:         BITNESS   => BITNESS 
  1117:       ) 
  1118:       port map ( 
  1119:         iIx       => sReg2.Ix(BITNESS - 1 downto 0), 
  1120:         iPx       => sS3PxM, 
  1121:         iSign     => sReg2.Sign, 
  1122:         oErrorVal => sS3Err7M 
  1123:       ); 
  1124:    
  1125:     u_a9_m : entity work.a9_modulo_reduction(behavioral) 
  1126:       generic map ( 
  1127:         BITNESS   => BITNESS, RANGE_P => RANGE_P 
  1128:       ) 
  1129:       port map ( 
  1130:         iErrorVal => sS3Err7M, 
  1131:         oErrorVal => sS3Err9M 
  1132:       ); 
  1133:    
  1134:     -- DeltaCq from live Stage-4 A.13. On miss, sDeltaCq is irrelevant (sFwdRegHit=0). 
  1135:     sDeltaCq <= sS4CqNew - sReg3.Cq; 
  1136:    
  1137:     sSpecUseM <= '1' when sFwdRegHit = '1' and sDeltaCq < 0 else 
  1138:                  '0'; 
  1139:     sSpecUseP <= '1' when sFwdRegHit = '1' and sDeltaCq > 0 else 
  1140:                  '0'; 
  1141:    
  1142:     sS3Err9Sel <= sS3Err9M when sSpecUseM = '1' else 
  1143:                   sS3Err9P when sSpecUseP = '1' else 
  1144:                   sS3Err9C; 
  1145:    
  1146:     ------------------------------------------------------------------------------------------------------------- 
  1147:     -- Stage 3 — RI: A.19, A.20 
  1148:     ------------------------------------------------------------------------------------------------------------- 
  1149:     u_a19 : entity work.a19_run_interruption_error(behavioral) 
  1150:       generic map ( 
  1151:         BITNESS => BITNESS, 
  1152:         RANGE_P => RANGE_P 
  1153:       ) 
  1154:       port map ( 
  1155:         iErrval => sReg2.Errval(BITNESS downto 0), 
  1156:         iRItype => sReg2.RiType, 
  1157:         iRa     => sReg2.Ra(BITNESS - 1 downto 0), 
  1158:         iRb     => sReg2.Rb(BITNESS - 1 downto 0), 
  1159:         oErrval => sS3RiErr19, 
  1160:         oSign   => sS3RiSign 
  1161:       ); 
  1162:    
  1163:     -- A.20: single context read returns (Aq, Nq) for Q ∈ {365, 366}. 
  1164:     u_a20 : entity work.a20_compute_temp(behavioral) 
  1165:       generic map ( 
  1166:         A_WIDTH => A_WIDTH, 
  1167:         N_WIDTH => N_WIDTH 
  1168:       ) 
  1169:       port map ( 
  1170:         iRItype => sReg2.RiType, 
  1171:         iAq     => sS3Aq, 
  1172:         iNq     => sS3Nq, 
  1173:         oTemp   => sS3RiTemp 
  1174:       ); 
  1175:    
  1176:     ------------------------------------------------------------------------------------------------------------- 
  1177:     -- Register 3 (Stage 3 → Stage 4) — carry per-mode Errval / Temp / Sign 
  1178:     ------------------------------------------------------------------------------------------------------------- 
  1179:     p_reg3 : process (iClk) is 
  1180:    
  1181:       variable v : t_pipeline_token; 
  1182:    
  1183:     begin 
  1184:    
  1185:       if rising_edge(iClk) then 
  1186:         if (iRst = '1') then 
  1187:           sReg3    <= CO_TOKEN_NONE; 
  1188:           sReg3V   <= '0'; 
  1189:           sReg3Eoi <= '0'; 
  1190:           sReg3Par <= '0'; 
  1191:         elsif (sCE3 = '1') then 
  1192:           v      := sReg2; 
  1193:           v.Aq   := sS3Aq; 
  1194:           v.Bq   := sS3Bq; 
  1195:           v.Cq   := sS3Cq; 
  1196:           v.Nq   := sS3Nq; 
  1197:           v.Nn   := sS3Nn; 
  1198:           v.Temp := (others => '0'); 
  1199:    
  1200:           case sReg2.mode is 
  1201:    
  1202:             when token_regular => 
  1203:    
  1204:               v.Errval := resize(sS3Err9Sel, v.Errval'length); 
  1205:    
  1206:             when token_run_interruption => 
  1207:    
  1208:               v.Errval := resize(sS3RiErr19, v.Errval'length); 
  1209:               v.Sign   := sS3RiSign; 
  1210:               v.Temp   := sS3RiTemp; 
  1211:    
  1212:             when others => 
  1213:    
  1214:               null; 
  1215:    
  1216:           end case; 
  1217:    
  1218:           if (sReg2V = '0') then 
  1219:             v := CO_TOKEN_NONE; 
  1220:           end if; 
  1221:           sReg3    <= v; 
  1222:           sReg3V   <= sReg2V; 
  1223:           sReg3Eoi <= sReg2Eoi; 
  1224:           sReg3Par <= sReg2Par; 
  1225:         end if; 
  1226:       end if; 
  1227:    
  1228:     end process p_reg3; 
  1229:    
  1230:     ------------------------------------------------------------------------------------------------------------- 
  1231:     -- Stage 4 — Shared A.10; regular A.12 + A.13; RI A.23 
  1232:     --           A.10's iAq is muxed: regular → Aq, RI → Temp. 
  1233:     ------------------------------------------------------------------------------------------------------------- 
  1234:     sS4AqSel <= sReg3.Temp when sReg3.mode = token_run_interruption else 
  1235:                 sReg3.Aq; 
  1236:    
  1237:     u_a10 : entity work.a10_compute_k(behavioral) 
  1238:       generic map ( 
  1239:         A_WIDTH => A_WIDTH, 
  1240:         K_WIDTH => K_WIDTH, 
  1241:         N_WIDTH => N_WIDTH 
  1242:       ) 
  1243:       port map ( 
  1244:         iNq     => sReg3.Nq, 
  1245:         iAq     => sS4AqSel, 
  1246:         oK      => sS4K 
  1247:       ); 
  1248:    
  1249:     u_a12 : entity work.a12_variables_update(rtl) 
  1250:       generic map ( 
  1251:         ERROR_WIDTH => ERROR_WIDTH, 
  1252:         A_WIDTH     => A_WIDTH, 
  1253:         B_WIDTH     => B_WIDTH, 
  1254:         N_WIDTH     => N_WIDTH, 
  1255:         RESET       => RESET 
  1256:       ) 
  1257:       port map ( 
  1258:         iErrorVal   => sReg3.Errval(BITNESS downto 0), 
  1259:         iAq         => sReg3.Aq, 
  1260:         iBq         => sReg3.Bq, 
  1261:         iNq         => sReg3.Nq, 
  1262:         oAq         => sS4AqNew, 
  1263:         oBq         => sS4BqMid, 
  1264:         oNq         => sS4NqNew 
  1265:       ); 
  1266:    
  1267:     u_a13 : entity work.a13_update_bias(rtl) 
  1268:       generic map ( 
  1269:         B_WIDTH => B_WIDTH, 
  1270:         N_WIDTH => N_WIDTH, 
  1271:         C_WIDTH => C_WIDTH, 
  1272:         MIN_C   => MIN_C, 
  1273:         MAX_C   => MAX_C 
  1274:       ) 
  1275:       port map ( 
  1276:         iBq     => sS4BqMid, 
  1277:         iNq     => sS4NqNew, 
  1278:         iCq     => sReg3.Cq, 
  1279:         oBq     => sS4BqNew, 
  1280:         oCq     => sS4CqNew 
  1281:       ); 
  1282:    
  1283:     u_a23 : entity work.a23_run_interruption_update(behavioral) 
  1284:       generic map ( 
  1285:         A_WIDTH     => A_WIDTH, 
  1286:         N_WIDTH     => N_WIDTH, 
  1287:         NN_WIDTH    => NN_WIDTH, 
  1288:         ERROR_WIDTH => ERROR_WIDTH, 
  1289:         RESET       => RESET 
  1290:       ) 
  1291:       port map ( 
  1292:         iErrVal     => sReg3.Errval(BITNESS downto 0), 
  1293:         iRItype     => sReg3.RiType, 
  1294:         iAq         => sReg3.Aq, 
  1295:         iNq         => sReg3.Nq, 
  1296:         iNn         => sReg3.Nn, 
  1297:         oAq         => sS4RiAqNew, 
  1298:         oNq         => sS4RiNqNew, 
  1299:         oNn         => sS4RiNnNew 
  1300:       ); 
  1301:    
  1302:     ------------------------------------------------------------------------------------------------------------- 
  1303:     -- Register 4 (Stage 4 → Stage 5) 
  1304:     ------------------------------------------------------------------------------------------------------------- 
  1305:     p_reg4 : process (iClk) is 
  1306:    
  1307:       variable v : t_pipeline_token; 
  1308:    
  1309:     begin 
  1310:    
  1311:       if rising_edge(iClk) then 
  1312:         if (iRst = '1') then 
  1313:           sReg4    <= CO_TOKEN_NONE; 
  1314:           sReg4V   <= '0'; 
  1315:           sReg4Eoi <= '0'; 
  1316:         elsif (sCE4 = '1') then 
  1317:           v   := sReg3; 
  1318:           v.k := resize(sS4K, K_WIDTH); 
  1319:           if (sReg3V = '0') then 
  1320:             v := CO_TOKEN_NONE; 
  1321:           end if; 
  1322:           sReg4    <= v; 
  1323:           sReg4V   <= sReg3V; 
  1324:           sReg4Eoi <= sReg3Eoi; 
  1325:         end if; 
  1326:       end if; 
  1327:    
  1328:     end process p_reg4; 
  1329:    
  1330:     ------------------------------------------------------------------------------------------------------------- 
  1331:     -- Stage 5 — Regular: A.11; RI: A.21 + A.22; 
  1332:     ------------------------------------------------------------------------------------------------------------- 
  1333:     u_a11 : entity work.a11_error_mapping(behavioral) 
  1334:       generic map ( 
  1335:         N_WIDTH                => N_WIDTH, 
  1336:         B_WIDTH                => B_WIDTH, 
  1337:         K_WIDTH                => K_WIDTH, 
  1338:         ERROR_WIDTH            => ERROR_WIDTH, 
  1339:         MAPPED_ERROR_VAL_WIDTH => MAPPED_ERROR_VAL_WIDTH 
  1340:       ) 
  1341:       port map ( 
  1342:         iK                     => sReg4.k, 
  1343:         iBq                    => sReg4.Bq, 
  1344:         iNq                    => sReg4.Nq, 
  1345:         iErrorVal              => sReg4.Errval(BITNESS downto 0), 
  1346:         oMappedErrorVal        => sS5MErrval 
  1347:       ); 
  1348:    
  1349:     u_a21 : entity work.a21_compute_map(behavioral) 
  1350:       generic map ( 
  1351:         K_WIDTH     => K_WIDTH, 
  1352:         N_WIDTH     => N_WIDTH, 
  1353:         ERROR_WIDTH => ERROR_WIDTH 
  1354:       ) 
  1355:       port map ( 
  1356:         iK          => sReg4.k, 
  1357:         iErrval     => sReg4.Errval(BITNESS downto 0), 
  1358:         iNn         => resize(sReg4.Nn, N_WIDTH), 
  1359:         iNq         => sReg4.Nq, 
  1360:         oMap        => sS5RiMap 
  1361:       ); 
  1362:    
  1363:     u_a22 : entity work.a22_errval_mapping(behavioral) 
  1364:       generic map ( 
  1365:         ERROR_WIDTH         => ERROR_WIDTH, 
  1366:         MAPPED_ERRVAL_WIDTH => MAPPED_ERROR_VAL_WIDTH 
  1367:       ) 
  1368:       port map ( 
  1369:         iErrval             => sReg4.Errval(BITNESS downto 0), 
  1370:         iRItype             => sReg4.RiType, 
  1371:         iMap                => sS5RiMap, 
  1372:         oEmErrVal           => sS5RiEmErrval 
  1373:       ); 
  1374:    
  1375:     sS5GolMErr <= sS5MErrval when sReg4.mode = token_regular else 
  1376:                   sS5RiEmErrval; 
  1377:    
  1378:     ------------------------------------------------------------------------------------------------------------- 
  1379:     -- Register 5 (Stage 5 mapping → A.11_1 golomb encoder) 
  1380:     ------------------------------------------------------------------------------------------------------------- 
  1381:     p_reg5 : process (iClk) is 
  1382:    
  1383:       variable v : t_pipeline_token; 
  1384:    
  1385:     begin 
  1386:    
  1387:       if rising_edge(iClk) then 
  1388:         if (iRst = '1') then 
  1389:           sReg5        <= CO_TOKEN_NONE; 
  1390:           sReg5V       <= '0'; 
  1391:           sReg5Eoi     <= '0'; 
  1392:           sReg5GolMErr <= (others => '0'); 
  1393:         elsif (sCE5 = '1') then 
  1394:           v := sReg4; 
  1395:           if (sReg4V = '0') then 
  1396:             v := CO_TOKEN_NONE; 
  1397:           end if; 
  1398:           sReg5        <= v; 
  1399:           sReg5V       <= sReg4V; 
  1400:           sReg5Eoi     <= sReg4Eoi; 
  1401:           sReg5GolMErr <= sS5GolMErr; 
  1402:         end if; 
  1403:       end if; 
  1404:    
  1405:     end process p_reg5; 
  1406:    
  1407:     u_a11_1 : entity work.a11_1_golomb_encoder(behavioral) 
  1408:       generic map ( 
  1409:         K_WIDTH                => K_WIDTH, 
  1410:         QBPP                   => QBPP, 
  1411:         LIMIT                  => LIMIT, 
  1412:         UNARY_WIDTH            => UNARY_WIDTH, 
  1413:         SUFFIX_WIDTH           => SUFFIX_WIDTH, 
  1414:         SUFFIXLEN_WIDTH        => SUFFIXLEN_WIDTH, 
  1415:         MAPPED_ERROR_VAL_WIDTH => MAPPED_ERROR_VAL_WIDTH 
  1416:       ) 
  1417:       port map ( 
  1418:         iK                     => sReg5.k, 
  1419:         iMappedErrorVal        => sReg5GolMErr, 
  1420:         iRiMode                => bool2bit(sReg5.mode = TOKEN_RUN_INTERRUPTION), 
  1421:         iRunIndex              => sReg5.RiRunIndex, 
  1422:         oUnaryZeros            => sS5Unary, 
  1423:         oSuffixLen             => sS5SufLen, 
  1424:         oSuffixVal             => sS5SufVal 
  1425:       ); 
  1426:    
  1427:     ------------------------------------------------------------------------------------------------------------- 
  1428:     -- Register 6 (golomb encoder → bit packer) 
  1429:     ------------------------------------------------------------------------------------------------------------- 
  1430:     p_reg6 : process (iClk) is 
  1431:    
  1432:       variable v : t_pipeline_token; 
  1433:    
  1434:     begin 
  1435:    
  1436:       if rising_edge(iClk) then 
  1437:         if (iRst = '1') then 
  1438:           sReg6       <= CO_TOKEN_NONE; 
  1439:           sReg6V      <= '0'; 
  1440:           sReg6Eoi    <= '0'; 
  1441:           sReg6Unary  <= (others => '0'); 
  1442:           sReg6SufLen <= (others => '0'); 
  1443:           sReg6SufVal <= (others => '0'); 
  1444:         elsif (sCE6 = '1') then 
  1445:           v := sReg5; 
  1446:           if (sReg5V = '0') then 
  1447:             v := CO_TOKEN_NONE; 
  1448:           end if; 
  1449:           sReg6       <= v; 
  1450:           sReg6V      <= sReg5V; 
  1451:           sReg6Eoi    <= sReg5Eoi; 
  1452:           sReg6Unary  <= sS5Unary; 
  1453:           sReg6SufLen <= sS5SufLen; 
  1454:           sReg6SufVal <= sS5SufVal; 
  1455:         end if; 
  1456:       end if; 
  1457:    
  1458:     end process p_reg6; 
  1459:    
  1460:     ------------------------------------------------------------------------------------------------------------- 
  1461:     -- Output — bit packer → byte stuffer → framer 
  1462:     --          internally registered in the IPs 
  1463:     ------------------------------------------------------------------------------------------------------------- 
  1464:     sBpRawV <= '1' when sReg6V = '1' and sStallLogic = '0' 
  1465:                         and (sReg6.mode = token_run_interruption or sReg6.mode = token_raw) else 
  1466:                '0'; 
  1467:     sBpGolV <= '1' when sReg6V = '1' and sStallLogic = '0' 
  1468:                         and (sReg6.mode = token_regular or sReg6.mode = token_run_interruption) else 
  1469:                '0'; 
  1470:    
  1471:     u_bit_packer : entity work.a11_2_bit_packer(behavioral) 
  1472:       generic map ( 
  1473:         LIMIT           => LIMIT, 
  1474:         OUT_WIDTH       => LIMIT, 
  1475:         UNARY_WIDTH     => UNARY_WIDTH, 
  1476:         SUFFIX_WIDTH    => SUFFIX_WIDTH, 
  1477:         SUFFIXLEN_WIDTH => SUFFIXLEN_WIDTH 
  1478:       ) 
  1479:       port map ( 
  1480:         iClk            => iClk, 
  1481:         iRst            => iRst, 
  1482:         iStall          => sStallLogic, 
  1483:         iRawValid       => sBpRawV, 
  1484:         iRawLen         => sReg6.RawLen, 
  1485:         iRawVal         => sReg6.RawVal, 
  1486:         iGolombValid    => sBpGolV, 
  1487:         iUnaryZeros     => sReg6Unary, 
  1488:         iSuffixLen      => sReg6SufLen, 
  1489:         iSuffixVal      => sReg6SufVal, 
  1490:         oWord           => sBpWord, 
  1491:         oWordValid      => sBpWordV, 
  1492:         oValidLen       => sBpValidLen 
  1493:       ); 
  1494:    
  1495:     u_byte_stuffer : entity work.byte_stuffer(behavioral) 
  1496:       generic map ( 
  1497:         IN_WIDTH            => LIMIT, 
  1498:         OUT_BYTES_PER_CYCLE => BYTE_STUFFER_OUT_BYTES_PER_CYCLE, 
  1499:         BURST_DEPTH         => BYTE_STUFFER_BURST_DEPTH 
  1500:       ) 
  1501:       port map ( 
  1502:         iClk                => iClk, 
  1503:         iRst                => iRst, 
  1504:         iStall              => sStallLogic, 
  1505:         iWord               => sBpWord, 
  1506:         iWordValid          => sBpWordV, 
  1507:         iWordValidLen       => sBpValidLen, 
  1508:         iFlush              => sBsFlush, 
  1509:         oWord               => sBsWord, 
  1510:         oWordValid          => sBsWordV, 
  1511:         oValidBytes         => sBsValidB, 
  1512:         iReady              => sFramerReady, 
  1513:         oAlmostFull         => sBsAlmostFull, 
  1514:         oFlushDone          => sBsFlushDone 
  1515:       ); 
  1516:    
  1517:     u_framer : entity work.jls_framer(behavioral) 
  1518:       generic map ( 
  1519:         BITNESS          => BITNESS, 
  1520:         IN_WIDTH         => BYTE_STUFFER_OUT_WIDTH, 
  1521:         OUT_WIDTH        => OUT_WIDTH, 
  1522:         MAX_IMAGE_WIDTH  => MAX_IMAGE_WIDTH, 
  1523:         MAX_IMAGE_HEIGHT => MAX_IMAGE_HEIGHT 
  1524:       ) 
  1525:       port map ( 
  1526:         iClk             => iClk, 
  1527:         iRst             => iRst, 
  1528:         iStart           => sFramerStart, 
  1529:         iImageWidth      => sImageWidth, 
  1530:         iImageHeight     => sImageHeight, 
  1531:         iEoi             => sFramerEoi, 
  1532:         iWord            => sBsWord, 
  1533:         iValid           => sBsWordV, 
  1534:         iByteEnable      => sBsValidB, 
  1535:         oReady           => sFramerReady, 
  1536:         iReady           => iReady, 
  1537:         oWord            => oData, 
  1538:         oValid           => oValid, 
  1539:         oByteEnable      => sFramerVBytes, 
  1540:         oLast            => oLast 
  1541:       ); 
  1542:    
  1543:     -- AXI-Stream tkeep: one bit per byte 
  1544:    
  1545:     gen_keep : for i in 0 to OUT_WIDTH / 8 - 1 generate 
  1546:       oKeep(OUT_WIDTH / 8 - 1 - i) <= '1' when sFramerVBytes > i else 
  1547:                                       '0'; 
  1548:     end generate gen_keep; 
  1549:    
  1550:     ------------------------------------------------------------------------------------------------------------- 
  1551:     -- Flush / framer control 
  1552:     ------------------------------------------------------------------------------------------------------------- 
  1553:    
  1554:     -- Pass the flush control from the EOI pipeline to the output stages 
  1555:     p_flush_control : process (iClk) is 
  1556:     begin 
  1557:    
  1558:       if rising_edge(iClk) then 
  1559:         if (iRst = '1') then 
  1560:           sBsFlush <= '0'; 
  1561:         elsif (sStallLogic = '0') then 
  1562:           sBsFlush <= sReg6Eoi; 
  1563:         end if; 
  1564:       end if; 
  1565:    
  1566:     end process p_flush_control; 
  1567:    
  1568:     sFramerEoi <= sBsFlushDone; 
  1569:    
  1570:     -- First-pixel tracker. line_buffer flags EOI combinationally on the image's 
  1571:     -- last accepted pixel, so the next accepted pixel starts the following image 
  1572:     p_first_pixel : process (iClk) is 
  1573:     begin 
  1574:    
  1575:       if rising_edge(iClk) then 
  1576:         if (iRst = '1') then 
  1577:           sFirstPixel <= '1'; 
  1578:         elsif (sValid = '1') then 
  1579:           sFirstPixel <= sLbEoi; 
  1580:         end if; 
  1581:       end if; 
  1582:    
  1583:     end process p_first_pixel; 
  1584:    
  1585:     sFramerStart <= sValid and sFirstPixel; 
  1586:    
  1587:   end architecture rtl;