我正在尝试使用 100khz 时钟和 0.6 毫秒到 2.4 毫秒的 PWM 创建一个 PWM 发生器,但我一直坚持在 vhdl 中实现它我一直在尝试使用状态机来做到这一点,但它变得更加复杂比它应该的。
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity PWM is
Port ( clk : in STD_LOGIC;
reset : in STD_LOGIC;
pwm_out : out STD_LOGIC;
PWM_CONST : STD_LOGIC_VECTOR(2 downto 0));
end PWM;
architecture Behavioral of PWM is
type State_type is (LOW,HIGH,Counting); --States
signal Sreg, Snext : State_type; --Curent state and next state
signal t20ms,t100ms,t_6ms,t_825ms,t1_05ms,t1_275ms,t1_5ms,t1_725ms,t1_95ms,t2_175ms,t2_4ms: STD_LOGIC;
signal twenty : STD_LOGIC;
signal count_flag : STD_LOGIC;
begin
-------------------------Clock Dividers for timing---------------------------------------
process(clk,reset)
variable toggle_20ms,toggle_1666hz,toggle_1212hz,toggle_952hz,toggle_785hz,toggle_666hz,toggle_579hz,toggle_512hz,toggle_460hz,toggle_416hz : STD_LOGIC :='0';
variable counter_20ms : integer range 0 to 999;
variable counter_1666hz : integer range 0 to 29;
variable counter_1212hz : integer range 0 to 40;
variable counter_952hz : integer range 0 to 51;
variable counter_785hz : integer range 0 to 63;
variable counter_666hz : integer range 0 to 74;
variable counter_579hz : integer range 0 to 85;
variable counter_512hz : integer range 0 to 96;
variable counter_460hz : integer range 0 to 107;
variable counter_416hz : integer range 0 to 119;
begin
if reset = '1' then
t_6ms<='0';
t_825ms<='0';
t1_05ms<='0';
t1_275ms<='0';
t1_5ms<='0';
t1_725ms<='0';
t1_95ms<='0';
t2_175ms<='0';
t2_4ms<='0';
twenty<='0';
else
if(clk'event and clk = '1') then
counter_20ms := counter_20ms+1;
counter_1666hz := counter_1666hz+1;
counter_1212hz := counter_1212hz+1;
counter_952hz := counter_952hz+1;
counter_785hz := counter_785hz+1;
counter_666hz := counter_666hz+1;
counter_579hz := counter_579hz+1;
counter_512hz := counter_512hz+1;
counter_460hz := counter_460hz+1;
counter_416hz := counter_416hz+1;
counter_20ms := counter_20ms+1;
if (counter_1666hz = 29) then
toggle_1666hz := not toggle_1666hz;
counter_1666hz := 0;
end if;
if (counter_1212hz = 40) then
toggle_1212hz := not toggle_1212hz;
counter_1212hz := 0;
end if;
if (counter_952hz = 51) then
toggle_952hz := not toggle_952hz ;
counter_952hz := 0;
end if;
if (counter_785hz = 63) then
toggle_785hz := not toggle_785hz;
counter_785hz := 0;
end if;
if (counter_666hz = 74) then
toggle_666hz := not toggle_666hz;
counter_666hz := 0;
end if;
if (counter_579hz = 85) then
toggle_579hz := not toggle_579hz;
counter_579hz := 0;
end if;
if (counter_512hz = 96) then
toggle_512hz := not toggle_512hz;
counter_512hz := 0;
end if;
if (counter_460hz = 107) then
toggle_460hz := not toggle_460hz;
counter_460hz := 0;
end if;
if (counter_416hz = 119) then
toggle_416hz := not toggle_416hz;
counter_416hz := 0;
end if;
if (counter_20ms = 999) then
toggle_20ms := not toggle_20ms;
counter_20ms := 0;
end if;
t_6ms<=toggle_1666hz;
t_825ms<=toggle_1212hz;
t1_05ms<=toggle_952hz;
t1_275ms<=toggle_785hz;
t1_5ms<=toggle_666hz;
t1_725ms<=toggle_579hz;
t1_95ms<=toggle_512hz;
t2_175ms<=toggle_460hz;
t2_4ms<=toggle_416hz;
twenty<=toggle_20ms;
end if;
end if;
end process;
-------------------------Next State Logic----------------------------------
process(Sreg,reset,PWM_CONST)
begin
case Sreg is
when LOW => if (rising_edge(twenty)) then Snext <= HIGH;
else Snext <= LOW;
end if;
when HIGH => if reset = '1' then Snext <= LOW;
else Snext <= Counting;
end if;
when Counting => if count_flag = '1' then Snext <= Counting;
else Snext <= LOW;
end if;
end case;
end process;
-----------------------Update State----------------------------------------
process(clk)
begin
if (clk'event and clk='1') then
Sreg <= Snext;
end if;
end process;
------------------------Count_flag---------------------------------------------
process(clk,PWM_CONST)
begin
case PWM_CONST is
when "000"=> t_6ms <= count_flag;
when "001"=> t_825ms <= count_flag;
when "010"=> t1_05ms <= count_flag;
when "011"=> t1_275ms <= count_flag;
when "100"=> t1_5ms <= count_flag;
when "101"=> t1_725ms <= count_flag;
when "110"=> t1_95ms <= count_flag;
when "111"=> t2_175ms <= count_flag;
when others => t2_4ms <= count_flag;
end case;
end process;
----------------------Output Logic-----------------------------------------
with Sreg select -- output logic based on state only
pwm_out <= '1' when HIGH | Counting,
'0' when LOW,
'0' when others;
---------------------------------------------------------------------------
end Behavioral;
<code>
尝试合成时出现错误的同步错误