logo

 

Introduction
Master clock
Générateur de fréquence
Régler le volume
PWM
Générateur de bruit
Dent de scie et triangle
Sinus
Envelope
Filtres
Interface CPU
Silicium: Volume
Silicum: DAC
LFSR Experimenter

Modulation de largeur d'impulsion (PWM)

Mettons le volume de côté pour simplifier les explications. Il pourra être rajouté sans mal à la fin de la chaîne.

Jusqu'à présent, la sortie du générateur de fréquence est carrée. C'est à dire que le rapport cyclique (temps haut/temps bas) est de 0.5 ou 50%.
Un effet qui peut être désiré en audio est la modulation de largeur d'impulsion (ou PWM pour Pulse Width Modulation), où le rapport cyclique peut être modifié afin d'obtenir des temps hauts et bas différents.

Comme il est difficile de décrire le son produit, voici un exemple de PWM sur deux notes:

On pourrait croire que la fréquence fondamentale des notes change, mais ce n'est pas du tout le cas. La variation du rapport cyclique ne modifie pas la fréquence de la note, seulement les harmoniques.

Pour créer cet effet, on pourrait ajouter un second compteur (un pour l'état bas et un pour l'état haut), mais ça compliquerait inutilement les choses.
On peut conserver toujours le même compteur, ajouter un registre contenant la valeur du rapport cyclique ("DUTY") et une simple comparaison.

PERIOD sert toujours à définir la fréquence de la note, mais d'une autre manière. Précédemment, HPERIOD représentait une demi-periode car on inversait le signal de sortie OSC. Avec une logique permettant la PWM, la valeur représente une période entière car elle servira à temporiser les deux états de OSC.
A chaque expiration du compteur CNT, OSC ne sera plus inversé, mais mis à 0.
Lorsque la valeur du compteur est égale à celle de DUTY, OSC sera mis à 1, donnant ainsi le contrôle sur le temps haut et bas à l'aide de 2 paramètres mais toujours d'un seul compteur.

soundchip

Ceux qui font de l'embarqué penseront aux timers et leurs "compare match", c'est pareil ;)

reg [2:0] CNT;
reg [2:0] DUTY;

always @(posedge MCLK)
begin
	if (CNT)
	begin
		if (CNT == DUTY)
			OSC <= 1'b1;	// Set sortie
		CNT <= CNT - 1'b1;	// Decrementer si > 0
	end
	else
	begin
		CNT <= HPERIOD;		// Reload
		OSC <= 1'b0;		// Reset sortie
	end
end

PERIOD donne la longueur d'une période, et DUTY indique où dans cette période le signal de sortie doit passer de 0 à 1.

Il est important de remarquer qu'avec ce système, la résolution du rapport cyclique dépend directement de la valeur du diviseur (PERIOD). Il est possible de mettre DUTY à une valeur plus grande que celle de PERIOD, mais cela ne produira qu'un signal constamment à 0 (car CNT ne sera jamais égal a DUTY).

Aussi, en mettant la comparaison du compteur dans la condition validée pour CNT différent de 0, on empêche d'avoir une attribution concurrente pour OSC. Si ce n'était pas le cas, en fixant DUTY à 0, OSC pourrait se faire attribuer la valeur 0 (car CNT=0) et 1 (car CNT=DUTY) en même temps, résultant en un état indéfini.
Avec le code ci-dessus, si DUTY est égal à 0, le signal de sortie OSC restera simplement à 0 au lieu de faire n'importe quoi.

soundchip

On pourra aussi faire varier DUTY:

soundchip

 

 

footer
symbol symbol symbol symbol symbol