There is a scaling issue since the DSM produce a bitstream that correspond to half the input amplitude. The output never reaches full range (flat-line high or low ds-stream). This might be ok for some use case, but for a test bench model of an ADC device with a 2nd order modulator, full range capability is an improvment.
Modified code is given here:
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all;
entity dac_dsm is generic (nbits : integer := 16); port (din : in signed(nbits-1 downto 0); dout : out std_logic; clk : in std_logic; clk_ena : in std_logic := '1'; n_rst : in std_logic := '1'); end dac_dsm;
architecture dsm of dac_dsm is signal del1, del2, d_q : signed(nbits+2 downto 0) := (others=>'0'); constant c1 : signed(nbits+2 downto 0) := to_signed( 1, nbits+3); constant c_1 : signed(nbits+2 downto 0) := to_signed(-1, nbits+3); begin
process (clk, n_rst) variable v1, v2 : signed(nbits+3 downto 0):=(others=>'0'); --(extra bit) -- function clip(constant i : signed(nbits+3 downto 0)) return signed is -- A limiter fixes full range wrap issue variable v : signed(nbits+2 downto 0); begin if i(i'left downto i'left-1)=b"01" then v:=(others=>'1'); v(v'left):='0'; elsif i(i'left downto i'left-1)=b"10" then v:=(others=>'0'); v(v'left):='1'; else v:=i(v'range); end if; return v; end function; -- begin if n_rst='0' then del1 <= (others=>'0'); del2 <= (others=>'0'); dout <= '0'; elsif rising_edge(clk) then if clk_ena='1' then v1 := resize(din,v1'length) - d_q + del1; v2 := v1/2 - d_q + del2; -- /2 is the prev.proposed stability mod. if v2 > 0 then d_q <= shift_left(c1, nbits-1); -- scaling fix dout <= '1'; else d_q <= shift_left(c_1, nbits-1); -- scaling fix dout <= '0'; end if; del1<=clip(v1); -- avoid wrapping del2<=clip(v2); end if; end if; end process;
end dac_dsm;
You've got some errors here and thus it won't compile, can you provide the code you used?
You've got some errors here and thus it won't compile, can you provide the code you used?