From 42a170534dd5885e961c9208fb615f7a7403deee Mon Sep 17 00:00:00 2001 From: Vladimir Burian Date: Thu, 19 May 2011 00:06:50 +0200 Subject: [PATCH 1/1] Added pwm_min_dump - modified sin wave This component dump pwm values relative to minimal pwm value stored in memory. In conjunction with pwm_min component can serve as modified sin wave generator. --- pwm_min_dump.vhd | 98 +++++++++++++++++++++++++++ tb/Makefile | 3 +- tb/tb_pwm_min_dump.sav | 27 ++++++++ tb/tb_pwm_min_dump.vhd | 146 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 273 insertions(+), 1 deletion(-) create mode 100644 pwm_min_dump.vhd create mode 100644 tb/tb_pwm_min_dump.sav create mode 100644 tb/tb_pwm_min_dump.vhd diff --git a/pwm_min_dump.vhd b/pwm_min_dump.vhd new file mode 100644 index 0000000..a252f10 --- /dev/null +++ b/pwm_min_dump.vhd @@ -0,0 +1,98 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +-------------------------------------------------------------------------------- + +entity pwm_min_dump is + generic ( + IRF_ADR_W : integer := 5; + BASE : integer := 0; + PWMMIN_OFF : integer := 6; + P_BASE : integer := 16; + PWM_OFF : integer := 1; + PWM_W : integer := 10); + port ( + -- Primary slave intefrace + ACK_O : out std_logic; + CLK_I : in std_logic; + RST_I : in std_logic; + STB_I : in std_logic; + -- PWM interface + PWM_DAT_O : out std_logic_vector (PWM_W-1 downto 0); + PWM_STB_O : out std_logic := '0'; + -- Shared dual-port memory + IRF_ACK_I : in std_logic; + IRF_ADR_O : out std_logic_vector (IRF_ADR_W-1 downto 0); + IRF_DAT_I : in std_logic_vector (15 downto 0); + IRF_STB_O : out std_logic); +end entity pwm_min_dump; + +-------------------------------------------------------------------------------- + +architecture behavioral of pwm_min_dump is + + type state_t is (ready, dump, done); + subtype irf_adr_t is std_logic_vector (IRF_ADR_W-1 downto 0); + + constant PWMMIN_ADR : irf_adr_t := conv_std_logic_vector(BASE+PWMMIN_OFF, IRF_ADR_W); + constant PWM_ADR : irf_adr_t := conv_std_logic_vector(P_BASE + PWM_OFF, IRF_ADR_W); + + signal state : state_t := ready; + + signal ack : std_logic := '0'; + --signal pwm_min : std_logic_vector (PWM_DAT_O'RANGE); + signal pwm_min : std_logic_vector (PWM_DAT_O'range); + signal pwm_stb : std_logic := '0'; + signal irf_adr : irf_adr_t := PWMMIN_ADR; + signal irf_we : std_logic := '0'; + +-------------------------------------------------------------------------------- + +begin + + ACK_O <= STB_I and ack; + + PWM_DAT_O <= IRF_DAT_I(pwm_min'RANGE) - pwm_min; + PWM_STB_O <= pwm_stb; + + IRF_ADR_O <= irf_adr; + IRF_STB_O <= STB_I; + + + FSM : process (CLK_I, RST_I) is + begin + if RST_I = '1' then + state <= ready; + ack <= '0'; + irf_adr <= PWMMIN_ADR; + pwm_stb <= '0'; + + elsif rising_edge(CLK_I) then + case state is + when ready => + if STB_I = '1' then + state <= dump; + irf_adr <= PWM_ADR; + end if; + + when dump => + state <= done; + ack <= '1'; + pwm_stb <= '1'; + pwm_min <= IRF_DAT_I(pwm_min'RANGE); + + when done => + pwm_stb <= '0'; + if STB_I = '0' then + state <= ready; + ack <= '0'; + irf_adr <= PWMMIN_ADR; + end if; + end case; + end if; + end process; + +end architecture behavioral; + diff --git a/tb/Makefile b/tb/Makefile index 99cabe9..c32d165 100644 --- a/tb/Makefile +++ b/tb/Makefile @@ -2,7 +2,7 @@ # bottom to up order (e.g. the top entity is the last in this list). Otherwise # it won't compile. -VHDL_MAIN = tb_pwm_min +VHDL_MAIN = tb_pwm_min_dump VHDL_ENTITIES = counter.o \ pwm.o \ wave_table.o \ @@ -16,6 +16,7 @@ VHDL_ENTITIES = counter.o \ irc_dump.o \ irc_base.o \ pwm_min.o \ + pwm_min_dump.o \ mcc.o diff --git a/tb/tb_pwm_min_dump.sav b/tb/tb_pwm_min_dump.sav new file mode 100644 index 0000000..2f457ec --- /dev/null +++ b/tb/tb_pwm_min_dump.sav @@ -0,0 +1,27 @@ +[timestart] 0 +[size] 1280 769 +[pos] -1 -1 +*-33.327084 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +@28 +clk_i +stb_i +ack_o +@24 +dbg_mem0x06[15:0] +dbg_mem0x11[15:0] +uut.pwm_min[9:0] +@200 +- +@24 +pwm_dat_o[9:0] +@28 +pwm_stb_o +@200 +- +@22 +uut.irf_dat_i[15:0] +uut.irf_adr_o[4:0] +@28 +uut.irf_stb_o +[pattern_trace] 1 +[pattern_trace] 0 diff --git a/tb/tb_pwm_min_dump.vhd b/tb/tb_pwm_min_dump.vhd new file mode 100644 index 0000000..5e64983 --- /dev/null +++ b/tb/tb_pwm_min_dump.vhd @@ -0,0 +1,146 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +entity tb_pwm_min_dump is +end tb_pwm_min_dump; + +-------------------------------------------------------------------------------- + +architecture testbench of tb_pwm_min_dump is + + constant period : time := 1 us; + constant offset : time := 0 us; + + constant IRF_ADR_W : integer := 5; + + + signal ACK_O : std_logic; + signal CLK_I : std_logic; + signal RST_I : std_logic; + signal STB_I : std_logic; + + signal IRF_ACK_I : std_logic; + signal IRF_ADR_O : std_logic_vector (IRF_ADR_W-1 downto 0); + signal IRF_DAT_I : std_logic_vector (15 downto 0); + signal IRF_DAT_O : std_logic_vector (15 downto 0); + signal IRF_STB_O : std_logic; + signal IRF_WE_O : std_logic; + + signal PWM_DAT_O : std_logic_vector (9 downto 0); + signal PWM_STB_O : std_logic; + + subtype word_t is std_logic_vector (15 downto 0); + + signal dbg_ack : std_logic := '0'; + + signal dbg_mem0x06 : word_t := (others => '0'); + signal dbg_mem0x11 : word_t := (others => '0'); + +-------------------------------------------------------------------------------- + +begin + + uut : entity work.pwm_min_dump + generic map ( + IRF_ADR_W => IRF_ADR_W, + BASE => 0, + PWMMIN_OFF => 16#06#, + P_BASE => 16#10#, + PWM_OFF => 1, + PWM_W => 10) + port map ( + ACK_O => ACK_O, + CLK_I => CLK_I, + RST_I => RST_I, + STB_I => STB_I, + PWM_DAT_O => PWM_DAT_O, + PWM_STB_O => PWM_STB_O, + IRF_ACK_I => IRF_ACK_I, + IRF_ADR_O => IRF_ADR_O, + IRF_DAT_I => IRF_DAT_I, + IRF_STB_O => IRF_STB_O); + + + SYSCON_CLK : process is + begin + CLK_I <= '0'; + wait for offset; + loop + CLK_I <= '1'; + wait for period/2; + CLK_I <= '0'; + wait for period/2; + end loop; + end process; + + SYSCON_RST : process is + begin + RST_I <= '0'; + wait for offset; + wait for 0.75*period; + RST_I <= '1'; + wait for 2*period; + RST_I <= '0'; + wait; + end process; + + + DBG_MEM : process (IRF_STB_O, CLK_I) is + begin + IRF_ACK_I <= IRF_STB_O and (IRF_WE_O or dbg_ack); + + if rising_edge(CLK_I) then + dbg_ack <= IRF_STB_O; + end if; + + if rising_edge(CLK_I) and IRF_STB_O = '1' then + if IRF_WE_O = '0' then + case conv_integer(IRF_ADR_O) is + when 16#06# => IRF_DAT_I <= dbg_mem0x06; + when 16#11# => IRF_DAT_I <= dbg_mem0x11; + when others => + IRF_DAT_I <= (others => 'X'); + report "Reading from non-readable register" severity warning; + end case; + else + case conv_integer(IRF_ADR_O) is + when others => + report "Writing to read-only registers" severity error; + end case; + end if; + end if; + end process; + +-------------------------------------------------------------------------------- + + UUT_FEED : process is + begin + IRF_DAT_O <= (others => '0'); + IRF_WE_O <= '0'; + STB_I <= '0'; + + wait for offset; + wait for 4*period; + + for i in 0 to 0 loop + dbg_mem0x06 <= conv_std_logic_vector(10, 16); + dbg_mem0x11 <= conv_std_logic_vector(45, 16); + + wait for 0.75*period; + STB_I <= '1'; + wait for 0.25*period; + wait until rising_edge(CLK_I) and ACK_O = '1'; + wait for 0.25*period; + STB_I <= '0'; + wait for 0.75*period; + + wait for 4*period; + end loop; + + wait; + end process; + +end testbench; + -- 2.39.2