📄 osd_sm.vhd
字号:
P_FIFO_URUN <= '0';
else
P_FIFO_URUN <= P_FIFO_URUN;
end if;
end if;
else
P_MUX_CTL <= P_MUX_CTL;
P_DATA_UNPACK <= P_DATA_UNPACK;
P_FIFO_URUN <= P_FIFO_URUN;
end if;
when BLANKING =>
-- During vertical blanking new parameters for OSD window are latched and FIFO flushed
-- This ensures that the new field will have a fresh start and will remain synchronized
-- with the video port.
if VSYNC = '1' and L1_VSYNC = '0' then
L_OSD_XSTART <= OSD_XSTART;
L_OSD_YSTART <= OSD_YSTART;
L_OSD_XSTOP <= OSD_XSTOP;
L_OSD_YSTOP <= OSD_YSTOP;
FIFO_FLUSH <= '1';
else
L_OSD_XSTART <= L_OSD_XSTART;
L_OSD_YSTART <= L_OSD_YSTART;
L_OSD_XSTOP <= L_OSD_XSTOP;
L_OSD_YSTOP <= L_OSD_YSTOP;
FIFO_FLUSH <= '0';
end if;
-- here though the state machine is in blanking, due to the latency in the state machine for one clock
-- cycle it may be necessary to output OSD data. Here COUNT_EN when it is zero tells the state machine
-- that active video portion of the video stream has completed. In this case video data is multilpexed.
-- If not, then the multiplexer control is kept unchanged.
if COUNT_EN <= '0' then
P_DATA_UNPACK <= '0';
P_MUX_CTL <= VID_DATA;
else
P_DATA_UNPACK <= P_DATA_UNPACK;
P_MUX_CTL <= P_MUX_CTL;
end if;
-- Events are unabled only when field detection is complete and Field 1 is detected. OSD_START when '1'
-- indicates that field detection is complete and Field 1 is detected.
if OSD_START = '1' then
P_EVT_EN <= '1';
else
P_EVT_EN <= '0';
end if;
-- This logic here performs field detection. Field 1 is detected (Field = '0') when the leading edges
-- of HSYNC and VSYNC are within 64 clock cycles of each other. A DETECT_CNTR is maintained that starts
-- counting whenever it detects a VSYNC or HSYNC. If it detects the other within 64 clock cycles, Field 1
-- is detected. If a VSYNC is detected, but no HSYNC happens within 64 clock cycles, then Field 0 is detected.
-- DETECT_VSYNC signal tells the logic which signal was detected and which one it needs to look for.
if FIELD_SET = '0' then
if CNTR_ON = '0' then
DETECT_CNTR <= (others => '0');
if (L1_HSYNC = '0' and HSYNC = '1') and (L1_VSYNC = '0' and VSYNC = '1') then
-- This takes care of the situation where both leading edges happen in the same
-- clock cycle.
CNTR_ON <= '0';
DETECT_VSYNC <= '0';
FIELD_SET <= '1';
FIELD <= '0';
OSD_START <= '1';
elsif (L1_HSYNC = '0' and HSYNC = '1') then
-- Here HSYNC has been detected. DETECT_VSYNC is set to '1' to tell the logic
-- to look for VSYNC. The detect counter is enabled.
CNTR_ON <= '1';
DETECT_VSYNC <= '1';
FIELD_SET <= '0';
FIELD <= '0';
OSD_START <= '0';
elsif (L1_VSYNC = '0' and VSYNC = '1') then
-- Here VSYNC has been detected. DETECT_VSYNC is set to '0' to tell the logic
-- to look for HSYNC. The detect counter is enabled.
CNTR_ON <= '1';
DETECT_VSYNC <= '0';
FIELD_SET <= '0';
FIELD <= '0';
OSD_START <= '0';
end if;
else
if (DETECT_VSYNC = '1') then
-- Here we are looking for a VSYNC.
if (DETECT_CNTR <= "1000000") and (L1_VSYNC = '0' and VSYNC = '1') then
-- VSYNC is detected within 64 clock cycles, field is set to Field 1.
-- OSD_START is set to '1' and events can begin.
FIELD <= '0';
CNTR_ON <= '0';
FIELD_SET <= '1';
DETECT_CNTR <= (others => '0');
OSD_START <= '1';
DETECT_VSYNC <= '0';
elsif DETECT_CNTR > "1000000" then
-- No VSYNC detected and counter has exceeded 64. The whole logic is
-- reset at this point to start over.
FIELD <= FIELD;
CNTR_ON <= '0';
FIELD_SET <= '0';
DETECT_CNTR <= (others => '0');
OSD_START <= '0';
DETECT_VSYNC <= '0';
else
-- Here we continue to look for VSYNC.
FIELD <= FIELD;
CNTR_ON <= '1';
FIELD_SET <= '0';
DETECT_CNTR <= DETECT_CNTR + 1;
OSD_START <= '0';
DETECT_VSYNC <= DETECT_VSYNC;
end if;
else
-- Here VSYNC has been detected and we are looking for HSYNC.
DETECT_VSYNC <= DETECT_VSYNC;
if (DETECT_CNTR <= "1000000") and (L1_HSYNC = '0' and HSYNC = '1') then
-- HSYNC is detected within 64 cycles. We set the field to Field 1.
-- OSD_START is set to '1' and events can begin.
FIELD <= '0';
CNTR_ON <= '0';
FIELD_SET <= '1';
DETECT_CNTR <= (others => '0');
OSD_START <= '1';
elsif DETECT_CNTR > "1000000" then
-- We have counted past 64 cycles without detecting HSYNC. Field is
-- set to Field 2. However OSD_START is set to '0' as we want to start
-- on Field 1.
FIELD <= '1';
CNTR_ON <= '0';
FIELD_SET <= '1';
DETECT_CNTR <= (others => '0');
OSD_START <= '0';
else
-- Here we continue to look for HSYNC.
FIELD <= FIELD;
CNTR_ON <= '1';
FIELD_SET <= '0';
DETECT_CNTR <= DETECT_CNTR + 1;
OSD_START <= '0';
end if;
end if;
end if;
else
-- Here field detection has been completed and we toggle the fields on detecting leading edge
-- of VSYNC.
if (L1_VSYNC = '0' and VSYNC = '1') then
FIELD <= not FIELD;
-- If OSD_START was not already enabled, it is enabled here. Events can start.
OSD_START <= '1';
else
FIELD <= FIELD;
OSD_START <= OSD_START;
end if;
end if;
when others =>
NULL;
end case;
end if;
end process MAIN_PROCESS;
-- purpose: Adds latency to the state control and output signals
LATENCY: process (VCLK, RESETz)
begin -- process LATENCY
if RESETz = '0' or SRESETz = '0' then -- asynchronous reset (active low)
PRESENT_STATE <= IDLE;
elsif VCLK'event and VCLK = '1' then -- rising clock edge
PRESENT_STATE <= NEXT_STATE;
end if;
end process LATENCY;
FLUSH_FIFO <= FIFO_FLUSH;
FIFO_URUN <= P_FIFO_URUN;
EVT_EN <= P_EVT_EN;
DATA_UNPACk <= P_DATA_UNPACK;
-- purpose: adds latency to signals to align all the data and control
-- signals that arrive at the OSD multiplexer
ADD_LATENCY: process (VCLK, RESETz)
begin -- process ADD_LATENCY
if RESETz = '0' or SRESETz = '0' then -- asynchronous reset (active low)
E1_MUX_CTL <= '0';
E2_MUX_CTL <= '0';
E3_MUX_CTL <= '0';
E4_MUX_CTL <= '0';
MUX_CTL <= '0';
L1_VSYNC <= '0';
L1_HSYNC <= '0';
elsif VCLK'event and VCLK = '1' then -- rising clock edge
E4_MUX_CTL <= P_MUX_CTL;
E3_MUX_CTL <= E4_MUX_CTL;
E2_MUX_CTL <= E3_MUX_CTL;
E1_MUX_CTL <= E2_MUX_CTL;
MUX_CTL <= E1_MUX_CTL;
L1_VSYNC <= VSYNC;
L1_HSYNC <= HSYNC;
end if;
end process ADD_LATENCY;
-- purpose: keeps tracks of active pixels and active lines
COUNTERS : process(VCLK, RESETz)
begin -- process COUNTERS
if RESETz = '0' or SRESETz = '0' then
FP_COUNT <= (others => '0');
FL_COUNT <= (others => '0');
FL_COUNT_RESET <= '1';
COUNT_EN <= '0';
elsif VCLK'event and VCLK = '1' then
if OSD_EN = '1' then
if AVID = '0' then
FP_COUNT <= (others => '0');
if VSYNC = '1' then
FL_COUNT <= (others => '0');
FL_COUNT_RESET <= '1';
elsif L1_HSYNC = '0' and HSYNC = '1' and FL_COUNT_RESET = '0' then
FL_COUNT <= FL_COUNT + 1;
FL_COUNT_RESET <= FL_COUNT_RESET;
else
FL_COUNT <= FL_COUNT;
FL_COUNT_RESET <= FL_COUNT_RESET;
end if;
COUNT_EN <= '0';
else
if COUNT_EN = '1' then
FP_COUNT <= FP_COUNT + 1;
FL_COUNT <= FL_COUNT;
FL_COUNT_RESET <= '0';
else
FP_COUNT <= FP_COUNT;
FL_COUNT <= FL_COUNT;
FL_COUNT_RESET <= FL_COUNT_RESET;
end if;
if BUS_WIDTH_8 = '1' then
COUNT_EN <= not COUNT_EN;
else
COUNT_EN <= '1';
end if;
end if;
else
FP_COUNT <= (others => '0');
FL_COUNT <= (others => '0');
FL_COUNT_RESET <= '1';
COUNT_EN <= '0';
end if;
end if;
end process COUNTERS;
end RTL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -