⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ym2149_linmix.vhd

📁 a vhdl model to ym2149
💻 VHD
📖 第 1 页 / 共 2 页
字号:
      ena_div_noise <= '0';
      if (cnt_div = "0000") then
        cnt_div <= (not I_SEL_L) & "111";
        ena_div <= '1';

        noise_div <= not noise_div;
        if (noise_div = '1') then
          ena_div_noise <= '1';
        end if;
      else
        cnt_div <= cnt_div - "1";
      end if;
    end if;
  end process;

  p_noise_gen            : process
    variable noise_gen_comp : std_logic_vector(4 downto 0);
    variable poly17_zero : std_logic;
  begin
    wait until rising_edge(CLK);

    if (reg(6)(4 downto 0) = "00000") then
      noise_gen_comp := "00000";
    else
      noise_gen_comp := (reg(6)(4 downto 0) - "1");
    end if;

    poly17_zero := '0';
    if (poly17 = "00000000000000000") then poly17_zero := '1'; end if;

    if (ENA = '1') then

      if (ena_div_noise = '1') then -- divider ena

        if (noise_gen_cnt >= noise_gen_comp) then
          noise_gen_cnt <= "00000";
          poly17 <= (poly17(0) xor poly17(2) xor poly17_zero) & poly17(16 downto 1);
        else
          noise_gen_cnt <= (noise_gen_cnt + "1");
        end if;
      end if;
    end if;
  end process;
  noise_gen_op <= poly17(0);

  p_tone_gens            : process
    variable tone_gen_freq : array_3x12;
    variable tone_gen_comp : array_3x12;
  begin
    wait until rising_edge(CLK);

    -- looks like real chips count up - we need to get the Exact behaviour ..
    tone_gen_freq(1) := reg(1)(3 downto 0) & reg(0);
    tone_gen_freq(2) := reg(3)(3 downto 0) & reg(2);
    tone_gen_freq(3) := reg(5)(3 downto 0) & reg(4);
    -- period 0 = period 1
    for i in 1 to 3 loop
      if (tone_gen_freq(i) = x"000") then
        tone_gen_comp(i) := x"000";
      else
        tone_gen_comp(i) := (tone_gen_freq(i) - "1");
      end if;
    end loop;

    if (ENA = '1') then
      for i in 1 to 3 loop
        if (ena_div = '1') then -- divider ena

          if (tone_gen_cnt(i) >= tone_gen_comp(i)) then
            tone_gen_cnt(i) <= x"000";
            tone_gen_op(i) <= not tone_gen_op(i);
          else
            tone_gen_cnt(i) <= (tone_gen_cnt(i) + "1");
          end if;
        end if;
      end loop;
    end if;
  end process;

  p_envelope_freq        : process
    variable env_gen_freq : std_logic_vector(15 downto 0);
    variable env_gen_comp : std_logic_vector(15 downto 0);
  begin
    wait until rising_edge(CLK);
    env_gen_freq := reg(12) & reg(11);
    -- envelope freqs 1 and 0 are the same.
    if (env_gen_freq = x"0000") then
      env_gen_comp := x"0000";
    else
      env_gen_comp := (env_gen_freq - "1");
    end if;

    if (ENA = '1') then
      env_ena <= '0';
      if (ena_div = '1') then -- divider ena
        if (env_gen_cnt >= env_gen_comp) then
          env_gen_cnt <= x"0000";
          env_ena <= '1';
        else
          env_gen_cnt <= (env_gen_cnt + "1");
        end if;
      end if;
    end if;
  end process;

  p_envelope_shape       : process(env_reset, CLK)
    variable is_bot    : boolean;
    variable is_bot_p1 : boolean;
    variable is_top_m1 : boolean;
    variable is_top    : boolean;
  begin
        -- envelope shapes
        -- C AtAlH
        -- 0 0 x x  \___
        --
        -- 0 1 x x  /___
        --
        -- 1 0 0 0  \\\\
        --
        -- 1 0 0 1  \___
        --
        -- 1 0 1 0  \/\/
        --           ___
        -- 1 0 1 1  \
        --
        -- 1 1 0 0  ////
        --           ___
        -- 1 1 0 1  /
        --
        -- 1 1 1 0  /\/\
        --
        -- 1 1 1 1  /___
    if (env_reset = '1') then
      -- load initial state
      if (reg(13)(2) = '0') then -- attack
        env_vol <= "11111";
        env_inc <= '0'; -- -1
      else
        env_vol <= "00000";
        env_inc <= '1'; -- +1
      end if;
      env_hold <= '0';

    elsif rising_edge(CLK) then
      is_bot    := (env_vol = "00000");
      is_bot_p1 := (env_vol = "00001");
      is_top_m1 := (env_vol = "11110");
      is_top    := (env_vol = "11111");

      if (ENA = '1') then
        if (env_ena = '1') then
          if (env_hold = '0') then
            if (env_inc = '1') then
              env_vol <= (env_vol + "00001");
            else
              env_vol <= (env_vol + "11111");
            end if;
          end if;

          -- envelope shape control.
          if (reg(13)(3) = '0') then
            if (env_inc = '0') then -- down
              if is_bot_p1 then env_hold <= '1'; end if;
            else
              if is_top then env_hold <= '1'; end if;
            end if;
          else
            if (reg(13)(0) = '1') then -- hold = 1
              if (env_inc = '0') then -- down
                if (reg(13)(1) = '1') then -- alt
                  if is_bot    then env_hold <= '1'; end if;
                else
                  if is_bot_p1 then env_hold <= '1'; end if;
                end if;
              else
                if (reg(13)(1) = '1') then -- alt
                  if is_top    then env_hold <= '1'; end if;
                else
                  if is_top_m1 then env_hold <= '1'; end if;
                end if;
              end if;

            elsif (reg(13)(1) = '1') then -- alternate
              if (env_inc = '0') then -- down
                if is_bot_p1 then env_hold <= '1'; end if;
                if is_bot    then env_hold <= '0'; env_inc <= '1'; end if;
              else
                if is_top_m1 then env_hold <= '1'; end if;
                if is_top    then env_hold <= '0'; env_inc <= '0'; end if;
              end if;
            end if;

          end if;
        end if;
      end if;
    end if;
  end process;

  p_chan_mixer           : process(cnt_div, reg, tone_gen_op)
  begin
    tone_ena_l  <= '1'; tone_src <= '1';
    noise_ena_l <= '1'; chan_vol <= "00000";
    case cnt_div(1 downto 0) is
      when "00" =>
        tone_ena_l  <= reg(7)(0); tone_src <= tone_gen_op(1); chan_vol <=  reg(8)(4 downto 0);
        noise_ena_l <= reg(7)(3);
      when "01" =>
        tone_ena_l  <= reg(7)(1); tone_src <= tone_gen_op(2); chan_vol <=  reg(9)(4 downto 0);
        noise_ena_l <= reg(7)(4);
      when "10" =>
        tone_ena_l  <= reg(7)(2); tone_src <= tone_gen_op(3); chan_vol <= reg(10)(4 downto 0);
        noise_ena_l <= reg(7)(5);
      when "11" => null; -- tone gen outputs become valid on this clock
      when others => null;
    end case;
  end process;

  p_op_mixer             : process
    variable chan_mixed : std_logic;
    variable chan_amp : std_logic_vector(4 downto 0);
  begin
    wait until rising_edge(CLK);
    if (ENA = '1') then

      chan_mixed := (tone_ena_l or tone_src) and (noise_ena_l or noise_gen_op);

      chan_amp := (others => '0');
      if (chan_mixed = '1') then
        if (chan_vol(4) = '0') then
          if (chan_vol(3 downto 0) = "0000") then -- nothing is easy ! make sure quiet is quiet
            chan_amp := "00000";
          else
            chan_amp := chan_vol(3 downto 0) & '1'; -- make sure level 31 (env) = level 15 (tone)
          end if;
        else
          chan_amp := env_vol(4 downto 0);
        end if;
      end if;

      dac_amp <= x"00";
      case chan_amp is
        when "11111" => dac_amp <= x"FF";
        when "11110" => dac_amp <= x"D9";
        when "11101" => dac_amp <= x"BA";
        when "11100" => dac_amp <= x"9F";
        when "11011" => dac_amp <= x"88";
        when "11010" => dac_amp <= x"74";
        when "11001" => dac_amp <= x"63";
        when "11000" => dac_amp <= x"54";
        when "10111" => dac_amp <= x"48";
        when "10110" => dac_amp <= x"3D";
        when "10101" => dac_amp <= x"34";
        when "10100" => dac_amp <= x"2C";
        when "10011" => dac_amp <= x"25";
        when "10010" => dac_amp <= x"1F";
        when "10001" => dac_amp <= x"1A";
        when "10000" => dac_amp <= x"16";
        when "01111" => dac_amp <= x"13";
        when "01110" => dac_amp <= x"10";
        when "01101" => dac_amp <= x"0D";
        when "01100" => dac_amp <= x"0B";
        when "01011" => dac_amp <= x"09";
        when "01010" => dac_amp <= x"08";
        when "01001" => dac_amp <= x"07";
        when "01000" => dac_amp <= x"06";
        when "00111" => dac_amp <= x"05";
        when "00110" => dac_amp <= x"04";
        when "00101" => dac_amp <= x"03";
        when "00100" => dac_amp <= x"03";
        when "00011" => dac_amp <= x"02";
        when "00010" => dac_amp <= x"02";
        when "00001" => dac_amp <= x"01";
        when "00000" => dac_amp <= x"00";
        when others => null;
      end case;

      if (cnt_div(1 downto 0) = "10") then
        audio_mix   <= (others => '0');
        audio_final <= audio_mix;
      else
        audio_mix   <= audio_mix + ("00" & dac_amp);
      end if;

      if (RESET_L = '0') then
        O_AUDIO(7 downto 0) <= "00000000";
      else
        if (audio_final(9) = '0') then
          O_AUDIO(7 downto 0) <= audio_final(8 downto 1);
        else -- clip
          O_AUDIO(7 downto 0) <= x"FF";
        end if;
      end if;
    end if;
  end process;

  p_io_ports             : process(reg)
  begin
    O_IOA <= reg(14);

    O_IOA_OE_L <= not reg(7)(6);
    O_IOB <= reg(15);
    O_IOB_OE_L <= not reg(7)(7);
  end process;

  p_io_ports_inreg       : process
  begin
    wait until rising_edge(CLK);
    ioa_inreg <= I_IOA;
    iob_inreg <= I_IOB;
  end process;
end architecture RTL;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -