File: ../../Sources/A15_A16_encode_run.vhd
0: ----------------------------------------------------------------------------------
1: -- Engineer: Vitor Mendes Camilo
2: --
3: -- Module Name: A15_A16_encode_run - Behavioral
4: -- Description: Code segments A.15 and A.16 — run-segment encoding.
5: --
6: -- Mealy FSM: outputs are combinational from A14's current outputs
7: -- and registered state. A14 is connected combinationally (no
8: -- register between A14 and this stage).
9: --
10: -- sNextBound: cumulative pixel count at which the next A15 '1' bit
11: -- fires. Initialized to 2^J[RUNindex] at run start; advances by
12: -- 2^J[RUNindex+1] on each boundary hit.
13: --
14: -- Each cycle when iRunHit='1':
15: -- if iRunCnt == sNextBound → emit A15 '1' (oA15Valid).
16: -- When run ends (iRunContinue='0'):
17: -- EOLine, residual > 0: emit A16 '1' bit (only if no boundary hit).
18: -- Break (iRunHit='0'): emit RI token with A16 prefix. Covers
19: -- both breaks after one or more matches (sInRun='1') and the
20: -- immediate-break case on the first pixel of run mode
21: -- (sInRun='0', RUNcnt=0 → single '0' bit + RI).
22: --
23: -- RUNindex persists across runs within a scan; resets at iEoi.
24: ----------------------------------------------------------------------------------
25:
26: library ieee;
27: use ieee.std_logic_1164.all;
28: use ieee.numeric_std.all;
29: use work.openjls_pkg.all;
30:
31: entity a15_a16_encode_run is
32: generic (
33: BITNESS : natural := CO_BITNESS_STD;
34: RUN_CNT_WIDTH : natural := 16
35: );
36: port (
37: iClk : in std_logic;
38: iRst : in std_logic;
39: iCE : in std_logic;
40: iEoi : in std_logic;
41:
42: -- From A14 (combinational — no register between A14 and this stage)
43: iRunCnt : in unsigned(RUN_CNT_WIDTH - 1 downto 0); -- A14 oRunCnt
44: iRunHit : in std_logic; -- A14 oRunHit
45: iRunContinue : in std_logic; -- A14 oRunContinue
46:
47: -- Mode gate: only process when pipeline is in run mode
48: iModeIsRun : in std_logic;
49:
50: -- Pixel data for RI token (valid on break cycle)
51: iIx : in unsigned(BITNESS - 1 downto 0);
52: iRa : in unsigned(BITNESS - 1 downto 0);
53: iRb : in unsigned(BITNESS - 1 downto 0);
54:
55: -- Raw bit token: A15 '1' bits (SuffixLen=1, SuffixVal=1) and
56: -- A16 break prefix (SuffixLen=J+1, SuffixVal=residual).
57: -- oRiValid may be asserted simultaneously on break.
58: oRawValid : out std_logic;
59: oRawSuffixLen : out unsigned(4 downto 0);
60: oRawSuffixVal : out unsigned(RUN_CNT_WIDTH - 1 downto 0);
61:
62: -- Run-interruption token (break case only); carries Ix/Ra/Rb for Golomb path.
63: -- oRiRunIndex is RUNindex before the A.16 decrement, used by A.22.1 to
64: -- compute glimit = LIMIT - J[RUNindex] - 1.
65: oRiValid : out std_logic;
66: oRiIx : out unsigned(BITNESS - 1 downto 0);
67: oRiRa : out unsigned(BITNESS - 1 downto 0);
68: oRiRb : out unsigned(BITNESS - 1 downto 0);
69: oRiRunIndex : out unsigned(4 downto 0);
70: oInRunNext : out std_logic -- Tells top level we are mid-run
71: );
72: end entity a15_a16_encode_run;
73:
74: architecture behavioral of a15_a16_encode_run is
75:
76: constant C_BOUND_WIDTH : natural := RUN_CNT_WIDTH + 1;
77:
78: -- Registered state
79: signal sRunIndex : unsigned(4 downto 0);
80: signal sNextBound : unsigned(C_BOUND_WIDTH - 1 downto 0);
81: signal sInRun : std_logic;
82:
83: -- Next-state signals (driven combinationally, captured by clocked process)
84: signal sRunIndexNext : unsigned(4 downto 0);
85: signal sNextBoundNext : unsigned(C_BOUND_WIDTH - 1 downto 0);
86: signal sInRunNext : std_logic;
87:
88: begin
89:
90: -- Contract assertions in PSL (active in NVC sims via --psl, plain comments
91: -- to synthesis): run state and RUNindex must clear one cycle after iEoi
92: -- (T.87: RUNindex persists across runs within a scan only); tokens only
93: -- fire in run mode.
94: -- psl default clock is rising_edge(iClk);
95: -- psl assert always ((iRst = '1' or iEoi = '1') -> next (sInRun = '0' and sRunIndex = 0)) report "a15_a16: run state must clear one cycle after iEoi/reset";
96: -- psl assert always (iModeIsRun = '0' -> (oRawValid = '0' and oRiValid = '0')) report "a15_a16: no tokens outside run mode";
97:
98: -- ── Combinational: outputs and next-state ─────────────────────────────────
99: p_comb : process (sRunIndex, sNextBound, sInRun,
100: iRunCnt, iRunHit, iRunContinue, iModeIsRun, iEoi, iRst,
101: iIx, iRa, iRb) is
102:
103: variable vJ : natural;
104: variable vJNext : natural;
105: variable vStep : unsigned(C_BOUND_WIDTH - 1 downto 0);
106: variable vStepNext : unsigned(C_BOUND_WIDTH - 1 downto 0);
107: variable vBoundHit : boolean;
108: variable vNewIndex : unsigned(4 downto 0);
109:
110: begin
111:
112: -- Output defaults
113: oRawValid <= '0';
114: oRawSuffixLen <= to_unsigned(1, 5);
115: oRawSuffixVal <= to_unsigned(1, RUN_CNT_WIDTH);
116: oRiValid <= '0';
117: oRiIx <= iIx;
118: oRiRa <= iRa;
119: oRiRb <= iRb;
120: oRiRunIndex <= sRunIndex;
121:
122: -- Next-state defaults: hold current
123: sRunIndexNext <= sRunIndex;
124: sNextBoundNext <= sNextBound;
125: sInRunNext <= sInRun;
126:
127: if (iModeIsRun = '1' and iRst = '0') then
128: vJ := CO_J_TABLE(to_integer(sRunIndex));
129: vStep := shift_left(to_unsigned(1, C_BOUND_WIDTH), vJ);
130: if (sRunIndex < 31) then
131: vJNext := CO_J_TABLE(to_integer(sRunIndex) + 1);
132: else
133: vJNext := CO_J_TABLE(31);
134: end if;
135: vStepNext := shift_left(to_unsigned(1, C_BOUND_WIDTH), vJNext);
136:
137: if (iRunHit = '1') then
138: -- ── A.15: matching pixel ───────────────────────────────────────────
139: vBoundHit := resize(iRunCnt, C_BOUND_WIDTH) = sNextBound;
140: vNewIndex := sRunIndex;
141:
142: if (vBoundHit) then
143: oRawValid <= '1';
144: if (sRunIndex < 31) then
145: vNewIndex := sRunIndex + 1;
146: end if;
147: end if;
148:
149: sInRunNext <= '1';
150:
151: if (iRunContinue = '0') then
152: -- EOLine
153: sInRunNext <= '0';
154: if (not vBoundHit and iRunCnt > 0) then
155: oRawValid <= '1'; -- A16 EOLine '1' bit
156: end if;
157: sRunIndexNext <= vNewIndex;
158: sNextBoundNext <= shift_left(to_unsigned(1, C_BOUND_WIDTH),
159: CO_J_TABLE(to_integer(vNewIndex)));
160: else
161: -- Run continues
162: sRunIndexNext <= vNewIndex;
163: if (vBoundHit) then
164: sNextBoundNext <= sNextBound + vStepNext;
165: end if;
166: end if;
167: else
168: -- ── A.16: break (iRunHit='0') ─────────────────────────────────────
169: -- Covers both break-after-matches (sInRun='1') and immediate break on
170: -- the first pixel of run mode (sInRun='0', RUNcnt=0).
171: -- residual = iRunCnt - (sNextBound - vStep) = count since last boundary
172: -- (for immediate break: iRunCnt=0, sNextBound=1, vStep=1 → residual=0,
173: -- SuffixLen = J[0]+1 = 1 → single '0' break marker).
174: oRawValid <= '1';
175: oRawSuffixLen <= to_unsigned(vJ + 1, 5);
176: oRawSuffixVal <= iRunCnt - resize(sNextBound - vStep, RUN_CNT_WIDTH);
177: oRiValid <= '1';
178: oRiIx <= iIx;
179: oRiRa <= iRa;
180: oRiRb <= iRb;
181:
182: if (sRunIndex > 0) then
183: vNewIndex := sRunIndex - 1;
184: else
185: vNewIndex := (others => '0');
186: end if;
187:
188: sInRunNext <= '0';
189: sRunIndexNext <= vNewIndex;
190: sNextBoundNext <= shift_left(to_unsigned(1, C_BOUND_WIDTH),
191: CO_J_TABLE(to_integer(vNewIndex)));
192: end if;
193: end if;
194:
195: end process p_comb;
196:
197: oInRunNext <= sInRunNext;
198:
199: -- ── Clocked: state registers ──────────────────────────────────────────────
200: p_state_reg : process (iClk) is
201: begin
202:
203: if rising_edge(iClk) then
204: if (iRst = '1' or iEoi = '1') then
205: sRunIndex <= (others => '0');
206: sNextBound <= to_unsigned(1, C_BOUND_WIDTH);
207: sInRun <= '0';
208: elsif (iCE = '1') then
209: sRunIndex <= sRunIndexNext;
210: sNextBound <= sNextBoundNext;
211: sInRun <= sInRunNext;
212: end if;
213: end if;
214:
215: end process p_state_reg;
216:
217: end architecture behavioral;