summaryrefslogtreecommitdiffstats
path: root/spdif_decoder.vhd
blob: c16a6f53c77ef1e060d82b8ce73f6d1b170796fd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.std_logic_unsigned.all;
use IEEE.std_logic_misc.all;
use IEEE.numeric_std.all;


-- clk wants to be so that the small feature is 3 ticks

entity spdif_decoder is
    generic (
        Z24 : std_logic_vector(23 downto 0) := (others => '0');
        Z32 : std_logic_vector(31 downto 0) := (others => '0')
        );


    port (
        n_reset : in std_logic;
        spdif   : in std_logic;
        clk     : in std_logic;

        bmc_ready : out std_logic;
        bmc_e     : out std_logic;
        bmc_l     : out std_logic;
        bmc_d     : out std_logic;

        d     : out std_logic_vector(26 downto 0);
        ready : out std_logic;
        sof   : out std_logic;
        bna   : out std_logic;
        sos   : out std_logic
        );
end spdif_decoder;


architecture rtl of spdif_decoder is

    component bmc_decoder is
        port
            (
                n_reset : in  std_logic;
                clk     : in  std_logic;
                spdif   : in  std_logic;
                ready   : out std_logic;
                e       : out std_logic;
                l       : out std_logic;
                d       : out std_logic
                );
    end component;


    signal b_ready : std_logic;
    signal b_e     : std_logic;
    signal b_l     : std_logic;
    signal b_d     : std_logic;

    signal parity_valid : std_logic;

    signal e_sr : std_logic_vector(31 downto 0);
    signal d_sr : std_logic_vector(31 downto 0);
    signal l_sr : std_logic_vector(31 downto 0);

    signal d_buf     : std_logic_vector(26 downto 0);
    signal sof_buf   : std_logic;
    signal sos_buf   : std_logic;
    signal ready_buf : std_logic;
    signal bna_buf   : std_logic;
begin

    bmc :
        bmc_decoder port map (
            n_reset => n_reset,
            clk     => clk,
            spdif   => spdif,
            ready   => b_ready,
            e       => b_e,
            l       => b_l,
            d       => b_d
            );

    bmc_ready <= b_ready;
    bmc_e     <= b_e;
    bmc_l     <= b_l;
    bmc_d     <= b_d;


    process (clk, b_ready, b_e, b_l, b_d, n_reset)
    begin
        if n_reset = '0' then
            e_sr <= (others => '0');
            d_sr <= (others => '0');
            l_sr <= (others => '0');
        elsif rising_edge(clk) then
            if (b_ready = '1') then
                e_sr <= b_e & e_sr(31 downto 1);
                d_sr <= b_d & d_sr(31 downto 1);
                l_sr <= b_l & l_sr(31 downto 1);
            end if;
        end if;
    end process;


    parity_valid <= not xor_reduce(d_sr(31 downto 4));

    process (clk, b_ready, e_sr, l_sr, d_sr, parity_valid, n_reset)
    begin
        if n_reset = '0' then
            d_buf     <= (others => '0');
            sof_buf   <= '0';
            bna_buf   <= '0';
            ready_buf <= '0';
        elsif rising_edge(clk) then
            if (b_ready = '1') and (parity_valid = '1') and (e_sr = Z32) then
                if (d_sr(3 downto 1) = "010") and (l_sr(3 downto 1) = "101") then  --B code
                    d_buf     <= d_sr(29 downto 3);
                    sof_buf   <= '1';
                    sos_buf   <= '1';
                    bna_buf   <= '0';
                    ready_buf <= '1';
                elsif (d_sr(3 downto 1) = "100") and (l_sr(3 downto 1) = "011") then  --M code
                    d_buf     <= d_sr(29 downto 3);
                    sof_buf   <= '0';
                    sos_buf   <= '1';
                    bna_buf   <= '0';
                    ready_buf <= '1';
                elsif (d_sr(3 downto 0) = "0100") and (l_sr(3 downto 0) = "0001") then  --W code
                    d_buf     <= d_sr(30 downto 4);
                    sof_buf   <= '0';
                    sos_buf   <= '0';
                    bna_buf   <= '1';
                    ready_buf <= '1';
                else
                    sof_buf   <= '0';
                    sos_buf   <= '0';
                    bna_buf   <= '1';
                    ready_buf <= '0';
                end if;
            else
                sof_buf   <= '0';
                sos_buf   <= '0';
                bna_buf   <= '1';
                ready_buf <= '0';
            end if;
        end if;

    end process;

    d     <= d_buf;
    ready <= ready_buf;
    sof   <= sof_buf;
    bna   <= bna_buf;
    sos   <= sos_buf;

end rtl;