📄 tx_encoder.vhd
字号:
-------------------------------------------------------------------------- -------- WISHBONE SPDIF IP Core -------- -------- This file is part of the SPDIF project -------- http://www.opencores.org/cores/spdif_interface/ -------- -------- Description -------- SPDIF transmitter signal encoder. Reads out samples from the -------- sample buffer, assembles frames and subframes and encodes -------- serial data as bi-phase mark code. -------- -------- To Do: -------- - -------- -------- Author(s): -------- - Geir Drange, gedra@opencores.org -------- ------------------------------------------------------------------------------ -------- Copyright (C) 2004 Authors and OPENCORES.ORG -------- -------- This source file may be used and distributed without -------- restriction provided that this copyright statement is not -------- removed from the file and that any derivative work contains -------- the original copyright notice and the associated disclaimer. -------- -------- This source file is free software; you can redistribute it -------- and/or modify it under the terms of the GNU Lesser General -------- Public License as published by the Free Software Foundation; -------- either version 2.1 of the License, or (at your option) any -------- later version. -------- -------- This source is distributed in the hope that it will be -------- useful, but WITHOUT ANY WARRANTY; without even the implied -------- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR -------- PURPOSE. See the GNU Lesser General Public License for more -------- details. -------- -------- You should have received a copy of the GNU Lesser General -------- Public License along with this source; if not, download it -------- from http://www.opencores.org/lgpl.shtml -------- ------------------------------------------------------------------------------ CVS Revision History---- $Log: tx_encoder.vhd,v $-- Revision 1.3 2007/10/11 19:14:43 gedra-- Code beautification---- Revision 1.2 2005/03/27 14:02:51 gedra-- evt_hsbf and evt_lsbf signals stayed high too long---- Revision 1.1 2004/07/19 16:59:08 gedra-- Transmitter SPDIF encoder.------library ieee;use ieee.std_logic_1164.all;use ieee.numeric_std.all;entity tx_encoder is generic (DATA_WIDTH : integer range 16 to 32; ADDR_WIDTH : integer range 8 to 64); port ( wb_clk_i : in std_logic; -- clock conf_mode : in std_logic_vector(3 downto 0); -- sample format conf_ratio : in std_logic_vector(7 downto 0); -- clock divider conf_udaten : in std_logic_vector(1 downto 0); -- user data control conf_chsten : in std_logic_vector(1 downto 0); -- ch. status control conf_txdata : in std_logic; -- sample data enable conf_txen : in std_logic; -- spdif signal enable user_data_a : in std_logic_vector(191 downto 0); -- ch. a user data user_data_b : in std_logic_vector(191 downto 0); -- ch. b user data ch_stat_a : in std_logic_vector(191 downto 0); -- ch. a status ch_stat_b : in std_logic_vector(191 downto 0); -- ch. b status chstat_freq : in std_logic_vector(1 downto 0); -- sample freq. chstat_gstat : in std_logic; -- generation status chstat_preem : in std_logic; -- preemphasis status chstat_copy : in std_logic; -- copyright bit chstat_audio : in std_logic; -- data format sample_data : in std_logic_vector(DATA_WIDTH - 1 downto 0); -- audio data mem_rd : out std_logic; -- sample buffer read sample_addr : out std_logic_vector(ADDR_WIDTH - 2 downto 0); -- address evt_lcsbf : out std_logic; -- lower ch.st./user data buf empty evt_hcsbf : out std_logic; -- higher ch.st/user data buf empty evt_hsbf : out std_logic; -- higher sample buf empty event evt_lsbf : out std_logic; -- lower sample buf empty event spdif_tx_o : out std_logic);end tx_encoder;architecture rtl of tx_encoder is signal spdif_clk_en, spdif_out : std_logic; signal clk_cnt : integer range 0 to 511; type buf_states is (IDLE, READ_CHA, READ_CHB, CHA_RDY, CHB_RDY); signal bufctrl : buf_states; signal adr_cnt : integer range 0 to 2**(ADDR_WIDTH - 1) - 1; signal cha_samp_ack, chb_samp_ack : std_logic; type frame_states is (IDLE, BLOCK_START, CHANNEL_A, CHANNEL_B); signal framest : frame_states; signal frame_cnt : integer range 0 to 191; signal bit_cnt, par_cnt : integer range 0 to 31; signal inv_preamble, toggle, valid : std_logic; signal def_user_data, def_ch_status : std_logic_vector(191 downto 0); signal active_user_data, active_ch_status : std_logic_vector(191 downto 0); signal audio : std_logic_vector(23 downto 0); signal par_vector : std_logic_vector(26 downto 0); signal send_audio, imem_rd : std_logic; constant X_PREAMBLE : std_logic_vector(0 to 7) := "11100010"; constant Y_PREAMBLE : std_logic_vector(0 to 7) := "11100100"; constant Z_PREAMBLE : std_logic_vector(0 to 7) := "11101000"; function encode_bit ( signal bit_cnt : integer; -- sub-frame bit position signal valid : std_logic; -- validity bit signal frame_cnt : integer; -- frame counter signal par_cnt : integer; -- parity counter signal user_data : std_logic_vector(191 downto 0); signal ch_status : std_logic_vector(191 downto 0); signal audio : std_logic_vector(23 downto 0); signal toggle : std_logic; signal prev_spdif : std_logic) -- prev. value of spdif signal return std_logic is variable spdif, next_bit : std_logic; begin if bit_cnt > 3 and bit_cnt < 28 then -- audio part next_bit := audio(bit_cnt - 4); elsif bit_cnt = 28 then -- validity bit next_bit := valid; elsif bit_cnt = 29 then -- user data next_bit := user_data(frame_cnt); elsif bit_cnt = 30 then next_bit := ch_status(frame_cnt); -- channel status elsif bit_cnt = 31 then if par_cnt mod 2 = 1 then next_bit := '1'; else next_bit := '0'; end if; end if; -- bi-phase mark encoding: if next_bit = '0' then if toggle = '0' then spdif := not prev_spdif; else spdif := prev_spdif; end if; else spdif := not prev_spdif; end if; return(spdif); end encode_bit; begin-- SPDIF clock enable generation. The clock is a fraction of the Wishbone bus-- clock, determined by the conf_ratio value. CGEN : process (wb_clk_i) begin if rising_edge(wb_clk_i) then if conf_txen = '0' then -- transmitter disabled spdif_clk_en <= '0'; clk_cnt <= 0; else -- transmitter enabled if clk_cnt < to_integer(unsigned(conf_ratio)) then -- <= ? clk_cnt <= clk_cnt + 1; spdif_clk_en <= '0'; else clk_cnt <= 0; spdif_clk_en <= '1'; end if; end if; end if; end process CGEN;-- Sample memory read process. Enabled by the conf_txdata bit.-- Buffer address is reset when disabled. Also generates events for-- lower and upper buffer empty conditions sample_addr <= std_logic_vector(to_unsigned(adr_cnt, ADDR_WIDTH - 1)); mem_rd <= imem_rd; SRD : process (wb_clk_i) begin if rising_edge(wb_clk_i) then if conf_txdata = '0' then bufctrl <= IDLE; imem_rd <= '0'; adr_cnt <= 0; evt_lsbf <= '0'; evt_hsbf <= '0'; else case bufctrl is when IDLE => adr_cnt <= 0; imem_rd <= '0'; if conf_txdata = '1' then bufctrl <= READ_CHA; imem_rd <= '1'; end if; when READ_CHA => imem_rd <= '0'; adr_cnt <= (adr_cnt + 1) mod 2**(ADDR_WIDTH - 1); bufctrl <= CHA_RDY; when CHA_RDY => if cha_samp_ack = '1' then imem_rd <= '1'; bufctrl <= READ_CHB; end if; when READ_CHB => imem_rd <= '0'; adr_cnt <= (adr_cnt + 1) mod 2**(ADDR_WIDTH - 1); bufctrl <= CHB_RDY; when CHB_RDY => if chb_samp_ack = '1' then imem_rd <= '1'; bufctrl <= READ_CHA; end if; when others => bufctrl <= IDLE; end case; -- generate lower/upper buffer empty events if imem_rd = '1' then if adr_cnt = 2**(ADDR_WIDTH - 2) - 1 then evt_lsbf <= '1'; end if; if adr_cnt = 2**(ADDR_WIDTH - 1) - 1 then evt_hsbf <= '1'; end if; else evt_lsbf <= '0'; evt_hsbf <= '0'; end if; end if; end if; end process SRD;-- State machine that generates sub-frames and blocks spdif_tx_o <= spdif_out; FRST : process (wb_clk_i) begin if rising_edge(wb_clk_i) then if conf_txen = '0' then framest <= IDLE; frame_cnt <= 0; bit_cnt <= 0; spdif_out <= '0'; inv_preamble <= '0'; toggle <= '0'; valid <= '1'; send_audio <= '0'; cha_samp_ack <= '0'; chb_samp_ack <= '0'; evt_lcsbf <= '0'; evt_hcsbf <= '0';
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -