Skip to content

Capítulo 19: Secuenciando notas

Juan Gonzalez-Gomez edited this page Sep 2, 2015 · 23 revisions

Ejemplos de este capítulo en github

Introducción

Hasta ahora hemos generado sonidos en canales diferentes, de manera independiente. Implementaremos un secuenciador que nos permita tocar 4 notas que sonarán consecutivamente en el altavoz. Reproduciremos la secuencia: DO, RE, MI, (silencio) y se volverá al comienzo. Esto nos abre la puerta a la creación de melodías sencillas :-)

secnotas.v: Descripción del hardware

Una manera de lograr la secuenciación de las notas es utilizar un multiplexor, con el que se seleccionará en cada momento el canal a escuchar

En este ejemplo, tocaremos las notas DO, RE, MI, que se introducirán por las entradas 0, 1 y 2 respectivamente del multiplexor. Por la cuarta pondremos un "0" para que haya silencio.

La entrada de selección la conectamos a un contador de 2 bits, de forma que seleccione alternativamente los canales 0, 1, 2 y 3. Este contador tendrá una entrada de reloj que determinará la duración de la nota, que establecemos en 250ms.

El esquema del circuito se muestra en esta figura:

La descripción en verilog asociada a este esquema es:

//-- Fichero: secnotas.v

//-- Incluir las constantes del modulo del divisor
`include "divider.vh"

//-- Parameteros:
//-- clk: Reloj de entrada de la placa iCEstick
//-- ch_out: Canal de salida
module secnotas(input wire clk, output reg ch_out);

//-- Parametros: notas a tocar
//-- Se define como parametro para poder modificarlas desde el testbench
//-- para hacer pruebas
parameter N0 = `DO;
parameter N1 = `RE;
parameter N2 = `MI;
parameter DUR = `T_250ms;

//-- Cables de salida de los canales
wire ch0, ch1, ch2;

//-- Selección del canal del multiplexor
reg [1:0] sel = 0;

//-- Reloj con la duracion de la nota
wire clk_dur;

//-- Canal 0
divider #(N0)
  CH0 (
    .clk_in(clk),
    .clk_out(ch0)
  );

//-- Canal 1
divider #(N1)
  CH1 (
    .clk_in(clk),
    .clk_out(ch1)
  );

//-- canal 2
divider #(N2)
  CH2 (
    .clk_in(clk),
    .clk_out(ch2)
  );

//-- Multiplexor de seleccion del canal de salida
always @*
  case (sel)
     0 : ch_out <= ch0;
     1 : ch_out <= ch1;
     2 : ch_out <= ch2;
     3 : ch_out <= 0;
     default : ch_out <= 0;
  endcase

//-- Contador para seleccion de nota
always @(posedge clk_dur)
  sel <= sel + 1;

//-- Divisor para marcar la duración de cada nota
divider #(DUR)
  TIMER0 (
    .clk_in(clk),
    .clk_out(clk_dur)
  );

endmodule
Clone this wiki locally