zermelo
Junior Member level 3
- Joined
- May 24, 2013
- Messages
- 25
- Helped
- 0
- Reputation
- 0
- Reaction score
- 0
- Trophy points
- 1,281
- Activity points
- 1,543
Hi,
I am trying to build my own linear interpolator (that's it , to implement : y(x) = y1+ [(y2-y1)/(x2-x1)]*(x - x1)). To do that , I designed a simple pipelined stage computing the difference terms, and other stages computing the product, division and final sum.
The problem is that s_x_x1 term (see code above) computes well, while as the s_y2_y1 and the s_x2_x1 remain stuck at zero (of course the operands are not equal in any case).
Here is the code:
Found this error while simulating with Modelsim a larger component which instantiates the interpolator. The instantation of this component is:
The mapped signals/constants are declared in the architecture of the top component as:
The signals i_x1, i_x2 , y_1 & y_2 take constant values (as required for the interpolator) . Any hint of what could be going on here?
Thanks in advance. In the mean time I'll try to simulate the interpolator isolated with different values.
Note:
I found the "divide" function somewhere on the internet, and seemed to work fine at least in behavioral simulation. That's the only thing I use of the work.skp_math.pkg. It's defined for unsigned only, and , as I want the interpolator to be as general as possible (and avoid instantiation of Xilinx/Altera IPs) I had to do that nasty conversion (hope it works).
Here is the code for the function:
I am trying to build my own linear interpolator (that's it , to implement : y(x) = y1+ [(y2-y1)/(x2-x1)]*(x - x1)). To do that , I designed a simple pipelined stage computing the difference terms, and other stages computing the product, division and final sum.
The problem is that s_x_x1 term (see code above) computes well, while as the s_y2_y1 and the s_x2_x1 remain stuck at zero (of course the operands are not equal in any case).
Here is the code:
Code VHDL - [expand] 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 Library ieee; library work; use ieee.std_logic_1164.all ; use ieee.numeric_std.all; use work.skp_math_pkg.all; Entity lin_itpl is Generic (G_WORD_SIZE : integer := 8); Port (-- Reset & clock/clock en i_rst : in std_logic; i_clk : in std_logic; i_conv : in std_logic; -- Inputs i_x : in signed(G_WORD_SIZE - 1 downto 0); i_x1 : in signed(G_WORD_SIZE - 1 downto 0); i_x2 : in signed(G_WORD_SIZE - 1 downto 0); i_y1 : in signed(G_WORD_SIZE - 1 downto 0); i_y2 : in signed(G_WORD_SIZE - 1 downto 0); -- Outputs o_data_rdy : out std_logic; o_data : out signed(G_WORD_SIZE - 1 downto 0)); end lin_itpl; Architecture rtl of lin_itpl is signal s_sgn_quot : std_logic; -- pipe ctrl signal s_p1_trg : std_logic; signal s_p2_trg : std_logic; signal s_p3_trg : std_logic; signal s_p4_trg : std_logic; -- Arithmetic signal s_x_x1 : signed(G_WORD_SIZE downto 0); -- Sign bit! signal s_x2_x1: signed(G_WORD_SIZE downto 0); signal s_y2_y1: signed(G_WORD_SIZE downto 0); signal s_quot : signed(G_WORD_SIZE downto 0); -- Unsigned division of operands of the same size , converted to signed (+1 bit!) signal s_prod : signed(G_WORD_SIZE downto 0); signal s_sum : signed(G_WORD_SIZE - 1 downto 0); begin -- Quotient sign (operands in 2's comp) s_sgn_quot <= s_y2_y1(s_y2_y1'left) xor s_x2_x1(s_x2_x1'left); P_PIPE_ITPL : process(i_clk) begin if (i_clk'event and i_clk = '1') then if (i_rst = '1') then -- pipe ctrl s_p1_trg <= '0'; s_p2_trg <= '0'; s_p3_trg <= '0'; s_p4_trg <= '0'; -- Arithmetic s_x_x1 <= (others => '0'); s_x2_x1 <= (others => '0'); s_y2_y1 <= (others => '0'); s_sum <= (others => '0'); s_prod <= (others => '0'); else -- Pipeline triggers are pulsed s_p1_trg <= '0'; s_p2_trg <= '0'; s_p3_trg <= '0'; s_p4_trg <= '0'; -- Difference terms are independent: compute in parallel if (i_conv = '1') then s_x_x1 <= resize(i_x, s_x_x1'length) - resize(i_x1,s_x_x1'length); s_x2_x1 <= resize(i_x2,s_x2_x1'length) - resize(i_x1,s_x2_x1'length); s_y2_y1 <= resize(i_y2,s_y2_y1'length) - resize(i_y1,s_y2_y1'length); s_p1_trg <= '1'; end if; -- Unsigned division of operands of the same size , converted to signed -- (include sign bit and to_std_logic_vector first!!) if (s_p1_trg = '1') then s_quot <= resize(signed(std_logic_vector(s_sgn_quot&f_divide(unsigned(s_y2_y1),unsigned(s_x2_x1)))),s_quot'length); s_p2_trg <= '1'; end if; -- Truncated product term if (s_p2_trg = '1') then s_prod <= resize(s_quot*s_x_x1,s_prod'length); s_p3_trg <= '1'; end if; -- Truncated product term if (s_p3_trg = '1') then s_sum <= resize(s_prod + i_y1,s_sum'length) ; s_p4_trg <= '1'; end if; end if; end if; end process P_PIPE_ITPL; -- Outputs o_data_rdy <= s_p4_trg; o_data <= s_sum; end rtl;
Found this error while simulating with Modelsim a larger component which instantiates the interpolator. The instantation of this component is:
Code VHDL - [expand] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 U_ITPL_TTL_HIGH: lin_itpl Generic map (G_WORD_SIZE => 12) Port map (-- Reset & clock/clock en i_rst => i_rst, i_clk => i_clk, i_conv => s_tx_cr_p_zc, -- Inputs i_x => signed(s_tx_tmr), i_x1 => to_signed(0,12), i_x2 => signed(c_tx_tmr_tc), i_y1 => signed(s_freq_hilen), i_y2 => signed(s_freq_lolen), -- Outputs o_data_rdy => s_ttl_data_hi_rdy, o_data => s_ttl_data_hi);
The mapped signals/constants are declared in the architecture of the top component as:
Code VHDL - [expand] 1 2 3 4 signal s_tx_tmr : unsigned(11 downto 0); constant c_tx_tmr_tc : unsigned(s_tx_tmr'range):=to_unsigned(1000,s_tx_tmr'length); signal s_freq_lolen : unsigned(s_tx_tmr'range); signal s_freq_hilen : unsigned(s_tx_tmr'range);
The signals i_x1, i_x2 , y_1 & y_2 take constant values (as required for the interpolator) . Any hint of what could be going on here?
Thanks in advance. In the mean time I'll try to simulate the interpolator isolated with different values.
Note:
I found the "divide" function somewhere on the internet, and seemed to work fine at least in behavioral simulation. That's the only thing I use of the work.skp_math.pkg. It's defined for unsigned only, and , as I want the interpolator to be as general as possible (and avoid instantiation of Xilinx/Altera IPs) I had to do that nasty conversion (hope it works).
Here is the code for the function:
Code VHDL - [expand] 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 function f_divide (a : unsigned ; b : unsigned ) return unsigned is variable a1 : unsigned(a'length-1 downto 0):= a; -- Divisor variable b1 : unsigned(b'length-1 downto 0):= b; -- Dividend variable p1 : unsigned(b'length downto 0):= (others => '0'); begin for i in 0 to b'length-1 loop p1(b'length-1 downto 1) := p1(b'length-2 downto 0); p1(0) := a1(a'length-1); a1(a'length-1 downto 1) := a1(a'length-2 downto 0); p1 := p1-b1; if(p1(b'length-1) ='1') then a1(0) :='0'; p1 := p1+b1; else a1(0) :='1'; end if; end loop; return a1; end f_divide; end skp_math_pkg ;
Last edited by a moderator: