eengr
Member level 4
I am working on a VHDL code to generate PWM outputs
For now I would like to generate 50% duty cycle 50kHz waveforms
There are 6 PWM outputs
Each output needs to be 60 degrees out of phase with the previous one (Full cycle is 360 degrees)
So for 50MHz clock input signal, I am using counters for each individual waveform. The counters are incremented by 1 with each rising edge of clock
On time scale it should be something like:
So, when counter0 reaches (1000/2 = 500) then PWM(0) goes HIGH
When counter 1 reaches [(1000/6) + (1000/2)] = 666.666 = I used 666 in my code, PWM(1) goes HIGH
And so on...
I used the following VHDL code:
I then used TestBench on ISIM to simulate the code and got the waveforms as below:
The problem I have is that: For the code that I am using I could only use whole number (integers) like 666 (0X29A) instead of 666.666 (or the answer of [(1000/6) + (1000/2)]
This consequently results in slightly different time difference between the waveforms from what they should have been
This could also be seen for the signals:
brick3, brick4, … , brick12 (in my VHDL code)
I am a beginner in VHDL and don’t know the best way to implement this. What is the recommended way / syntax to assign an answer of a function (like [(1000/6) + (1000/2)]) to a signal (say brick3)? Any help would be greatly appreciated
For now I would like to generate 50% duty cycle 50kHz waveforms
There are 6 PWM outputs
Each output needs to be 60 degrees out of phase with the previous one (Full cycle is 360 degrees)
So for 50MHz clock input signal, I am using counters for each individual waveform. The counters are incremented by 1 with each rising edge of clock
On time scale it should be something like:
So, when counter0 reaches (1000/2 = 500) then PWM(0) goes HIGH
When counter 1 reaches [(1000/6) + (1000/2)] = 666.666 = I used 666 in my code, PWM(1) goes HIGH
And so on...
I used the following VHDL 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 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.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 ( FPGA_OSC : in STD_LOGIC; PWM_OUT : out STD_LOGIC_VECTOR (5 downto 0)); end pwm; architecture pwm_arch of pwm is signal pwm_sig : STD_LOGIC_VECTOR (5 downto 0) := (others => '0'); signal counter0 : STD_LOGIC_VECTOR (11 downto 0) := (others => '0'); signal counter1 : STD_LOGIC_VECTOR (11 downto 0) := (others => '0'); signal counter2 : STD_LOGIC_VECTOR (11 downto 0) := (others => '0'); signal counter3 : STD_LOGIC_VECTOR (11 downto 0) := (others => '0'); signal counter4 : STD_LOGIC_VECTOR (11 downto 0) := (others => '0'); signal counter5 : STD_LOGIC_VECTOR (11 downto 0) := (others => '0'); signal brick1: STD_LOGIC_VECTOR (11 downto 0); signal brick2: STD_LOGIC_VECTOR (11 downto 0); signal brick3: STD_LOGIC_VECTOR (11 downto 0); signal brick4: STD_LOGIC_VECTOR (11 downto 0); signal brick5: STD_LOGIC_VECTOR (11 downto 0); signal brick6: STD_LOGIC_VECTOR (11 downto 0); signal brick7: STD_LOGIC_VECTOR (11 downto 0); signal brick8: STD_LOGIC_VECTOR (11 downto 0); signal brick9: STD_LOGIC_VECTOR (11 downto 0); signal brick10: STD_LOGIC_VECTOR (11 downto 0); signal brick11: STD_LOGIC_VECTOR (11 downto 0); signal brick12: STD_LOGIC_VECTOR (11 downto 0); signal brick_s2: STD_LOGIC_VECTOR (11 downto 0); signal brick_s3: STD_LOGIC_VECTOR (11 downto 0); signal brick_s4: STD_LOGIC_VECTOR (11 downto 0); signal brick_s5: STD_LOGIC_VECTOR (11 downto 0); signal brick_s6: STD_LOGIC_VECTOR (11 downto 0); -- constant brick3: STD_LOGIC_VECTOR (11 downto 0) := X"0502"; -- Input port 0 - 8 bits begin brick1 <= X"1F4"; -- 500 brick2 <= brick1 + brick1; -- 1000 brick3 <= X"29A"; -- 666 brick4 <= brick3 + brick1; -- 1166 brick5 <= X"340"; -- 832 brick6 <= brick5 + brick1; brick7 <= X"3E6"; --998 brick8 <= brick7 + brick1; brick9 <= X"48C"; --1164 brick10 <= brick9 + brick1; brick11 <= X"532"; -- 1330 brick12 <= brick11 + brick1; brick_s2 <= brick3 - brick1; brick_s3 <= brick5 - brick1; brick_s4 <= brick7 - brick1; brick_s5 <= brick9 - brick1; brick_s6 <= brick11 - brick1; process (FPGA_OSC) begin if (rising_edge (FPGA_OSC)) then if (counter0 < brick1) then -- 500 is 1F4 pwm_sig(0) <= '0'; counter0 <= counter0 + 1; elsif (counter0 >= brick1 and counter0 < brick2) then -- 1000 is 3E8 pwm_sig(0) <= '1'; counter0 <= counter0 + 1; else counter0 <= (others => '0'); end if; -- *************************************************************** if (counter1 < brick3) then -- 500 is 1F4 pwm_sig(1) <= '0'; counter1 <= counter1 + 1; elsif (counter1 >= brick3 and counter1 < brick4) then -- 1000 is 3E8 pwm_sig(1) <= '1'; counter1 <= counter1 + 1; else counter1 <= brick_s2; end if; -- *************************************************************** if (counter2 < brick5) then -- 500 is 1F4 pwm_sig(2) <= '0'; counter2 <= counter2 + 1; elsif (counter2 >= brick5 and counter2 < brick6) then -- 1000 is 3E8 pwm_sig(2) <= '1'; counter2 <= counter2 + 1; else counter2 <= brick_s3; end if; -- *************************************************************** if (counter3 < brick7) then -- 500 is 1F4 pwm_sig(3) <= '0'; counter3 <= counter3 + 1; elsif (counter3 >= brick7 and counter3 < brick8) then -- 1000 is 3E8 pwm_sig(3) <= '1'; counter3 <= counter3 + 1; else counter3 <= brick_s4; end if; -- *************************************************************** if (counter4 < brick9) then -- 500 is 1F4 pwm_sig(4) <= '0'; counter4 <= counter4 + 1; elsif (counter4 >= brick9 and counter4 < brick10) then -- 1000 is 3E8 pwm_sig(4) <= '1'; counter4 <= counter4 + 1; else counter4 <= brick_s5; end if; -- *************************************************************** if (counter5 < brick11) then -- 500 is 1F4 pwm_sig(5) <= '0'; counter5 <= counter5 + 1; elsif (counter5 >= brick11 and counter5 < brick12) then -- 1000 is 3E8 pwm_sig(5) <= '1'; counter5 <= counter5 + 1; else counter5 <= brick_s6; end if; -- *************************************************************** end if; PWM_OUT(0) <= pwm_sig(0); PWM_OUT(1) <= pwm_sig(1); PWM_OUT(2) <= pwm_sig(2); PWM_OUT(3) <= pwm_sig(3); PWM_OUT(4) <= pwm_sig(4); PWM_OUT(5) <= pwm_sig(5); end process; end pwm_arch;
I then used TestBench on ISIM to simulate the code and got the waveforms as below:
The problem I have is that: For the code that I am using I could only use whole number (integers) like 666 (0X29A) instead of 666.666 (or the answer of [(1000/6) + (1000/2)]
This consequently results in slightly different time difference between the waveforms from what they should have been
This could also be seen for the signals:
brick3, brick4, … , brick12 (in my VHDL code)
I am a beginner in VHDL and don’t know the best way to implement this. What is the recommended way / syntax to assign an answer of a function (like [(1000/6) + (1000/2)]) to a signal (say brick3)? Any help would be greatly appreciated