Für ein 16Bit/48kHz PWM wird ein Takt von 2^16*48kHz=3.146 GHz benötigt. Dieser kann noch halbiert werden, da bei der steigenden und fallenden Flanke der PWM-Zähler hochgezählt werden kann.
Auf unserem Board DE0-Nano stehen uns lediglich 50 MHz zur Verfügung. Diese können mit der PLL auf ca. 500MHz hochgetaktet werden. Wir müssen also bei der Bitbreite oder Abtastfrequenz des PWM sparen. z.B: 14Bit/24KHz: 2^14*24kHz/2=196.6MHz
Um die Funktionsweise des PWM zu testen haben wir uns vorerst auf ein 8Bit PWM beschränkt. In folgenden Zeitdiagrammen ist die Funktionsweise deutlich zu sehen:
Bei jedem Nulldurchgang des Zählers T wird der am Eingang X anliegende Weit ins Register X1 gespeichert und der Ausgang Y auf 1 gesetzt (ausser X=0, dann bleibt der Ausgang 0). Danach wird T hochgezählt, bis der Wert von X1 erreicht ist und Y wieder auf 0 gesetzt wird. So ist es nun möglich, ein Rechtecksignal Y zu generieren, dessen Pulsbreite über den digitalen Wert X gesteuert werden kann.
// // 8 Bit PWM // // Clock > 2^8 * srate / 2 // z.B. @ 48 kHz: 6.1 MHz // module PWM_8 (SYS_CLK, X, Y, X1, T); // input SYS_CLK; input [7:0] X; // output Y; output [7:0] X1; output [7:0] T; // wire [7:0] X; reg [7:0] X1; reg Y; reg [7:0] T; initial begin Y <= 0; T <= 8'h00; X1 <= 8'h00; end // always @(SYS_CLK) does not work, why? always @(posedge SYS_CLK) begin if (T==0) begin X1 <= X; if(X1 != 0) Y <= 1; end else if (T==X1) begin Y <= 0; end T <= T + 1; end endmodule
Quartus Projekt: fpga_synth.zip
Hier, was ich alles versucht habe, und die entsprechenden Fehlermeldungen:
// always @(SYS_CLK) does not work, does not trigger, why?
// always @(posedge SYS_CLK or negedge SYS_CLK): Error (10239): Verilog HDL Always Construct error at PWM_8.v(35): event control cannot test for both positive and negative edges of variable “SYS_CLK”
// assign NEG_CLK=~SYS_CLK;
// always @(posedge SYS_CLK or posedge NEG_CLK): Error (10200): Verilog HDL Conditional Statement error at PWM_8.v(36): cannot match operand(s) in the condition to the corresponding edges in the enclosing event control of the always construct
“if your library supports dual edge FFs then its synthesizable else it
will throw an error. AFAIK there are no such libraries supported at
this time except in some cplds.”
Seen at: http://www.rhinocerus.net/forum/lang-verilog/168701-use-both-posedge-clk-negedge-clock.html
//
// 8 Bit PWM testbench for ModelSim
//
module PWM_8_tb ();
reg SYS_CLK;
reg [7:0] X;
wire [7:0] T;
wire Y;
PWM_8 i1 (
.SYS_CLK(SYS_CLK),
.X(X),
.T(T),
.Y(Y)
);
initial
begin
SYS_CLK=0;
X=0;
$display(“init done”);
end
always
begin
repeat (256) begin
#5 SYS_CLK=1;
#5 SYS_CLK=0;
end
X = X +1;
end
endmodule