library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; USE work.user_pkg.all; -- ************************************************************************************************************* -- erzeugung eines pwm-signals zur h-brückenansteuerung mit(vor der synthese) wählbarer auflösung. -- bausteine: xilinx xc9572, xc9536 -- die pwm-daten werden unabhängig vom zustand des pwm-generators seriell eingeschrieben und erst -- nach beendigung des laufenden pwm-zyklus !und! beendigung der seriellen datenübertragung in den -- pwm-generator übernommen, so dass sich das tastverhältnis des pwm-signals jitterfrei ändern lässt. -- das programm wurde auf grundlage der atmel appnote DOC2324.PDF erstellt, wobei die datei 'user_pkg_inc_dec.vhd' -- unverändert übernommen wurde und bei der synthese eingebunden sein muß. -- da schieberegister und pwm-generator unabhängig voneinander arbeiten, müssen folgende signale, wie unten -- angegeben, verbunden werden(xilix-cpld) -- shift-clock -> gck2 -- clock -> gck1 -- reset -> gsr -- die übrigen verbindungen können frei gewählt werden entity pwm2 is Port ( --daten und steuersignale des schieberegisters shift_clock, -- schiebetakt, datenübernahme mit positiver flanke shift_dat, -- die seriellen daten shift_select : in STD_LOGIC; -- bausteinauswahl, '0'-aktiv --globaler takt und reset, motor links-rechts clock,reset,cw_ccw : in STD_LOGIC; --ansteuersignale der halbbrücken-gate-treiber pwm_rechts,pwm_links : out STD_LOGIC); end pwm2; architecture Behavioral of pwm2 is constant schieberegister_laenge : integer :=16; constant schieberegister_null : std_logic_vector(schieberegister_laenge-1 downto 0) :="0000000000000000"; constant pwm_aufloesung : integer :=11; constant pwm_max : std_logic_vector(pwm_aufloesung-1 downto 0) :="11111111111"; constant pwm_min : std_logic_vector(pwm_aufloesung-1 downto 0) :="00000000000"; signal schieberegister_int : std_logic_vector(schieberegister_laenge-1 downto 0); SIGNAL cnt_out_int : std_logic_vector(pwm_aufloesung-1 downto 0); SIGNAL pwm_int, rco_int : STD_LOGIC; -- diesen programmteil aktivieren, falls 'clock' heruntergeteilt werden soll -- in diesem fall muß 'clock' in allen prozessen, die an der erzeugung des pwm-signals beteiligt sind, durch -- 'pwm_clock' ersetzt werden --signal vorteiler : std_logic_vector(1 downto 0); --signal pwm_takt : std_logic; --process(clock,reset) --begin -- if(reset='1')then -- vorteiler<="00"; -- pwm_takt<= '0'; -- elsif (clock='1' and clock'event)then -- vorteiler <= vorteiler + 1; -- if(vorteiler = x"1")then -- pwm_takt <= not(pwm_takt); -- vorteiler<= "00"; -- end if; -- end if; --end process; begin -- schieberegister process (shift_clock, reset, shift_select) begin if (reset ='1') then schieberegister_int <= schieberegister_null; elsif (shift_clock = '1' and shift_clock'event) then if shift_select = '0' then schieberegister_int <= shift_dat & schieberegister_int(schieberegister_laenge-1 downto 1) ; end if; end if; end process; -- 8 BIT UPDN COUNTER. COUNTS UP OR DOWN BASED ON THE PWM_INT SIGNAL AND GENERATES -- TERMINAL COUNT WHENEVER COUNTER REACHES THE MAXIMUM VALUE OR WHEN IT TRANSISTS -- THROUGH ZERO. THE TERMINAL COUNT WILL BE USED AS INTERRUPT TO AVR FOR GENERATING -- THE LOAD SIGNAL. -- INC and DEC are the two functions which are used for up and down counting. They are defined in sepearate user_pakge library PROCESS (clock, rco_int,schieberegister_int, shift_select) BEGIN if rco_int ='1' then if shift_select = '1' then --(neuen)pwm-wert nur bei inaktivem chip_select in den zähler übernehmen: aus --dem 16bit register werden nur die unteren bits, die der pwm-auflösung entsprechen, --in den zähler geschrieben cnt_out_int <= schieberegister_int(pwm_aufloesung-1 downto 0); end if; ELSIF rising_edge(clock) THEN IF (rco_int = '0' and pwm_int ='1' and cnt_out_int < pwm_max) THEN cnt_out_int <= INC(cnt_out_int); ELSE IF (rco_int ='0' and pwm_int ='0' and cnt_out_int > pwm_min) THEN cnt_out_int <= DEC(cnt_out_int); END IF; END IF; END IF; END PROCESS; -- Logic to generate RCO signal PROCESS(cnt_out_int, rco_int, clock,reset) BEGIN IF (reset ='1') THEN rco_int <='1'; ELSIF rising_edge(clock) THEN IF ((cnt_out_int = pwm_max) or (cnt_out_int = pwm_min)) THEN rco_int <= '1'; ELSE rco_int <='0'; END IF; END IF; END PROCESS; -- TOGGLE FLIP FLOP TO GENERATE THE PWM OUTPUT. PROCESS (rco_int,reset) BEGIN IF (reset = '1') THEN pwm_int <='0'; ELSIF rising_edge(rco_int) THEN pwm_int <= NOT(pwm_int); ELSE pwm_int <= pwm_int; END IF; END PROCESS; pwm_rechts <= pwm_int when (cw_ccw = '1') else '0'; pwm_links <= pwm_int when (cw_ccw = '0') else '0'; end Behavioral;