Sommaire
Le Verilog
Le Verilog est un langage conçu à l’origine pour rédiger des spécifications de circuits logiques en électronique numérique. Le langage permet de décrire le comportement de sortie par rapport à des entrées logiques. Un peu comme les logiciels de saisie de schéma électronique, le Verilog est très hiérarchique, on décrit des modules avec leurs entrées‑sorties. Que l’on assemble ensuite dans d’autres modules pour finir dans un module « top » qui décrit le composant final.
Dans le cas de TapTempo, le module « top » est déclaré comme ceci :
module taptempo #(
parameter CLK_PER_NS = 40, // 25Mhz clock (ns)
parameter TP_CYCLE = 5120, // timepulse cycle period (ns)
parameter BPM_MAX = 250 // BPM max (bpm)
)(
input clk_i,
input btn_i,
output pwm_o
);
//corps du module
endmodule
Le module possède deux entrées : l’horloge (clk_i
) et le bouton (btn_i
) ainsi qu’une sortie pwm (pwm_o
) pour l’affichage. Les paramètres seront vus comme des constantes au moment de la simulation, ils permettent de configurer les composants en fonction de la cible. Le changement de valeur des signaux se fait dans des processus qui sont déclenchés sur événement. Ces processus sont décrits au moyen du mot clef always@()
en Verilog.
Par exemple, dans le code suivant :
/* Detect rising edge*/
reg btn_old, btn_rise;
always@(posedge clk_i)
begin
btn_old <= btn_i;
if(btn_old == 0 && btn_i == 1)
btn_rise <= 1;
else
btn_rise <= 0;
end
L’événement déclencheur du process est le front montant de l’horloge clk_i
. À chaque fois qu’un front montant d’horloge se présente, le processus est exécuté de manière séquentielle.
L’opérateur <=
est l’opérateur d’affectation dit « non bloquant ». Cela signifie que la valeur ne sera effectivement appliquée qu’à la fin de l’exécution du process. Donc, la valeur du signal btn_old
ne sera pas nécessairement égale à btn_i
à la ligne du if()
comme on aurait pu instinctivement le croire.
Le langage Verilog a beaucoup de succès dans le monde du logiciel libre. En effet, il est relativement peu verbeux et ressemble au C pour de nombreux aspects. Il est par exemple possible de décrire des macros de la même manière qu’en C, il suffit de remplacer le symbole #
par ` pour créer des constantes qui seront remplacées par le préprocesseur :
/* count tap period */
`define MIN_NS 60_000_000_000
`define BTN_PER_MAX (`MIN_NS/TP_CYCLE)
`define BTN_PER_SIZE ($clog2(1 + `BTN_PER_MAX))
Le Verilog reprend également les opérateurs booléen et binaire &
, &&
, |
, ||
, etc., du C.
C’est le langage HDL le mieux pris en charge par les différents logiciels libres. Si l’on souhaite se lancer dans le domaine des FPGA et/ou des ASIC, il est préférable de commencer par lui. C’est également le langage « de sortie » de quasiment tous les générateurs de code HDL.
Architecture de TapTempo
L’outil indispensable pour commencer un projet en Verilog est… le papier et le crayon. Il est en effet indispensable d’avoir une vue d’ensemble assez claire de ce que l’on souhaite réaliser avant de se lancer dans le code.
Voici donc l’architecture générale du composant TapTempo :
Même si l’on doit revenir plusieurs fois (ce qui est le cas ici puisque les constantes ne sont pas à jour) sur ce schéma général en cours de développement, cette partie est très importante. Si elle est bien pensée, le reste coule de source.
Le composant va nécessiter quelques compteurs, mais l’horloge utilisée ici étant très rapide nous allons d’abord factoriser le comptage au moyen du module nommé timepulse
, ce module va distribuer une pulsation qui servira de base aux autres compteurs pour leur fonctionnement interne.
L’entrée utilisateur se compose d’un bouton (touche télégraphique « morse »). Les fronts montant et descendant de cette entrée n’étant pas synchronisés sur l’horloge du système nous allons devoir le faire au moyen de deux bascules en série pour éviter la métastabilité.
/* Synchronize btn_i to avoid metastability*/
reg btn_old, btn_s;
always@(posedge clk_i or posedge rst)
begin
if(rst) begin
btn_old <= 1'b0;
btn_s <= 1'b0;
end else begin
btn_old <= btn_i;
btn_s <= btn_old;
end
end
Le second problème que pose notre entrée est que l’appui sur le bouton ne génère pas des changements francs de son état. Chaque « appui et relâche » génère une série de rebonds et donc une série de 0 et de 1 avant de se stabiliser. Pour lisser le signal il va donc falloir faire passer le signal dans le bloc « antirebond » debounce
.
Le bloc percount
va ensuite se charger de mesurer le temps entre deux appuis sur le bouton. Cette période va devoir être transformée en fréquence « BPM » (Beat Per Minute) via le module per2bpm
, puis en une valeur pseudo‐analogique (PWM) grâce au module pwmgen
.
La carte cible ne possédant pas de bouton « reset », il va falloir le générer grâce au module rstgen
de manière à s’assurer de l’état de départ de notre système au démarrage.
Entrée‑sortie
La plupart des programmes TapTempo proposés jusqu’ici supposaient — en plus d’un processeur — la présence d’un clavier et d’une console texte de sortie (avec toute la pile de pilotes et de système d’exploitation associés). Ici, nous allons devoir tout définir dans le « portegramme » — dans l’industrie on va parler d’IP pour Intellectual Property, quel horrible nom.
L’idée est donc de simplifier au maximum l’entrée « clavier » et la sortie histoire de pouvoir les décrire simplement.
Pour l’entrée nous allons nous contenter d’un contact de type bouton, ou d’une touche de type télégraphe « morse » :
Comme on peut le voir dans le schéma ci‑dessus, quand la touche est appuyée, l’entrée « bouton » est mise à la masse et donne un niveau logique à 0 sur notre système. Lorsque l’on relâche le bouton, la résistance de tirage ramène le niveau de tension à Vcc pour avoir un niveau 1 sur l’entrée.
Pour la sortie, l’idée de mettre un écran complexifie énormément le système. En effet, il est nécessaire de faire une machine d’état assez complexe pour initialiser l’écran puis rafraîchir l’affichage. Il est souvent nécessaire d’ajouter un processeur « soft » rien que pour ça d’ailleurs (bon, il est vrai que le VGA n’est pas si compliqué, mais il reste plus complexe que la solution proposée ici).
Non, l’idée ici est d’utiliser les graduations de l’antique voltmètre à aiguille trouvé dans une cave et qui gradue de 0 à 300 comme on peut le voir sur la photo :
Et comme un système numérique ne sort que des 0 et des 1 sur ses broches, on va « simuler » une valeur analogique au moyen d’une modulation de largeur d’impulsion, en anglais Pulse Width Modulation — PWM. Il suffit de changer le rapport cyclique entre le temps haut et le temps bas de notre signal pour faire varier la tension moyenne qui sera vue par le voltmètre. Si on l’ajuste correctement avec une résistance en série, il est relativement facile de forcer la valeur maximale (5 V) à 250.
La période de la modulation de largeur d’impulsion sera configurée suffisamment rapide pour que l’aiguille n’oscille pas.
Pulsation de temporisation (timepulse)
Le module ne prend pas de valeur d’entrée hormis l’horloge et le reset qui sont de rigueur dans tout le projet. Son signal de sortie tp_o
est une pulsation de l’horloge émise toutes les 5 120 ns :
module timepulse #(
parameter CLK_PER_NS = 40,
parameter PULSE_PER_NS = 5120
)(
/* clock and reset */
input clk_i,
input rst_i,
/* output */
output tp_o);
Pour pouvoir compter des périodes de 5 120 ns on définit un registre de comptage :
`define MAX_COUNT (PULSE_PER_NS/CLK_PER_NS)
`define MAX_COUNT_SIZE ($clog2(`MAX_COUNT))
reg [`MAX_COUNT_SIZE-1:0] counter = 0;
Puis on compte de manière synchronisée avec l’horloge :
always@(posedge clk_i or posedge rst_i)
begin
if(rst_i)
begin
counter <= 0;
end else begin
if (counter < `MAX_COUNT)
begin
counter <= counter + 1'b1;
end else begin
counter <= 0;
end
end
end
La pulsation est émise lorsque le compteur passe par 0 :
assign tp_o = (counter == 0);
Gestion des rebonds (debounce)
L’entrée de ce module est le signal de bouton préalablement synchronisé avec l’horloge du système btn_s
. Le compteur utilisera la pulsation tp_i
généré par le module timepulse décrit ci‑avant.
La sortie du module est un signal btn_o proprement lissé. La période de temporisation de 20 ms est donné ici en paramètre DEBOUNCE_PER_NS
:
module debounce #(
parameter PULSE_PER_NS = 5120,
parameter DEBOUNCE_PER_NS = 20_971_520
)(
/* clock and reset */
input clk_i,
input rst_i,
/* inputs */
input tp_i,
input btn_i,
/* output */
output btn_o
);
La gestion des rebonds est réalisée au moyen d’un compteur utilisé pour temporiser :
`define MAX_COUNT ((DEBOUNCE_PER_NS/PULSE_PER_NS)-1'b1)
`define MAX_COUNT_SIZE ($clog2(`MAX_COUNT))
/* Counter */
reg [`MAX_COUNT_SIZE-1:0] counter = 0;
Ainsi que d’une machine d’états à quatre états :
/* State machine */
localparam [1:0] s_wait_low = 2'h0,
s_wait_high = 2'h1,
s_cnt_high = 2'h2,
s_cnt_low = 2'h3;
reg [1:0] state_reg, state_next;
Les transitions de la machine d’états sont données dans le code ci‑dessous dans un processus dit « combinatoire » (always@*
) par opposition à un processus « synchrone ».
always@*
begin
case(state_reg)
s_wait_low:
if(btn_i)
state_next = s_cnt_high;
else
state_next = s_wait_low;
s_wait_high:
if(!btn_i)
state_next = s_cnt_low;
else
state_next = s_wait_high;
s_cnt_high:
/* verilator lint_off WIDTH */
if(counter == `MAX_COUNT)
/* verilator lint_on WIDTH */
state_next = s_wait_high;
else
state_next = s_cnt_high;
s_cnt_low:
/* verilator lint_off WIDTH */
if(counter == `MAX_COUNT)
/* verilator lint_on WIDTH */
state_next = s_wait_low;
else
state_next = s_cnt_low;
endcase;
end
L’état de la machine est tout de même synchronisé dans un second processus :
always@(posedge clk_i or posedge rst_i)
if(rst_i)
state_reg <= s_wait_low;
else
state_reg <= state_next;
Le principe de « lissage » des rebonds est donc le suivant : dans l’état initial s_wait_low
, on attend que le bouton passe à la valeur 1, et lorsque le signal passe à 1, on change d’état pour s_cnt_high
.
Le passage dans l’état s_cnt_high
a pour effet de faire passer le signal de sortie à 1 et déclencher le compteur. Tant que le compteur compte et n’a pas atteint la valeur MAX_COUNT
, on reste dans cet état quelles que soient les variations du signal d’entrée. Lorsque le compteur atteint la valeur maximale, la machine d’état passe dans l’état s_wait_high
(en attente de valeurs hautes).
Dans l’état s_wait_high
on surveille la valeur du bouton d’entrée, si elle passe à 0 on change d’état pour s_cnt_low
. De manière symétrique à s_cnt_high
, on déclenche donc le compteur en ignorant la valeur d’entrée, et, lorsqu’elle atteint son maximum, on passe à l’état initial s_wait_low
.
La valeur « lissée » du bouton en sortie est donnée par l’état de la machine d’état :
assign btn_o = (state_reg == s_cnt_high) || (state_reg == s_wait_high);
Mesure de la période de tempo (percount)
L’interface du module percount
se compose des entrées habituelles d’horloge clk_i
, de reset rst_i
, ainsi que de la pulsation tp_i
.
Le signal de mesure en entrée est btn_i
et la sortie est un vecteur btn_per_o
donnant la valeur mesurée. La valeur est considérée comme valide uniquement lorsque la sortie btn_per_valid
est à 1. Cette astuce permet d’économiser un registre si la sauvegarde de la valeur mesurée est inutile comme c’est le cas ici.
`define MIN_NS 60_000_000_000
`define BTN_PER_MAX (`MIN_NS/TP_CYCLE)
`define BTN_PER_SIZE ($clog2(1 + `BTN_PER_MAX))
module percount #(
parameter CLK_PER_NS = 40,
parameter TP_CYCLE = 5120,
parameter PULSE_PER_NS = 5120,
)(
/* clock and reset */
input clk_i,
input rst_i,
/* time pulse */
input tp_i,
/* input button */
input btn_i,
/* output period */
output [(`BTN_PER_SIZE-1):0] btn_per_o,
output btn_per_valid);
Maintenant que nous avons un signal de bouton btn_b
propre et lissé, nous pouvons entamer la mesure de la période entre deux appuis au moyen de… devinez quoi ? D’un compteur pardi !
reg [($clog2(`BTN_PER_MAX+1)-1):0] counter = 0;
reg counter_valid = 0;
assign btn_per_valid = counter_valid;
assign btn_per_o = counter;
Il nous faut tout d’abord détecter le front descendant du bouton :
reg btn_old;
wire btn_fall = btn_old & (!btn_i);
always@(posedge clk_i or posedge rst_i)
begin
if(rst_i)
btn_old <= 1'b0;
else
btn_old <= btn_i;
end
Le signal btn_fall
sert de remise à zéro du compteur ainsi que de validation de la valeur de sortie :
always@(posedge clk_i or posedge rst_i)
begin
if(rst_i)
begin
counter <= 0;
end else begin
if(btn_fall) begin
counter_valid <= 1'b1;
end else if(counter_valid) begin
counter <= 0;
counter_valid <= 1'b0;
end else begin
/* stop counting if max, count tp_i */
if(tp_i && counter < `BTN_PER_MAX)
counter <= counter + 1'b1;
end
end
end
Le compteur compte le nombre de pulsations de tp_i
jusqu’à atteindre la saturation BTN_PER_MAX
. Si un front montant du bouton se présente avec btn_fall
, on valide le compteur avec counter_valid
. Et si le signal de validation passe à 1 (donc, le coup d’horloge suivant), on remet le compteur à zéro et on recommence à compter.
Calcul de la fréquence en Beat Per Minute (per2bpm)
Avec le module per2bpm
on arrive dans la partie critique du projet, car il va nous falloir faire une division. On entre une période dans le module :
/* inputs */
input [(`BTN_PER_SIZE-1):0] btn_per_i,
input btn_per_valid,
Et on doit en ressortir une fréquence (BPM) :
/* outputs */
output [`BPM_SIZE - 1:0] bpm_o,
output bpm_valid
Suivant la formule :
Il faut donc diviser la constante <img style="display: inline; max-height: 1em;" class="mathjax" src="data:image/svg+xml;base64,PHN2ZyB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGlu%0AayIgdmlld0JveD0iMCAtMTAwMC43MTE5MDAxNDUyOTQ3IDMwMTAuMjM2MjE1%0AODg3MTggMTUwMS40MjM4MDAyOTA1ODk1IiBzdHlsZT0id2lkdGg6IDYuOTg4%0AZXg7IGhlaWdodDogMy40OTRleDsgdmVydGljYWwtYWxpZ246IC0xLjIwNWV4%0AOyBtYXJnaW46IDFweCAwcHg7IHBvc2l0aW9uOiBzdGF0aWM7IiB4bWxucz0i%0AaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxkZWZzIGlkPSJNYXRoSmF4%0AX1NWR19nbHlwaHMiPjxwYXRoIGlkPSJTVElYV0VCTUFJTkktNEQiIHN0cm9r%0AZS13aWR0aD0iMTAiIGQ9Ik04NzIgNjUzdi0xNmMtNTcgLTkgLTY3IC0yMyAt%0AODEgLTc0bC0xMjMgLTQ0M2MtNyAtMjUgLTE0IC00NiAtMTQgLTYyYzAgLTI2%0AIDE4IC00MCA4MSAtNDJsLTEgLTE2aC0yNzF2MTZjNjUgNyA4NSAyNCAxMDIg%0AODZsMTI2IDQ1OWwtMzc2IC01NjFoLTE3bC02MiA1NDZsLTExOCAtNDI4Yy01%0AIC0xOCAtOSAtNDMgLTkgLTU0YzAgLTI4IDE5IC00NCA3MCAtNDh2LTE2aC0x%0AOTd2MTZjNTIgNiA2OCAyMiAxMDAgMTM0bDExNCA0MDEgYzggMjcgMTIgNDQg%0AMTIgNTJjMCAxOSAtMjQgMzEgLTc0IDM0djE2aDE4MWw1NiAtNDkybDMzNSA0%0AOTJoMTY2WiI+PC9wYXRoPjxwYXRoIGlkPSJTVElYV0VCTUFJTkktNDkiIHN0%0Acm9rZS13aWR0aD0iMTAiIGQ9Ik0zODQgNjUzdi0xNmMtNTYgLTcgLTY1IC0x%0ANiAtODIgLTc3bC0xMjAgLTQyOWMtOSAtMzIgLTE1IC01NiAtMTUgLTc2YzAg%0ALTI4IDEyIC0zMiA2OSAtMzl2LTE2aC0yNDR2MTZjNTUgMTAgNjkgMTkgODQg%0ANzVsMTIwIDQ0MWM3IDI1IDEzIDQ2IDEzIDYyYzAgMjUgLTE2IDQwIC03MiA0%0AM3YxNmgyNDdaIj48L3BhdGg+PHBhdGggaWQ9IlNUSVhXRUJNQUlOSS00RSIg%0Ac3Ryb2tlLXdpZHRoPSIxMCIgZD0iTTcyNyA2NTN2LTE2Yy02MyAtMTQgLTY1%0AIC0xNiAtMTAyIC0xNDVsLTE0NiAtNTA3aC0xOGwtMjMwIDU1MGwtMTE0IC00%0AMjJjLTYgLTIxIC05IC00MSAtOSAtNTRjMCAtMjggMTggLTM5IDcwIC00M3Yt%0AMTZoLTE5OHYxNmM1NiA4IDcwIDI0IDEwNiAxNTJsMTE3IDQxNWMtMTUgMzUg%0ALTM5IDU0IC04NiA1NHYxNmgxNjBsMjA3IC00OTlsMTA2IDM4OGM2IDIxIDgg%0AMzIgOCA0NGMwIDM2IC0xMiA0NiAtNjkgNTF2MTZoMTk4WiI+PC9wYXRoPjxw%0AYXRoIGlkPSJTVElYV0VCTUFJTi01RiIgc3Ryb2tlLXdpZHRoPSIxMCIgZD0i%0ATTUwMCAtMTI1aC01MDB2NTBoNTAwdi01MFoiPjwvcGF0aD48cGF0aCBpZD0i%0AU1RJWFdFQk1BSU5JLTRFIiBzdHJva2Utd2lkdGg9IjEwIiBkPSJNNzI3IDY1%0AM3YtMTZjLTYzIC0xNCAtNjUgLTE2IC0xMDIgLTE0NWwtMTQ2IC01MDdoLTE4%0AbC0yMzAgNTUwbC0xMTQgLTQyMmMtNiAtMjEgLTkgLTQxIC05IC01NGMwIC0y%0AOCAxOCAtMzkgNzAgLTQzdi0xNmgtMTk4djE2YzU2IDggNzAgMjQgMTA2IDE1%0AMmwxMTcgNDE1Yy0xNSAzNSAtMzkgNTQgLTg2IDU0djE2aDE2MGwyMDcgLTQ5%0AOWwxMDYgMzg4YzYgMjEgOCAzMiA4IDQ0YzAgMzYgLTEyIDQ2IC02OSA1MXYx%0ANmgxOThaIj48L3BhdGg+PHBhdGggaWQ9IlNUSVhXRUJNQUlOSS01MyIgc3Ry%0Ab2tlLXdpZHRoPSIxMCIgZD0iTTUwOCA2NjdsLTQwIC0yMDBsLTE4IDNjMCAx%0AMDIgLTIyIDE2MyAtMTE5IDE2M2MtNjkgMCAtMTEyIC0zNyAtMTEyIC0xMDBj%0AMCAtNDkgOCAtNjUgOTkgLTE1NmM5MSAtOTIgMTEzIC0xMzUgMTEzIC0yMDBj%0AMCAtMTE0IC04NyAtMTk1IC0yMDIgLTE5NWMtMzEgMCAtNTggNyAtMTA0IDIz%0AYy0yNyAxMCAtMzYgMTIgLTQ3IDEyYy0yMCAwIC0zNiAtOSAtNDMgLTMyaC0x%0AOGwzNCAyMjRsMjAgLTJjLTIgLTkgLTIgLTE2IC0yIC0yMyBjMCAtOTggNjAg%0ALTE2NyAxNDQgLTE2N2M3NyAwIDEzMSA1MiAxMzEgMTI4YzAgNDMgLTE0IDcz%0AIC02MCAxMjNsLTM5IDQyYy0xNCAxNSAtMjYgMjkgLTM5IDQyYy02MCA2NCAt%0ANzUgOTYgLTc1IDE1MGMwIDEwNSA4MiAxNjQgMTc4IDE2NGMzMSAwIDY0IC01%0AIDg1IC0xNGMyMSAtOCAzMyAtMTEgNDYgLTExYzIyIDAgMzEgNSA0NSAyNmgy%0AM1oiPjwvcGF0aD48cGF0aCBpZD0iU1RJWFdFQk1BSU5JLTU0IiBzdHJva2Ut%0Ad2lkdGg9IjEwIiBkPSJNNjMzIDY1M2wtNDQgLTE2NGwtMTcgMmMyIDE3IDMg%0AMzMgMyA0NmMwIDUzIC0zNiA4MSAtMTAxIDgxaC01OGwtMTM3IC00OTBjLTYg%0ALTIxIC0xNCAtNDQgLTE0IC02NmMwIC0zMSAxMiAtMzkgNTMgLTQzbDM1IC0z%0Adi0xNmgtMjg4djE2YzY5IDYgOTIgMjEgMTA3IDc1bDE0MyA1MjdjLTE1OCAw%0AIC0xOTAgLTE2IC0yMzggLTEyNGwtMTggNGw0MiAxNTVoNTMyWiI+PC9wYXRo%0APjxwYXRoIGlkPSJTVElYV0VCTUFJTkktNTAiIHN0cm9rZS13aWR0aD0iMTAi%0AIGQ9Ik0xNDYgNjUzaDI0MWMxNDcgMCAyMTggLTUyIDIxOCAtMTQ4YzAgLTU0%0AIC0yNyAtMTA5IC02OCAtMTQzYy00NiAtMzggLTExNiAtNTcgLTIwNSAtNTdj%0ALTQyIDAgLTY0IDIgLTkwIDhsLTUzIC0xOTNjLTcgLTI3IC0xNCAtNDggLTE0%0AIC02M2MwIC0yMyAxNSAtMzUgNjkgLTQxdi0xNmgtMjQ0djE2YzU3IDggNjYg%0AMTcgODQgODJsMTE2IDQxNGMxMyA0NyAxNyA2OCAxNyA4M2MwIDI3IC0xNCAz%0ANSAtNzEgNDJ2MTZ6TTMyMCA1OTJsLTY5IC0yNDUgYzI5IC01IDM0IC01IDUy%0AIC01YzYyIDAgOTcgNiAxMjggMjRjNDQgMjUgNzEgNjkgNzEgMTM0YzAgODkg%0ALTQ4IDEyMyAtMTMwIDEyM2MtMjggMCAtNDYgLTggLTUyIC0zMVoiPjwvcGF0%0AaD48cGF0aCBpZD0iU1RJWFdFQk1BSU4tNUYiIHN0cm9rZS13aWR0aD0iMTAi%0AIGQ9Ik01MDAgLTEyNWgtNTAwdjUwaDUwMHYtNTBaIj48L3BhdGg+PHBhdGgg%0AaWQ9IlNUSVhXRUJNQUlOSS00RSIgc3Ryb2tlLXdpZHRoPSIxMCIgZD0iTTcy%0ANyA2NTN2LTE2Yy02MyAtMTQgLTY1IC0xNiAtMTAyIC0xNDVsLTE0NiAtNTA3%0AaC0xOGwtMjMwIDU1MGwtMTE0IC00MjJjLTYgLTIxIC05IC00MSAtOSAtNTRj%0AMCAtMjggMTggLTM5IDcwIC00M3YtMTZoLTE5OHYxNmM1NiA4IDcwIDI0IDEw%0ANiAxNTJsMTE3IDQxNWMtMTUgMzUgLTM5IDU0IC04NiA1NHYxNmgxNjBsMjA3%0AIC00OTlsMTA2IDM4OGM2IDIxIDggMzIgOCA0NGMwIDM2IC0xMiA0NiAtNjkg%0ANTF2MTZoMTk4WiI+PC9wYXRoPjxwYXRoIGlkPSJTVElYV0VCTUFJTkktNTMi%0AIHN0cm9rZS13aWR0aD0iMTAiIGQ9Ik01MDggNjY3bC00MCAtMjAwbC0xOCAz%0AYzAgMTAyIC0yMiAxNjMgLTExOSAxNjNjLTY5IDAgLTExMiAtMzcgLTExMiAt%0AMTAwYzAgLTQ5IDggLTY1IDk5IC0xNTZjOTEgLTkyIDExMyAtMTM1IDExMyAt%0AMjAwYzAgLTExNCAtODcgLTE5NSAtMjAyIC0xOTVjLTMxIDAgLTU4IDcgLTEw%0ANCAyM2MtMjcgMTAgLTM2IDEyIC00NyAxMmMtMjAgMCAtMzYgLTkgLTQzIC0z%0AMmgtMThsMzQgMjI0bDIwIC0yYy0yIC05IC0yIC0xNiAtMiAtMjMgYzAgLTk4%0AIDYwIC0xNjcgMTQ0IC0xNjdjNzcgMCAxMzEgNTIgMTMxIDEyOGMwIDQzIC0x%0ANCA3MyAtNjAgMTIzbC0zOSA0MmMtMTQgMTUgLTI2IDI5IC0zOSA0MmMtNjAg%0ANjQgLTc1IDk2IC03NSAxNTBjMCAxMDUgODIgMTY0IDE3OCAxNjRjMzEgMCA2%0ANCAtNSA4NSAtMTRjMjEgLTggMzMgLTExIDQ2IC0xMWMyMiAwIDMxIDUgNDUg%0AMjZoMjNaIj48L3BhdGg+PC9kZWZzPjxnIHN0cm9rZT0iYmxhY2siIGZpbGw9%0AImJsYWNrIiBzdHJva2Utd2lkdGg9IjAiIHRyYW5zZm9ybT0ibWF0cml4KDEg%0AMCAwIC0xIDAgMCkiPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEyMCwwKSI+%0APHJlY3Qgc3Ryb2tlPSJub25lIiB3aWR0aD0iMjc3MCIgaGVpZ2h0PSI2MCIg%0AeD0iMCIgeT0iMjIwIj48L3JlY3Q+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUo%0ANjAsNTAyKSI+PHVzZSB0cmFuc2Zvcm09InNjYWxlKDAuNzA3MTA2NzgxMTg2%0ANTQ3NikiIHhsaW5rOmhyZWY9IiNTVElYV0VCTUFJTkktNEQiPjwvdXNlPjx1%0Ac2UgdHJhbnNmb3JtPSJzY2FsZSgwLjcwNzEwNjc4MTE4NjU0NzYpIiB4bGlu%0AazpocmVmPSIjU1RJWFdFQk1BSU5JLTQ5IiB4PSI4NzciIHk9IjAiPjwvdXNl%0APjx1c2UgdHJhbnNmb3JtPSJzY2FsZSgwLjcwNzEwNjc4MTE4NjU0NzYpIiB4%0AbGluazpocmVmPSIjU1RJWFdFQk1BSU5JLTRFIiB4PSIxMjY1IiB5PSIwIj48%0AL3VzZT48dXNlIHRyYW5zZm9ybT0ic2NhbGUoMC43MDcxMDY3ODExODY1NDc2%0AKSIgeGxpbms6aHJlZj0iI1NUSVhXRUJNQUlOLTVGIiB4PSIxOTk4IiB5PSIw%0AIj48L3VzZT48dXNlIHRyYW5zZm9ybT0ic2NhbGUoMC43MDcxMDY3ODExODY1%0ANDc2KSIgeGxpbms6aHJlZj0iI1NUSVhXRUJNQUlOSS00RSIgeD0iMjUwMyIg%0AeT0iMCI+PC91c2U+PHVzZSB0cmFuc2Zvcm09InNjYWxlKDAuNzA3MTA2Nzgx%0AMTg2NTQ3NikiIHhsaW5rOmhyZWY9IiNTVElYV0VCTUFJTkktNTMiIHg9IjMy%0AMzUiIHk9IjAiPjwvdXNlPjwvZz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgz%0AMjMsLTM4NikiPjx1c2UgdHJhbnNmb3JtPSJzY2FsZSgwLjcwNzEwNjc4MTE4%0ANjU0NzYpIiB4bGluazpocmVmPSIjU1RJWFdFQk1BSU5JLTU0Ij48L3VzZT48%0AdXNlIHRyYW5zZm9ybT0ic2NhbGUoMC43MDcxMDY3ODExODY1NDc2KSIgeGxp%0Abms6aHJlZj0iI1NUSVhXRUJNQUlOSS01MCIgeD0iNjM4IiB5PSIwIj48L3Vz%0AZT48dXNlIHRyYW5zZm9ybT0ic2NhbGUoMC43MDcxMDY3ODExODY1NDc2KSIg%0AeGxpbms6aHJlZj0iI1NUSVhXRUJNQUlOLTVGIiB4PSIxMjU0IiB5PSIwIj48%0AL3VzZT48dXNlIHRyYW5zZm9ybT0ic2NhbGUoMC43MDcxMDY3ODExODY1NDc2%0AKSIgeGxpbms6aHJlZj0iI1NUSVhXRUJNQUlOSS00RSIgeD0iMTc1OSIgeT0i%0AMCI+PC91c2U+PHVzZSB0cmFuc2Zvcm09InNjYWxlKDAuNzA3MTA2NzgxMTg2%0ANTQ3NikiIHhsaW5rOmhyZWY9IiNTVElYV0VCTUFJTkktNTMiIHg9IjI0OTEi%0AIHk9IjAiPjwvdXNlPjwvZz48L2c+PC9nPjwvc3ZnPg==%0A" alt="\frac{MIN\_NS}{TP\_NS}">
par la variable <img style="display: inline; max-height: 1em;" class="mathjax" src="data:image/svg+xml;base64,PHN2ZyB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGlu%0AayIgdmlld0JveD0iMCAtNzEyLjI3NzQ4OTAwMjU0MSAzOTc5IDk0Ni41NTQ5%0ANzgwMDUwODE4IiBzdHlsZT0id2lkdGg6IDkuMjc3ZXg7IGhlaWdodDogMi4x%0ANjlleDsgdmVydGljYWwtYWxpZ246IC0wLjYwMmV4OyBtYXJnaW46IDFweCAw%0AcHg7IHBvc2l0aW9uOiBzdGF0aWM7IiB4bWxucz0iaHR0cDovL3d3dy53My5v%0AcmcvMjAwMC9zdmciPjxkZWZzIGlkPSJNYXRoSmF4X1NWR19nbHlwaHMiPjxw%0AYXRoIGlkPSJTVElYV0VCTUFJTkktNjIiIHN0cm9rZS13aWR0aD0iMTAiIGQ9%0AIk0xNjMgMjkwaDFjNjggMTEzIDEyMyAxNTEgMTkzIDE1MWM2NyAwIDExNiAt%0ANDMgMTE2IC0xMjBjMCAtMTU4IC0xNjUgLTMzMiAtMzIwIC0zMzJjLTU3IDAg%0ALTEzMCAyMyAtMTMwIDUzdjZsMTQyIDUyM2M2IDI0IDkgMzggOSA0N2MwIDIy%0AIC01IDIzIC02NCAyNXYxN2M2NyA4IDEwMyAxNCAxNTMgMjNsNSAtNWwtMjEg%0ALTgyek0zODggMzA2YzAgNjEgLTI2IDg2IC03MCA4NmMtNDggMCAtOTQgLTQy%0AIC0xMzcgLTExNSBjLTQ0IC03NCAtNzIgLTE3MSAtNzIgLTIzMWMwIC0yMyAx%0ANSAtMzQgNDYgLTM0YzQzIDAgODYgMjEgMTIzIDU5YzYwIDYyIDExMCAxNjEg%0AMTEwIDIzNVoiPjwvcGF0aD48cGF0aCBpZD0iU1RJWFdFQk1BSU5JLTc0IiBz%0AdHJva2Utd2lkdGg9IjEwIiBkPSJNMjk2IDQyOGwtNSAtMzJoLTg0bC04NyAt%0AMzI4Yy0xIC00IC0yIC0xMSAtMiAtMTRjMCAtMTMgNiAtMTYgMTUgLTE2YzE2%0AIDAgMzIgMTYgODEgNzlsMTMgLTdjLTYwIC05MiAtOTEgLTEyMSAtMTQzIC0x%0AMjFjLTI3IDAgLTQ2IDEyIC00NiAzN2MwIDExIDggNDIgMTYgNzRsNzggMjk2%0AaC03NWMtMSAzIC0xIDYgLTEgNmMwIDExIDkgMjAgMzMgMjVjMzIgNyA5NyA1%0ANiAxMzMgMTEwYzQgNiAxMCA5IDE0IDljNiAwIDkgLTMgOSAtOCBjMCAwIDAg%0ALTUgLTEgLTdsLTI4IC0xMDNoODBaIj48L3BhdGg+PHBhdGggaWQ9IlNUSVhX%0ARUJNQUlOSS02RSIgc3Ryb2tlLXdpZHRoPSIxMCIgZD0iTTQ2MCAxMTdsMTQg%0ALTEzYy02OCAtOTMgLTkzIC0xMTMgLTE0MCAtMTEzYy0yNSAwIC00NyAxNiAt%0ANDcgNTRjMCAxMCAyIDIzIDE2IDc1bDQ0IDE2MmM4IDMxIDE0IDY3IDE0IDc5%0AYzAgMTggLTkgMjkgLTI0IDI5Yy00MCAwIC04NSAtNDkgLTE0OCAtMTQyYy00%0ANSAtNjcgLTUzIC05MCAtMTAwIC0yNDhoLTc1bDk2IDM1MGMxIDUgMiAxMSAy%0AIDE3YzAgMjAgLTE0IDI2IC02NSAyN3YxNmM4MSAxNiAxMDkgMjAgMTYyIDMx%0AbDQgLTJsLTY3IC0yMTggYzEwMCAxNjAgMTY3IDIyMCAyMzEgMjIwYzQzIDAg%0ANjUgLTI1IDY1IC02MWMwIC0xOCAtNCAtMzkgLTEwIC02MGwtNTYgLTIwM2Mt%0AMTAgLTM2IC0xNCAtNTMgLTE0IC02MWMwIC05IDQgLTE4IDE2IC0xOGMxNCAw%0AIDMyIDE2IDYxIDUzYzcgOCAxNCAxNyAyMSAyNloiPjwvcGF0aD48cGF0aCBp%0AZD0iU1RJWFdFQk1BSU4tNUYiIHN0cm9rZS13aWR0aD0iMTAiIGQ9Ik01MDAg%0ALTEyNWgtNTAwdjUwaDUwMHYtNTBaIj48L3BhdGg+PHBhdGggaWQ9IlNUSVhX%0ARUJNQUlOSS03MCIgc3Ryb2tlLXdpZHRoPSIxMCIgZD0iTTIxNSA0MjhsLTI5%0AIC0xMDBjNTQgODEgMTExIDExMyAxNzEgMTEzYzc0IDAgMTE1IC00NyAxMTUg%0ALTEyNWMwIC0xNjUgLTE1MSAtMzI3IC0yOTcgLTMyN2MtMjMgMCAtNDQgNCAt%0ANjkgMTdjLTE3IC03MCAtNDAgLTE1MiAtNDAgLTE2NmMwIC0yMiAxNSAtMjkg%0ANjIgLTI5di0xNmgtMjAzdjE2YzQzIDEgNTYgMTYgNjggNjNsMTE1IDQzMmMx%0AMSA0MCAxNiA2NiAxNiA3MWMwIDI0IC0yOCAyNyAtNDQgMjdoLTIybC0yIDE1%0AbDE1NiAyMiBjMyAwIDUgLTIgNSAtNGMwIDAgLTEgLTUgLTIgLTl6TTM4MiAz%0AMTNjMCA1NyAtMTcgODUgLTYyIDg1Yy01MyAwIC0xMTIgLTU0IC0xMzUgLTEx%0ANGMtMjkgLTc1IC02NSAtMjA0IC02NSAtMjM4YzAgLTIyIDIwIC0zOCA0OCAt%0AMzhjNTMgMCAxMDEgMzMgMTQ1IDk1YzQ4IDY3IDY5IDE0MCA2OSAyMTBaIj48%0AL3BhdGg+PHBhdGggaWQ9IlNUSVhXRUJNQUlOSS02NSIgc3Ryb2tlLXdpZHRo%0APSIxMCIgZD0iTTM1OCAxMDlsMTIgLTEyYy01NyAtNzAgLTEyMSAtMTA4IC0y%0AMDQgLTEwOGMtODEgMCAtMTM1IDU0IC0xMzUgMTM3YzAgMTU1IDE0OSAzMTUg%0AMjk5IDMxNWM1MyAwIDgyIC0yNiA4MiAtNjhjMCAtODYgLTEwNSAtMTY0IC0y%0AODQgLTE4N2MtMTAgLTIwIC0xMCAtNDYgLTEwIC02MWMwIC01NSAzNyAtOTEg%0AOTMgLTkxYzQ0IDAgNzUgMTYgMTQ3IDc1ek0xNTIgMjUybC0xNyAtNDRjODYg%0AMjEgMTI0IDM5IDE2MSA3NGMzMSAzMCA1MCA2NiA1MCA5NyBjMCAyNCAtNyAz%0AOSAtMzUgMzljLTU3IDAgLTEyNSAtNzcgLTE1OSAtMTY2WiI+PC9wYXRoPjxw%0AYXRoIGlkPSJTVElYV0VCTUFJTkktNzIiIHN0cm9rZS13aWR0aD0iMTAiIGQ9%0AIk0xNzYgMjIzbDE2IDM1YzE5IDQyIDUzIDk1IDk0IDEzOGMyNiAyNyA1NiA0%0ANSA3OSA0NWMyOCAwIDQ3IC0yMSA0NyAtNTFzLTE3IC01NCAtNDcgLTU0Yy0x%0AOCAwIC0yNiAxMSAtMzUgMjZjLTYgMTAgLTkgMTQgLTE2IDE0Yy0xOCAwIC00%0ANiAtMzMgLTgyIC05NGMtNDMgLTc0IC02MSAtMTE0IC0xMTEgLTI4MmgtNzZs%0AODEgMjkyYzE0IDUyIDE2IDYxIDE2IDgycy0xOCAyNiAtMzggMjZjLTggMCAt%0AMTYgLTEgLTMxIC0zdjE3bDE1NSAyN2wzIC0yIFoiPjwvcGF0aD48cGF0aCBp%0AZD0iU1RJWFdFQk1BSU4tNUYiIHN0cm9rZS13aWR0aD0iMTAiIGQ9Ik01MDAg%0ALTEyNWgtNTAwdjUwaDUwMHYtNTBaIj48L3BhdGg+PHBhdGggaWQ9IlNUSVhX%0ARUJNQUlOSS02OSIgc3Ryb2tlLXdpZHRoPSIxMCIgZD0iTTI2NCA1OTljMCAt%0AMjggLTIzIC01MSAtNDkgLTUxYy0yOSAwIC00OCAyMSAtNDggNTNjMCAzMSAy%0AMCA1MyA0NyA1M3M1MCAtMjYgNTAgLTU1ek0yMjIgMTE0bDEzIC0xMWMtNTUg%0ALTg0IC04NyAtMTE0IC0xMzcgLTExNGMtMzMgMCAtNDkgMTggLTQ5IDU1YzAg%0AMjAgNyA1NSAyMiAxMTFsNDggMTc3YzUgMTggOSAzNiA5IDQ0YzAgMjAgLTEw%0AIDIzIC02NCAyNHYxNmMzOSAzIDU5IDYgMTYwIDI1bDQgLTNsLTk0IC0zNDMg%0AYy01IC0xNyAtMTAgLTMwIC0xMCAtNDRjMCAtMTAgNiAtMTUgMTQgLTE1YzE3%0AIDAgNDEgMjEgODQgNzhaIj48L3BhdGg+PC9kZWZzPjxnIHN0cm9rZT0iYmxh%0AY2siIGZpbGw9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjAiIHRyYW5zZm9ybT0i%0AbWF0cml4KDEgMCAwIC0xIDAgMCkiPjx1c2UgeGxpbms6aHJlZj0iI1NUSVhX%0ARUJNQUlOSS02MiI+PC91c2U+PHVzZSB4bGluazpocmVmPSIjU1RJWFdFQk1B%0ASU5JLTc0IiB4PSI1MDUiIHk9IjAiPjwvdXNlPjx1c2UgeGxpbms6aHJlZj0i%0AI1NUSVhXRUJNQUlOSS02RSIgeD0iODA2IiB5PSIwIj48L3VzZT48dXNlIHhs%0AaW5rOmhyZWY9IiNTVElYV0VCTUFJTi01RiIgeD0iMTMxMSIgeT0iMCI+PC91%0Ac2U+PHVzZSB4bGluazpocmVmPSIjU1RJWFdFQk1BSU5JLTcwIiB4PSIxODE2%0AIiB5PSIwIj48L3VzZT48dXNlIHhsaW5rOmhyZWY9IiNTVElYV0VCTUFJTkkt%0ANjUiIHg9IjIzMjUiIHk9IjAiPjwvdXNlPjx1c2UgeGxpbms6aHJlZj0iI1NU%0ASVhXRUJNQUlOSS03MiIgeD0iMjc3NCIgeT0iMCI+PC91c2U+PHVzZSB4bGlu%0AazpocmVmPSIjU1RJWFdFQk1BSU4tNUYiIHg9IjMxOTEiIHk9IjAiPjwvdXNl%0APjx1c2UgeGxpbms6aHJlZj0iI1NUSVhXRUJNQUlOSS02OSIgeD0iMzY5NiIg%0AeT0iMCI+PC91c2U+PC9nPjwvc3ZnPg==%0A" alt="btn\_per\_i">
La division (tout comme la multiplication) est un point sensible en Verilog. En effet, l’opérateur de division existe bien dans le langage et il se peut que cela simule parfaitement.
C’est lorsque arrivera l’étape de la synthèse que l’on risque d’avoir quelques surprises. Il est possible que certains logiciels de synthèse réussiront à faire quelque chose en un coup d’horloge, mais il est certain que cela se fera au prix de très mauvaises performances en matière de ressources utilisées et de fréquence d’horloge. Il est surtout probable que votre logiciel de synthèse jette l’éponge.
Pour réaliser cette division, nous allons donc en revenir aux fondamentaux appris au primaire et poser la division. Une division, c’est la recherche du quotient et du reste de l’équation suivante :
<img style="display: inline; max-height: 1em;" class="mathjax" src="data:image/svg+xml;base64,PHN2ZyB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGlu%0AayIgdmlld0JveD0iLTMgLTcxMi4yNzc0ODkwMDI1NDEgMTgzNTAuNDQ0NDQ0%0ANDQ0NDQ1IDkyMy41NTQ5NzgwMDUwODE4IiBzdHlsZT0id2lkdGg6IDQyLjY1%0AMWV4OyBoZWlnaHQ6IDIuMTY5ZXg7IHZlcnRpY2FsLWFsaWduOiAtMC42MDJl%0AeDsgbWFyZ2luOiAxcHggMHB4OyBwb3NpdGlvbjogc3RhdGljOyIgeG1sbnM9%0AImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZGVmcyBpZD0iTWF0aEph%0AeF9TVkdfZ2x5cGhzIj48cGF0aCBpZD0iU1RJWFdFQk1BSU5JLTQ0IiBzdHJv%0Aa2Utd2lkdGg9IjEwIiBkPSJNMTMxIDY1M2gyNzdjMTc1IDAgMjkyIC05NCAy%0AOTIgLTI2OWMwIC0xMjQgLTYyIC0yMjUgLTE2MCAtMzAxYy03MyAtNTcgLTE3%0ANCAtODMgLTI5MSAtODNoLTI1N3YxNmM1NiAxMCA2NiAxNyA4MiA3NmwxMjIg%0ANDQ1YzcgMjUgMTEgNDQgMTEgNTljMCAyNyAtMTUgMzkgLTc2IDQxdjE2ek0z%0AMTAgNTg0bC0xMTggLTQyMmMtMTcgLTYyIC0yMiAtODIgLTIyIC05NWMwIC0y%0ANiAyMiAtMzcgNjggLTM3YzEwMSAwIDE3OSAzMCAyNDEgOTAgYzcxIDY5IDEx%0AMCAxODcgMTEwIDI4OGMwIDgwIC0yOSAxNDMgLTc4IDE4MGMtMzEgMjMgLTcz%0AIDM1IC0xMzEgMzVjLTM4IDAgLTYwIC00IC03MCAtMzlaIj48L3BhdGg+PHBh%0AdGggaWQ9IlNUSVhXRUJNQUlOSS02OSIgc3Ryb2tlLXdpZHRoPSIxMCIgZD0i%0ATTI2NCA1OTljMCAtMjggLTIzIC01MSAtNDkgLTUxYy0yOSAwIC00OCAyMSAt%0ANDggNTNjMCAzMSAyMCA1MyA0NyA1M3M1MCAtMjYgNTAgLTU1ek0yMjIgMTE0%0AbDEzIC0xMWMtNTUgLTg0IC04NyAtMTE0IC0xMzcgLTExNGMtMzMgMCAtNDkg%0AMTggLTQ5IDU1YzAgMjAgNyA1NSAyMiAxMTFsNDggMTc3YzUgMTggOSAzNiA5%0AIDQ0YzAgMjAgLTEwIDIzIC02NCAyNHYxNmMzOSAzIDU5IDYgMTYwIDI1bDQg%0ALTNsLTk0IC0zNDMgYy01IC0xNyAtMTAgLTMwIC0xMCAtNDRjMCAtMTAgNiAt%0AMTUgMTQgLTE1YzE3IDAgNDEgMjEgODQgNzhaIj48L3BhdGg+PHBhdGggaWQ9%0AIlNUSVhXRUJNQUlOSS03NiIgc3Ryb2tlLXdpZHRoPSIxMCIgZD0iTTIwNyA3%0AMGwzMSAzMmM3MiA3NCAxMzcgMTg0IDEzNyAyMzFjMCAxMCAtNSAxNyAtMTgg%0AMjljLTE4IDE2IC0yNSAyOSAtMjUgNDVjMCAyMSAxNyAzNCAzOCAzNGMzMyAw%0AIDU2IC0zMiA1NiAtNTljMCAtNDMgLTI4IC0xMDEgLTYzIC0xNTVjLTQ1IC03%0AMCAtMTAxIC0xMzQgLTExOSAtMTUzYy01NSAtNTkgLTgyIC05MiAtOTkgLTky%0AYy02IDAgLTkgMTAgLTkgMjd2MjRjMCA2OSAtMTEgMjAyIC0yNCAyNzhzLTI0%0AIDkzIC02MSA5MyBjLTEwIDAgLTIwIDAgLTMxIC0xdjEzYzQ1IDcgODAgMTQg%0AMTEyIDIxYzggMyAxNSA0IDIwIDRjOSAwIDkgLTYgMzAgLTExNGMxMyAtNjcg%0AMTkgLTEyMiAyNSAtMjU3WiI+PC9wYXRoPjxwYXRoIGlkPSJTVElYV0VCTUFJ%0ATkktNjkiIHN0cm9rZS13aWR0aD0iMTAiIGQ9Ik0yNjQgNTk5YzAgLTI4IC0y%0AMyAtNTEgLTQ5IC01MWMtMjkgMCAtNDggMjEgLTQ4IDUzYzAgMzEgMjAgNTMg%0ANDcgNTNzNTAgLTI2IDUwIC01NXpNMjIyIDExNGwxMyAtMTFjLTU1IC04NCAt%0AODcgLTExNCAtMTM3IC0xMTRjLTMzIDAgLTQ5IDE4IC00OSA1NWMwIDIwIDcg%0ANTUgMjIgMTExbDQ4IDE3N2M1IDE4IDkgMzYgOSA0NGMwIDIwIC0xMCAyMyAt%0ANjQgMjR2MTZjMzkgMyA1OSA2IDE2MCAyNWw0IC0zbC05NCAtMzQzIGMtNSAt%0AMTcgLTEwIC0zMCAtMTAgLTQ0YzAgLTEwIDYgLTE1IDE0IC0xNWMxNyAwIDQx%0AIDIxIDg0IDc4WiI+PC9wYXRoPjxwYXRoIGlkPSJTVElYV0VCTUFJTkktNjQi%0AIHN0cm9rZS13aWR0aD0iMTAiIGQ9Ik01MjEgNjgzbDYgLTZsLTM5IC0xNTJs%0ALTYwIC0yMTljLTMxIC0xMTQgLTY1IC0yMzAgLTY1IC0yNDZjMCAtMTIgNSAt%0AMjAgMTggLTIwYzE3IDAgMjggOSA4MiA3MWwxMiAtMTBjLTQ5IC03MyAtOTcg%0ALTExNCAtMTQ3IC0xMTRjLTI2IDAgLTQxIDE4IC00MSA0NWMwIDIzIDIgMzkg%0AMTMgODljLTU5IC05OSAtMTEwIC0xMzIgLTE3OCAtMTMyYy02NSAwIC0xMDcg%0ANDEgLTEwNyAxMTdjMCAxNjIgMTYyIDMzNSAyOTIgMzM1IGM0MiAwIDU5IC0x%0AOSA2NSAtNThoMWw0NSAxNjNjMTUgNTMgMTQgNTcgMTQgNzFjMCAyMSAtOSAy%0ANCAtNjQgMjZ2MTdjNjQgNiAxMDAgMTIgMTUzIDIzek0zNTYgMzYxYzAgMzYg%0ALTI0IDU3IC00NyA1N2MtMjggMCAtNjMgLTE3IC05MSAtNDZjLTY2IC03MCAt%0AMTE2IC0xNzkgLTExNiAtMjYyYzAgLTQ2IDIzIC03MyA1OCAtNzNjOTIgMCAx%0AOTYgMTcyIDE5NiAzMjRaIj48L3BhdGg+PHBhdGggaWQ9IlNUSVhXRUJNQUlO%0ASS02NSIgc3Ryb2tlLXdpZHRoPSIxMCIgZD0iTTM1OCAxMDlsMTIgLTEyYy01%0ANyAtNzAgLTEyMSAtMTA4IC0yMDQgLTEwOGMtODEgMCAtMTM1IDU0IC0xMzUg%0AMTM3YzAgMTU1IDE0OSAzMTUgMjk5IDMxNWM1MyAwIDgyIC0yNiA4MiAtNjhj%0AMCAtODYgLTEwNSAtMTY0IC0yODQgLTE4N2MtMTAgLTIwIC0xMCAtNDYgLTEw%0AIC02MWMwIC01NSAzNyAtOTEgOTMgLTkxYzQ0IDAgNzUgMTYgMTQ3IDc1ek0x%0ANTIgMjUybC0xNyAtNDRjODYgMjEgMTI0IDM5IDE2MSA3NGMzMSAzMCA1MCA2%0ANiA1MCA5NyBjMCAyNCAtNyAzOSAtMzUgMzljLTU3IDAgLTEyNSAtNzcgLTE1%0AOSAtMTY2WiI+PC9wYXRoPjxwYXRoIGlkPSJTVElYV0VCTUFJTkktNkUiIHN0%0Acm9rZS13aWR0aD0iMTAiIGQ9Ik00NjAgMTE3bDE0IC0xM2MtNjggLTkzIC05%0AMyAtMTEzIC0xNDAgLTExM2MtMjUgMCAtNDcgMTYgLTQ3IDU0YzAgMTAgMiAy%0AMyAxNiA3NWw0NCAxNjJjOCAzMSAxNCA2NyAxNCA3OWMwIDE4IC05IDI5IC0y%0ANCAyOWMtNDAgMCAtODUgLTQ5IC0xNDggLTE0MmMtNDUgLTY3IC01MyAtOTAg%0ALTEwMCAtMjQ4aC03NWw5NiAzNTBjMSA1IDIgMTEgMiAxN2MwIDIwIC0xNCAy%0ANiAtNjUgMjd2MTZjODEgMTYgMTA5IDIwIDE2MiAzMWw0IC0ybC02NyAtMjE4%0AIGMxMDAgMTYwIDE2NyAyMjAgMjMxIDIyMGM0MyAwIDY1IC0yNSA2NSAtNjFj%0AMCAtMTggLTQgLTM5IC0xMCAtNjBsLTU2IC0yMDNjLTEwIC0zNiAtMTQgLTUz%0AIC0xNCAtNjFjMCAtOSA0IC0xOCAxNiAtMThjMTQgMCAzMiAxNiA2MSA1M2M3%0AIDggMTQgMTcgMjEgMjZaIj48L3BhdGg+PHBhdGggaWQ9IlNUSVhXRUJNQUlO%0ASS02NCIgc3Ryb2tlLXdpZHRoPSIxMCIgZD0iTTUyMSA2ODNsNiAtNmwtMzkg%0ALTE1MmwtNjAgLTIxOWMtMzEgLTExNCAtNjUgLTIzMCAtNjUgLTI0NmMwIC0x%0AMiA1IC0yMCAxOCAtMjBjMTcgMCAyOCA5IDgyIDcxbDEyIC0xMGMtNDkgLTcz%0AIC05NyAtMTE0IC0xNDcgLTExNGMtMjYgMCAtNDEgMTggLTQxIDQ1YzAgMjMg%0AMiAzOSAxMyA4OWMtNTkgLTk5IC0xMTAgLTEzMiAtMTc4IC0xMzJjLTY1IDAg%0ALTEwNyA0MSAtMTA3IDExN2MwIDE2MiAxNjIgMzM1IDI5MiAzMzUgYzQyIDAg%0ANTkgLTE5IDY1IC01OGgxbDQ1IDE2M2MxNSA1MyAxNCA1NyAxNCA3MWMwIDIx%0AIC05IDI0IC02NCAyNnYxN2M2NCA2IDEwMCAxMiAxNTMgMjN6TTM1NiAzNjFj%0AMCAzNiAtMjQgNTcgLTQ3IDU3Yy0yOCAwIC02MyAtMTcgLTkxIC00NmMtNjYg%0ALTcwIC0xMTYgLTE3OSAtMTE2IC0yNjJjMCAtNDYgMjMgLTczIDU4IC03M2M5%0AMiAwIDE5NiAxNzIgMTk2IDMyNFoiPjwvcGF0aD48cGF0aCBpZD0iU1RJWFdF%0AQk1BSU4tM0QiIHN0cm9rZS13aWR0aD0iMTAiIGQ9Ik02MzcgMzIwaC01ODl2%0ANjZoNTg5di02NnpNNjM3IDEyMGgtNTg5djY2aDU4OXYtNjZaIj48L3BhdGg+%0APHBhdGggaWQ9IlNUSVhXRUJNQUlOSS01MSIgc3Ryb2tlLXdpZHRoPSIxMCIg%0AZD0iTTY5IC0xNjlsLTEwIDE2Yzc3IDU0IDg2IDYxIDE3NyAxNDFjLTExNCAy%0AMyAtMTc2IDEwOCAtMTc2IDIzN2MwIDEyMyA2NCAyNTMgMTczIDM0N2M3NyA2%0ANSAxNjUgOTQgMjQxIDk0YzEzNyAwIDIyNSAtMTAyIDIyNSAtMjM3YzAgLTE1%0ANiAtMTA0IC0zMjIgLTI1NiAtNDAyYy01NCAtMjkgLTg5IC0zOCAtMTY0IC00%0AM2wtNTQgLTU3aDI1YzM0IDAgNzkgLTEwIDEyMyAtMjBjNDEgLTEwIDc4IC0y%0AMSAxMTEgLTIxYzcyIDAgMTEyIDE5IDE2OCA3NyBsMTYgLTExYy0xNSAtMjEg%0ALTMyIC00MSAtNTIgLTU5Yy01MCAtNDUgLTExNCAtNzUgLTE5MSAtNzVjLTM4%0AIDAgLTkxIDggLTE0OCAyNmMtNDMgMTQgLTczIDE4I