Vous êtes sur la page 1sur 17

Personal

Open source

Business

Explore

Pricing

Blog

Support

This repository

Obijuan / open-fpga-verilog-tutorial
Code

Issues 0

Pull requests 0

Search

Watch
Wiki

Pulse

Sign in

13

Star

31

Sign up

Fork

15

Graphs

Captulo 25: Unidad de recepcin serie asncrona


Testato edited this page Feb 21, 2016 34 revisions

Pages 40

Inicio (EN)

Captulos

Ejemplos de este captulo en github

Introduccin
Disearemos una unidad de recepcin serie asncrona, que nos permita recibir datos tanto del
PC como de otro dispositivo de comunicacin serie. Obtendremos el componente final, listo para
usar en nuestros diseos
Para probarla haremos dos ejemplos: uno que saca los 4 bits menos segnificativos del dato
recibido por los leds de la ICEStick. Y otro que hace eco de todos los caracteres recibidos. Los
caracteres recibidos se envan al transmisor serie para que lleguen de nuevo al PC. Esto nos
permitir comprobar que efectivamente hemos recibido el dato correctamente.

Mdulo UART-RX
La unidad de transmisin serie la encapsularemos dentro del mdulo uart-rx

0 You are leaving the privative


sector (EN)
1 Hola mundo! (EN)
2 De un bit a datos (EN)
3 Puerta NOT (EN)
4 Contador de 26 bits (EN)
5 Prescaler de N bits (EN)
6 Mltiples prescalers
7 Contador de 4 bits con prescaler
8 Registro de 4 bits
9 Inicializador
10 Registro de desplazamiento
11 Multiplexor de 2 a 1
12 Multiplexor de M a 1
13 Inicializando registros
14 Registro de N bits con reset
sncrono
15 Divisor de frecuencias
16 Contador de segundos
17 Generando tonos audibles
18 Tocando notas
19 Secuenciando notas
20 Comunicaciones serie
asncronas
21 Baudios y transmisin
22 Reglas de diseo sncrono
23 Controladores y autmatas
finitos
24 Unidad de transmisin serie
asncrona
25 Unidad de recepcin serie
asncrona
26 Memoria ROM
27 Memoria ROM genrica
28 Memoria RAM
29 Puertas triestado
30 Hacia el microprocesador y ms
all
Clone this wiki locally

https://github.com/Obijuan/open-fpga-ve

Descripcin de la interfaz

Clone in Desktop

La unidad tiene 3 entradas y 2 salidas:

converted by Web2PDFConvert.com

Entradas:
clk: Reloj del sistema (12MHz en la ICEstick)
rstn: Reset negado. Cuando rstn es 0, se hace un reset sncrono de la unidad de
transmisin
rx: Linea de recepcin serie. Por donde llegan los datos en serie

Salidas:
rcv: Notificacin de carcter recibido. Es un pulso de 1 ciclo de ancho
data: Dato de recibido (8 bits)

Cronograma
Inicialmente, cuando la lnea est en reposo y no se ha recibido nada, la seal rcv est a 0. Al
recibirse el bit de start por rx, el receptor comienza a funcionar, leyendo los siguientes bits y
almacenndolos internamente en su registro de desplazamiento. En el instante t1, cuando se ha
recibido el bit de stop, el dato se captura y se saca por la salida data. En el siguiente ciclo de
reloj, instante t2 (en el cronograma el tiempo se ha exagerado para que se aprecie), aparece un
pulso de un ciclo de reloj de anchura (exagerado tambin en el dibujo) que permita capturar el dato
en un registro externo.

Esta interfaz es muy cmoda. Para usar uart-rx en nuestros diseos, slo hay que conectar la
salida data a la entrada de datos de un registro y la seal rcv usarla como habilitacin. El dato
recibido se capturar automticamente. Esta seal rcv tambin la podemos usar en los
controladores para saber cundo se ha recibido un dato nuevo.

Diagrama de bloques
El diagrama de bloques completo del receptor se muestra en la siguiente figura:

converted by Web2PDFConvert.com

Ruta de datos
La seal rx se registra, para cumplir con las normas de diseo sncrono, y se introduce por el bit
ms significativo de un registro de desplazamiento de 10 bits. El desplazamiento se realiza
cuando llega un pulso por la seal clk_baud, proveniente del generador de baudios. Este
generador slo funciona cuando la miroorden bauden est activada.
Un contador de 4 bits realiza la cuenta de los bits recibidos (cuenta cada pulso de clk_baud). Se
pone a 0 con la microrden clear
Por ltimo tenemos el controlador, que genera las micrordenes baudgen, load, clear y la seal
de interfaz rcv. La seal load se activa para que el dato recibido se almacene en el registro de
datos de 8 bits, de manera que se mantenga estable durante la recepcin del siguiente carcter

baudgen_rx: Generador de baudios para recepcin


El receptor tiene su propio generador de baudios que es diferente al del transmisor. En el
transmisor, al activar su generador con la microorden bauden, emite inmediatamente un pulso. Sin
embargo, en el receptor, se emite en la mitad del periodo. De esta forma se garantiza que el dato
se lee en la mitad del periodo, donde es mucho ms estable (y la probabilidad de error es mejor)

En el cronograma se puede ver cmo al recebir el flanco de bajada del bit de start bauden se
activa, para que comience a funcionar el reloj del receptor. Sin embargo, hasta que no ha
alcanzado la mitad del periodo de bit no se pone a 1. A partir de entonces, los pulsos coinciden
con la mitad de los periodos de los bits recibidos

converted by Web2PDFConvert.com

Controlador
El controlador est modelado como una mquina de 4 estados:

Los estados son:

IDLE: Estado de reposo. Esperando a recibir el bit de start por rx. En cuanto se recibe se pasa
al siguiente estado
RCV: Recibiendo datos. Se activa el temporizador de bits mediante la microorden baudgen y
se van recibiendo todos los bits, que se almacenan en el registro de desplazamiento. Cuando
se han recibido 10 bits (1 de start + 8 de datos + 1 de stop) la salida del contador (bitc) estar
a 10 y se pasa al siguiente estado
LOAD: Almacenamiento del dato recibido. Se activa la microorden load para guardar el dato
recibido (8 bits) en el registro de datos
DAV: (Data AVailable). Sealizacin de que existe un dato disponible. Se pone a uno la seal
rcv para que los circuitos externos puedan capturar el dato

Descripcin en verilog
La unidad de recepcin se compone de dos ficheros: el generador de baudios de recepcin
(baudgen_rx.v) y el propio receptor (uart_rx.v)

baudgen_rx.v
Este componente es similar al generador de baudios del transmisor, pero una vez habilitado el pulso
se enva transcurrida la mitad del periodo
El cdigo verilog es el siguiente:

converted by Web2PDFConvert.com

//-- Fichero: baudgen_rx.v


`include "baudgen.vh"
//-- ENTRADAS:
//--clk: Senal de reloj del sistema (12 MHZ en la iceStick)
//--clk_ena: Habilitacion.
//-1. funcionamiento normal. Emitiendo pulsos
//-0: Inicializado y parado. No se emiten pulsos
//
//-- SALIDAS:
//-- clk_out. Seal de salida para lograr la velocidad en baudios indicada
//-Anchura de 1 periodo de clk. SALIDA NO REGISTRADA
module baudgen_rx(input wire clk,
input wire clk_ena,
output wire clk_out);
//-- Valor por defecto de la velocidad en baudios
parameter M = `B115200;
//-- Numero de bits para almacenar el divisor de baudios
localparam N = $clog2(M);
//-- Valor para llegar a la mitad del periodo
localparam M2 = (M >> 1);
//-- Registro para implementar el contador modulo M
reg [N-1:0] divcounter = 0;
//-- Contador mdulo M
always @(posedge clk)
if (clk_ena)
//-- Funcionamiento normal
divcounter <= (divcounter == M - 1) ? 0 : divcounter + 1;
else
//-- Contador "congelado" al valor maximo
divcounter <= M - 1;
//-- Sacar un pulso de anchura 1 ciclo de reloj si el generador
//-- esta habilitado (clk_ena == 1)
//-- en caso contrario se saca 0
assign clk_out = (divcounter == M2) ? clk_ena : 0;
endmodule

uart_rx.v
Descripcin en verilog de la unidad de recepcin:
//-- Fichero: uart_rx.v
`default_nettype none
`include "baudgen.vh"
module uart_rx (input wire
input wire
input wire
output reg
output reg

clk,
rstn,
rx,
rcv,
[7:0] data);

//-//-//-//-//--

Reloj del sistema


Reset
Linea de recepcion serie
Indicar Dato disponible
Dato recibo

//-- Parametro: velocidad de recepcion


parameter BAUD = `B115200;
//-- Reloj para la recepcion
wire clk_baud;
//-- Linea de recepcion registrada
//-- Para cumplir reglas de diseo sincrono
converted by Web2PDFConvert.com

//-- Para cumplir reglas de diseo sincrono


reg rx_r;
//-- Microordenes
reg bauden; //-- Activar seal de reloj de datos
reg clear; //-- Poner a cero contador de bits
reg load;
//-- Cargar dato recibido

//------------------------------------------------------------------//-RUTA DE DATOS
//------------------------------------------------------------------//-- Registrar la seal de recepcion de datos
//-- Para cumplir con las normas de diseo sincrono
always @(posedge clk)
rx_r <= rx;
//-- Divisor para la generacion del reloj de llegada de datos
baudgen_rx #(BAUD)
baudgen0 (
.clk(clk),
.clk_ena(bauden),
.clk_out(clk_baud)
);
//-- Contador de bits
reg [3:0] bitc;
always @(posedge clk)
if (clear)
bitc <= 4'd0;
else if (clear == 0 && clk_baud == 1)
bitc <= bitc + 1;

//-- Registro de desplazamiento para almacenar los bits recibidos


reg [9:0] raw_data;
always @(posedge clk)
if (clk_baud == 1) begin
raw_data = {rx_r, raw_data[9:1]};
end
//-- Registro de datos. Almacenar el dato recibido
always @(posedge clk)
if (rstn == 0)
data <= 0;
else if (load)
data <= raw_data[8:1];
//------------------------------------//-- CONTROLADOR
//------------------------------------localparam IDLE = 2'd0; //-- Estado de reposo
localparam RECV = 2'd1; //-- Recibiendo datos
localparam LOAD = 2'd2; //-- Almacenamiento del dato recibido
localparam DAV = 2'd3; //-- Sealizar dato disponible
reg [1:0] state;
//-- Transiciones entre estados
always @(posedge clk)
if (rstn == 0)
state <= IDLE;
else
case (state)
//-- Resposo
IDLE :
converted by Web2PDFConvert.com

IDLE :
//-- Al llegar el bit de start se pasa al estado siguiente
if (rx_r == 0)
state <= RECV;
else
state <= IDLE;
//--- Recibiendo datos
RECV:
//-- Vamos por el ultimo bit: pasar al siguiente estado
if (bitc == 4'd10)
state <= LOAD;
else
state <= RECV;
//-- Almacenamiento del dato
LOAD:
state <= DAV;
//-- Sealizar dato disponible
DAV:
state <= IDLE;
default:
state <= IDLE;
endcase

//-- Salidas de microordenes


always @* begin
bauden <= (state == RECV) ? 1 : 0;
clear <= (state == IDLE) ? 1 : 0;
load <= (state == LOAD) ? 1 : 0;
rcv <= (state == DAV) ? 1 : 0;
end

endmodule

Ejemplo 1: Visualizando en los leds


Como primer ejemplo de uso de la unidad de recepcin, haremos un circuito que captura en un
registro el dato recibido por el puerto serie, a la velocidad de 115200 baudios y sus 4 bits menos
significativos los saca por los leds rojos de la placa ICEstick
La lnea rx se enva directamente al led verde para ver la actividad (se enva negada para que
normalmente est el led apagado, y cuando se reciban caracteres parpadee)

rxleds.v: Descripcin
El Diagrama de bloques del circuito se muestra a continuacin:

converted by Web2PDFConvert.com

Simplemente se instancia la unidad de recepcin y se colocan un inicializador para hacer el


reset y un registro para capturar el dato recibido. Este registro tiene un enable para capturar
cuando se reciba el dato (indicndose por la seal rcv)
Descripcin del cdigo en verilog:

converted by Web2PDFConvert.com

`default_nettype none
`include "baudgen.vh"
//-- Top design
module rxleds(input wire clk,
input wire rx,
output reg [3:0] leds,
output wire act);

//-//-//-//--

Reloj del sistema


Linea de recepcion serie
4 leds rojos
Led de actividad (verde)

//-- Parametro: Velocidad de transmision


localparam BAUD = `B115200;
//-- Seal de dato recibido
wire rcv;
//-- Datos recibidos
wire [7:0] data;
//-- Seal de reset
reg rstn = 0;
//-- Inicializador
always @(posedge clk)
rstn <= 1;
//-- Instanciar la unidad de recepcion
uart_rx #(BAUD)
RX0 (.clk(clk),
//-- Reloj del sistema
.rstn(rstn),
//-- Seal de reset
.rx(rx),
//-- Linea de recepcin de datos serie
.rcv(rcv),
//-- Seal de dato recibido
.data(data)
//-- Datos recibidos
);
//-- Sacar los 4 bits menos significativos del dato recibido por los leds
//-- El dato se registra
always @(posedge clk)
//-- Capturar el dato cuando se reciba
if (rcv == 1'b1)
leds <= data[3:0];
//-- Led de actividad
//-- La linea de recepcion negada se saca por el led verde
assign act = ~rx;
endmodule

Simulacin
El banco de pruebas genera el reloj del sistema y enva dos caracteres en serie. Para facilitar el
envo y poder realizar bancos de pruebas ms elaborados, que puedan enviar mayor cantidad de
datos, se ha creado la tarea send_car. En Verilog, las tareas son como las funciones en C (pero sin
devolver ningn valor). Permiten reutilizar el cdigo y hacer que los bancos de prueba sean ms
sencillos y legibles
El cdigo de send_car es:

converted by Web2PDFConvert.com

task send_car;
input [7:0]
begin
rx <= 0;
#BITRATE rx
#BITRATE rx
#BITRATE rx
#BITRATE rx
#BITRATE rx
#BITRATE rx
#BITRATE rx
#BITRATE rx
#BITRATE rx
#BITRATE rx
end
endtask

car;

<=
<=
<=
<=
<=
<=
<=
<=
<=
<=

car[0];
car[1];
car[2];
car[3];
car[4];
car[5];
car[6];
car[7];
1;
1;

//-//-//-//-//-//-//-//-//-//-//--

Bit start
Bit 0
Bit 1
Bit 2
Bit 3
Bit 4
Bit 5
Bit 6
Bit 7
Bit stop
Esperar a que se envie bit de stop

Recibe como argumento un carcter de 8 bits y saca por la seal rx la trama serie, comenzando
por el bit de start, luego los de datos y finalmente el bit de stop. Se hace a la velocidad indicada por
el parametro BITRATE que se define en funcin de la velocidad en baudios.
Para enviar un caracter slo hay que invocar a la tarea y pasar este caracter como parmetro. Por
ejemplo, para enviar una "A" en ascii slo habra que ejecutar:
senc_car("A");
El cdigo completo del banco de pruebas es el siguiente:
//-- Fichero rxleds_tb.v
`include "baudgen.vh"
module rxleds_tb();
localparam BAUD = `B115200;
//-- Tics de reloj para envio de datos a esa velocidad
//-- Se multiplica por 2 porque el periodo del reloj es de 2 unidades
localparam BITRATE = (BAUD << 1);
//-- Tics necesarios para enviar una trama serie completa, mas un bit adicional
localparam FRAME = (BITRATE * 10);
//-- Tiempo entre dos bits enviados
localparam FRAME_WAIT = (BITRATE * 4);
//---------------------------------------//-- Tarea para enviar caracteres serie
//---------------------------------------task send_car;
input [7:0] car;
begin
rx <= 0;
//-- Bit start
#BITRATE rx <= car[0]; //-- Bit 0
#BITRATE rx <= car[1]; //-- Bit 1
#BITRATE rx <= car[2]; //-- Bit 2
#BITRATE rx <= car[3]; //-- Bit 3
#BITRATE rx <= car[4]; //-- Bit 4
#BITRATE rx <= car[5]; //-- Bit 5
#BITRATE rx <= car[6]; //-- Bit 6
#BITRATE rx <= car[7]; //-- Bit 7
#BITRATE rx <= 1;
//-- Bit stop
#BITRATE rx <= 1;
//-- Esperar a que se envie bit de stop
end
endtask
//-- Registro para generar la seal de reloj
reg clk = 0;

converted by Web2PDFConvert.com

//-- Cables para las pruebas


reg rx = 1;
wire act;
wire [3:0] leds;
//-- Instanciar el modulo rxleds
rxleds #(BAUD)
dut(
.clk(clk),
.rx(rx),
.act(act),
.leds(leds)
);
//-- Generador de reloj. Periodo 2 unidades
always
# 1 clk <= ~clk;

//-- Proceso al inicio


initial begin
//-- Fichero donde almacenar los resultados
$dumpfile("rxleds_tb.vcd");
$dumpvars(0, rxleds_tb);
//-- Enviar datos de prueba
#BITRATE
send_car(8'h55);
#FRAME_WAIT send_car("K");
#(FRAME_WAIT*4) $display("FIN de la simulacion");
$finish;
end

Se envan dos caracteres de prueba. Primero el 0x55, que en binario es 01010101 (se alternan los
ceros y los unos). El segundo es el carcter K
Para realizar la simulacin ejecutamos el comando:
$ make sim

Y el resultado en gtkwave es:

La simulacin comienza con la lnea rx en reposo (a 1) y a continuacin se enva el valor 0x55 en


serie al receptor. Cuando se ha terminado se ve en la simulacin cmo aparece un pulso en la
seal rcv y cmo el valor 0x55 se guarda en el registro de datos (data). Adems, por los leds se
sacan los 4 bits menos significativos (que tienen el valor 5 en hexadecimal).
A continuacin, pasado un tiempo, se enva el carcter (K), y comprobamos que se recibe
correctamente

converted by Web2PDFConvert.com

Sntesis y pruebas
Hacemos la sntesis con el siguiente comando:
$ make sint

Los recursos empleados son:

Recurso

ocupacin

PIOs

7 / 96

PLBs

18 / 160

BRAMs

0 / 16

y lo cargamos en la FPGA con:


$ sudo iceprog rxleds.bin

Abrimos el gtkterm y lo configuramos a 115200 baudios. Si pulsamos teclas, veremos cmo


cambian los leds de la ICEstick. Por ejemplo, si pulsamos el 7, se enva el nmero 0x37, cuyos 4 bits
menos significativos coinciden con el nmero 7 (el cdigo ASCII se diseo adrede para cumplir con
esta propiedad). En binario es 0111. Veremos cmo se encienden los leds 0, 1 y 3.

Si ahora pulsamos la tecla 0, todos los leds estarn apagados


En este vdeo de youtube se puede ver el ejemplo en accin:

converted by Web2PDFConvert.com

Ejemplo 2: eco
Este segundo ejemplo es el clsico programa de "eco": que transmite todo lo que recibe. Es una
manera de comprobar que los caracteres se estn recibiendo correctamente

Descripcin
El diagrama de bloques se muestra a continuacin:

Slo se instancian la unidad de transmisin y recepcin, y se conectan de manera que lo recibido por
una llegue a la otra
El cdigo verilog es el siguiente:

converted by Web2PDFConvert.com

`default_nettype none
`include "baudgen.vh"
//-- Top design
module echo(input wire clk,
input wire rx,
output wire tx
);

//-- Reloj del sistema


//-- Linea de recepcion serie
//-- Linea de transmision serie

//-- Parametro: Velocidad de transmision


localparam BAUD = `B115200;
//-- Seal de dato recibido
wire rcv;
//-- Datos recibidos
wire [7:0] data;
//-- Seal de reset
reg rstn = 0;
//-- Seal de transmisor listo
wire ready;
//-- Inicializador
always @(posedge clk)
rstn <= 1;
//-- Instanciar la unidad de recepcion
uart_rx #(BAUD)
RX0 (.clk(clk),
//-- Reloj del sistema
.rstn(rstn),
//-- Seal de reset
.rx(rx),
//-- Linea de recepcin de datos serie
.rcv(rcv),
//-- Seal de dato recibido
.data(data)
//-- Datos recibidos
);
//-- Instanciar la unidad
uart_tx #(BAUD)
TX0 ( .clk(clk),
.rstn(rstn),
.start(rcv),
.data(data),
.tx(tx),
.ready(ready)
);

de transmision
//-//-//-//-//-//--

Reloj del sistema


Reset global (activo nivel bajo)
Comienzo de transmision
Dato a transmitir
Salida de datos serie (hacia el PC)
Transmisor listo / ocupado

endmodule

Simulacin
El banco de pruebas es similar al del ejemplo anterior: enva dos caracteres
`include "baudgen.vh"

module echo_tb();
localparam BAUD = `B115200;
//-- Tics de reloj para envio de datos a esa velocidad
//-- Se multiplica por 2 porque el periodo del reloj es de 2 unidades
localparam BITRATE = (BAUD << 1);
//-- Tics necesarios para enviar una trama serie completa, mas un bit adicional
localparam FRAME = (BITRATE * 10);
converted by Web2PDFConvert.com

//-- Tiempo entre dos bits enviados


localparam FRAME_WAIT = (BITRATE * 4);

//---------------------------------------//-- Tarea para enviar caracteres serie


//---------------------------------------task send_car;
input [7:0] car;
begin
rx <= 0;
//-- Bit start
#BITRATE rx <= car[0]; //-- Bit 0
#BITRATE rx <= car[1]; //-- Bit 1
#BITRATE rx <= car[2]; //-- Bit 2
#BITRATE rx <= car[3]; //-- Bit 3
#BITRATE rx <= car[4]; //-- Bit 4
#BITRATE rx <= car[5]; //-- Bit 5
#BITRATE rx <= car[6]; //-- Bit 6
#BITRATE rx <= car[7]; //-- Bit 7
#BITRATE rx <= 1;
//-- Bit stop
#BITRATE rx <= 1;
//-- Esperar a que se envie bit de stop
end
endtask

//-- Registro para generar la seal de reloj


reg clk = 0;

//-- Cables para las pruebas


reg rx = 1;
wire tx;
//-- Instanciar el modulo rxleds
echo #(BAUD)
dut(
.clk(clk),
.rx(rx),
.tx(tx)
);
//-- Generador de reloj. Periodo 2 unidades
always
# 1 clk <= ~clk;

//-- Proceso al inicio


initial begin
//-- Fichero donde almacenar los resultados
$dumpfile("echo_tb.vcd");
$dumpvars(0, echo_tb);
//-- Enviar datos de prueba
#BITRATE
send_car(8'h55);
#(FRAME_WAIT*3) send_car("K");
#(FRAME_WAIT*4) $display("FIN de la simulacion");
$finish;
end
endmodule

Para realizar la simulacin ejecutamos el comando:


$ make sim2

converted by Web2PDFConvert.com

El resultado en gtkwave es:

Se observa cmo en cuanto llega un caracter se vuelve a enviar de vuelta

Sntesis y pruebas
Hacemos la sntesis con el siguiente comando:
$ make sint2

Los recursos empleados son:

Recurso

ocupacin

PIOs

10 / 96

PLBs

44 / 160

BRAMs

0 / 16

y lo cargamos en la FPGA con:


$ sudo iceprog echo.bin

Abrimos el gtkterm y lo configuramos a 115200 baudios. Todo lo que escribamos se enviar a la


FPGA y se mostrar de vuelta en la pantalla

Ejercicios propuestos
TODO

Conclusiones
converted by Web2PDFConvert.com

TODO

FPGA Libres: [Wiki] [Repo]

2016 GitHub, Inc. Terms Privacy Security Contact Help

Status API Training Shop Blog About

converted by Web2PDFConvert.com

Vous aimerez peut-être aussi