Files
SMS_MiSTer/rtl/VM2413/sinetable.vhd
birdybro 26247dd359 Update edge detection method from VHDL 87 to VHDL 93 (#131)
Technically, `Clk’event and clk = ‘1’` can result in non-`0` triggers (e.g. `1`, `U`, `H`, `X`, `Z`, `W`, etc...), whereas `rising_edge(clk)` does not.
2022-07-07 16:00:25 +08:00

215 lines
9.2 KiB
VHDL

--
-- SineTable.vhd
--
-- Copyright (c) 2006 Mitsutaka Okazaki (brezza@pokipoki.org)
-- All rights reserved.
--
-- Redistribution and use of this source code or any derivative works, are
-- permitted provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
-- 3. Redistributions may not be sold, nor may they be used in a commercial
-- product or activity without specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
-- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-- OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-- WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-- OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--
--
--
-- modified by t.hara
--
-- ----------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_signed.all;
entity interpolate_mul is
port (
i0 : in std_logic_vector( 8 downto 0 ); -- 符号無し 9bit (整数部 0bit, 小数部 9bit)
i1 : in std_logic_vector( 11 downto 0 ); -- 符号付き12bit (整数部 8bit, 小数部 4bit)
o : out std_logic_vector( 13 downto 0 ) -- 符号付き 7bit (整数部 8bit, 小数部 6bit)
);
end interpolate_mul;
architecture rtl of interpolate_mul is
signal w_mul : std_logic_vector( 21 downto 0 ); -- 符号付き22bit (整数部 9bit, 小数部13bit)
begin
w_mul <= ('0' & i0) * i1;
o <= w_mul( 20 downto 7 ); -- MSBカットで 21bit, 小数部下位 7bitカット
end rtl;
-- ----------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all; -- conv_integer()
entity SineTable is
port (
clk : in std_logic;
clkena : in std_logic;
wf : in std_logic;
addr : in std_logic_vector( 17 downto 0 ); -- 整数部 9bit, 小数部 9bit
data : out std_logic_vector( 13 downto 0 ) -- 整数部 8bit, 小数部 6bit
);
end SineTable;
architecture rtl of sinetable is
component interpolate_mul
port (
i0 : in std_logic_vector( 8 downto 0 ); -- 符号無し 9bit (整数部 0bit, 小数部 9bit)
i1 : in std_logic_vector( 11 downto 0 ); -- 符号付き 8bit (整数部 8bit)
o : out std_logic_vector( 13 downto 0 ) -- 符号無し 7bit (整数部 8bit)
);
end component;
type sin_type is array (0 to 127) of std_logic_vector( 10 downto 0 ); -- 整数部 7bit, 小数部 4bit
constant sin_data : sin_type := (
"11111111111", "11001010000", "10101010001", "10010111100",
"10001010011", "10000000001", "01110111110", "01110000101",
"01101010101", "01100101001", "01100000011", "01011100000",
"01011000000", "01010100011", "01010001000", "01001101111",
"01001011000", "01001000010", "01000101101", "01000011010",
"01000000111", "00111110110", "00111100101", "00111010101",
"00111000110", "00110110111", "00110101001", "00110011100",
"00110001111", "00110000011", "00101110111", "00101101011",
"00101100000", "00101010110", "00101001011", "00101000001",
"00100111000", "00100101110", "00100100101", "00100011100",
"00100010100", "00100001011", "00100000011", "00011111011",
"00011110100", "00011101100", "00011100101", "00011011110",
"00011010111", "00011010001", "00011001010", "00011000100",
"00010111110", "00010111000", "00010110010", "00010101100",
"00010100111", "00010100001", "00010011100", "00010010111",
"00010010010", "00010001101", "00010001000", "00010000011",
"00001111111", "00001111010", "00001110110", "00001110010",
"00001101110", "00001101010", "00001100110", "00001100010",
"00001011110", "00001011010", "00001010111", "00001010011",
"00001010000", "00001001101", "00001001001", "00001000110",
"00001000011", "00001000000", "00000111101", "00000111011",
"00000111000", "00000110101", "00000110011", "00000110000",
"00000101110", "00000101011", "00000101001", "00000100111",
"00000100101", "00000100010", "00000100000", "00000011110",
"00000011101", "00000011011", "00000011001", "00000010111",
"00000010110", "00000010100", "00000010011", "00000010001",
"00000010000", "00000001110", "00000001101", "00000001100",
"00000001011", "00000001010", "00000001001", "00000001000",
"00000000111", "00000000110", "00000000101", "00000000100",
"00000000011", "00000000011", "00000000010", "00000000010",
"00000000001", "00000000001", "00000000000", "00000000000",
"00000000000", "00000000000", "00000000000", "00000000000"
);
signal ff_data0 : std_logic_vector( 10 downto 0 ); -- 符号ナシ整数部 7bit, 小数部 4bit
signal ff_data1 : std_logic_vector( 10 downto 0 ); -- 符号ナシ整数部 7bit, 小数部 4bit
signal w_wf : std_logic_vector( 13 downto 0 );
signal w_xor : std_logic_vector( 6 downto 0 );
signal w_addr0 : std_logic_vector( 6 downto 0 );
signal w_addr1 : std_logic_vector( 6 downto 0 );
signal w_xaddr : std_logic_vector( 6 downto 0 );
signal ff_sign : std_logic;
signal ff_wf : std_logic;
signal ff_weight : std_logic_vector( 8 downto 0 );
signal w_sub : std_logic_vector( 11 downto 0 ); -- 符号付き整数部 8bit, 小数部 4bit
signal w_mul : std_logic_vector( 13 downto 0 ); -- 符号付き整数部 8bit, 小数部 6bit
signal w_inter : std_logic_vector( 13 downto 0 );
signal ff_data : std_logic_vector( 13 downto 0 );
begin
w_xor <= (others => addr(16));
w_xaddr <= addr( 15 downto 9 ) xor w_xor;
w_addr0 <= w_xaddr;
w_addr1 <= "1111111" xor w_xor when(addr( 15 downto 9 ) = "1111111" )else -- 波形が循環する部分の対処
(addr( 15 downto 9 ) + 1) xor w_xor;
-- 波形メモリ
process( clk )
begin
if rising_edge(clk) then
if( clkena = '1' )then
ff_data0 <= sin_data( conv_integer( w_addr0 ) );
ff_data1 <= sin_data( conv_integer( w_addr1 ) );
end if;
end if;
end process;
-- 修飾情報の遅延(波形メモリの読み出し遅延にあわせる)
process( clk )
begin
if rising_edge(clk) then
if( clkena = '1' )then
ff_sign <= addr(17);
ff_wf <= wf and addr(17);
ff_weight <= addr( 8 downto 0 );
end if;
end if;
end process;
-- 補間 (※符号をまたがる場所では 0 になるから ff_sign は気にしない)
-- o = i0 * (1 - k) + i1 * w = i0 - w * i0 + w * i1 = i0 + w * (i1 - i0)
w_sub <= ('0' & ff_data1) - ('0' & ff_data0);
u_interpolate_mul: interpolate_mul
port map (
i0 => ff_weight,
i1 => w_sub,
o => w_mul
);
-- 下位 6bit (小数部)を演算精度維持のために残す
w_inter <= (ff_data0 & "00") + w_mul; -- "00" は桁あわせ
w_wf <= (others => ff_wf);
process( clk )
begin
if rising_edge(clk) then
if( clkena = '1' )then
-- 補間演算の結果をいったん FF に入れて演算遅延を吸収
ff_data <= (ff_sign & w_inter(12 downto 0)) or w_wf;
end if;
end if;
end process;
data <= ff_data;
--------------------------------------------------------------------------
-- addr X addr入力 X
-- w_addr0 X 確定 X
-- w_addr1 X 確定 X
-- ff_data0 X 確定 X
-- ff_data1 X 確定 X
-- ff_sign X 確定 X
-- ff_wf X 確定 X
-- ff_weight X 確定 X
-- w_sub X 確定 X
-- w_mul X 確定 X
-- w_inter X 確定 X
-- w_wf X 確定 X
-- ff_data X 確定 X
-- data X 確定 X
-- Operator
-- stage X 01 X 10 X 11 X 00 X
--
-- Operator は、stage = 01 のときに投入した入力値に基づく出力を得る場合に
-- stage = 11 で受け取らなければならない。
--
-- アドレス指定されてから、それに対応する値が得られるまで 2cycle の遅延
--
end rtl;