Teach Lecciones con laboratorios remotos

Lección Teach

Nios V en la DE1-SoC (4/5): visualizador HEX y temporizador

El alumnado compila y carga ejemplos en C para Nios V destinados a HEX0 y al temporizador de intervalo, y observa el comportamiento de HEX0 y LEDR0 en la DE1-SoC.

  • Nios V para DE1-SoC
  • 75 min
  • Primeros cursos universitarios de informática, electrónica o ingeniería de computadores
  • Español
  • Sistemas digitales y FPGA · Sistemas embebidos

¿Primera vez que activas Teach? Puedes realizar una sesión de clase sin costo. El alumnado entra con un código de clase.

Diagrama de flujo: el programa Nios V escribe en HEX3_HEX0 (0xFF200020), cuyo byte inferior controla HEX0, y configura el temporizador de intervalo (base 0xFF202000); cuando TO pasa a 1, el programa lo detecta, lo borra y conmuta LEDR0
Nios V para DE1-SoC · Ver información del laboratorio

Resultados de aprendizaje

  • Usar los periféricos de visualizador y temporizador mapeados en memoria y validados en el sistema Nios V fijo.

  • Explicar por qué los visualizadores de siete segmentos necesitan patrones de segmentos codificados.

  • Configurar y sondear el temporizador de intervalo de la FPGA en 0xFF202000.

  • Distinguir las entradas lógicas NB0..NB3 validadas por JP1/GPIO de la ruta del puerto KEY de FPGAcademy, a la que no llegan los controles KEY actuales del navegador.

  • Recoger evidencias en directo del comportamiento de los periféricos en una DE1-SoC real.

Vista previa de la actividad del estudiante

Contenido de la actividad

Solo vista previa. En una sesión de clase, los estudiantes pueden completar respuestas y entregar su trabajo al docente.

1

Del GPIO a los periféricos

5 min

En las lecciones anteriores usaste E/S mapeada en memoria para controles sencillos: entradas NSW del navegador, datos GPIO de JP1 y salidas LEDR. Esta lección aplica la misma idea a dos periféricos más completos ya incluidos en el sistema FPGA fijo.

Un periférico es un bloque de hardware que el procesador Nios V controla mediante lecturas y escrituras en una dirección concreta. No modificarás el diseño de la FPGA. Sustituirás main.c por pequeños ejemplos en C, compilarás un ELF, lo cargarás y comprobarás si el comportamiento de la placa coincide con la explicación de los registros.

Los dos ejemplos obligatorios son:

- hex_counter, que escribe patrones codificados en HEX0.
- timer_blink, que configura el temporizador de intervalo y conmuta LEDR0.

Para consultar el mapa completo de registros, usa el manual de usuario FPGAcademy DE1-SoC Computer with Nios V. Esta actividad proporciona el subconjunto necesario: HEX3_HEX0 en 0xFF200020 y el temporizador de intervalo en 0xFF202000.

Diagrama de flujo: el programa Nios V escribe en HEX3_HEX0 (0xFF200020), cuyo byte inferior controla HEX0, y configura el temporizador de intervalo (base 0xFF202000); cuando TO pasa a 1, el programa lo detecta, lo borra y conmuta LEDR0

Esta lección usa dos rutas de registro validadas del sistema Nios V fijo: la salida del visualizador HEX y la temporización del LED mediante el temporizador de intervalo.

El navegador muestra controles de botón lógicos específicos de Nios llamados NB0..NB3. Son entradas JP1/GPIO validadas, no el registro KEY de FPGAcademy en 0xFF200050.

Para el trabajo obligatorio, usa los ejemplos de HEX y temporizador que aparecen a continuación. La sección opcional de botones es autosuficiente si se asigna: utiliza NB0..NB3 como entradas lógicas de JP1 y evita la nomenclatura KEY0..KEY3.

Considera que un periférico está preparado para el curso solo cuando existe evidencia en directo para el perfil actual del laboratorio de LabsLand. Un registro puede existir en el sistema de referencia y aun así no ser adecuado para una actividad remota si la ruta de controles del navegador no está conectada a él.

2

Registro de salida HEX

22 min

Los visualizadores HEX son de siete segmentos. Un dígito no se escribe como el número 3, sino como un patrón de bits que enciende o apaga cada segmento.

El ejemplo hex_counter escribe patrones de segmentos en HEX3_HEX0, situado en 0xFF200020.

Cada byte de HEX3_HEX0 controla un visualizador. Este programa solo usa el byte inferior, por lo que únicamente cambia HEX0. Un valor como 0x3F no es el número cero en el sentido habitual: es el patrón que enciende los segmentos necesarios para dibujar 0.

Ejemplos:

- El dígito 0 usa el patrón 0x3F.
- El dígito 1 usa el patrón 0x06.
- El dígito A usa el patrón 0x77.

  1. Abre Nios V C IDE for DE1-SoC.

  2. Sustituye el código inicial por el código de hex_counter siguiente.

  3. Haz clic en Build ELF y, después, en Enviar a la FPGA.

  4. Observa HEX0 en la vista de la placa hasta ver al menos dos dígitos distintos.

  5. Anota si HEX0 cambia recorriendo valores hexadecimales.

Usa este código para hex_counter:

Selecciona el bloque completo antes de copiarlo en main.c; debes sustituir todo el código inicial.

/* DE1-SoC Computer with Nios V -- E/S mapeada en memoria */
volatile int *HEX3_HEX0 = (int *) 0xFF200020;  /* 7 segmentos: HEX3..HEX0 */

static const unsigned char HEX_CODE[16] = {
    0x3F, 0x06, 0x5B, 0x4F,
    0x66, 0x6D, 0x7D, 0x07,
    0x7F, 0x67, 0x77, 0x7C,
    0x39, 0x5E, 0x79, 0x71
};

static void delay(void)
{
    volatile int i;
    for (i = 0; i < 2000000; i++) {
    }
}

int main(void)
{
    int count = 0;

    while (1) {
        *HEX3_HEX0 = HEX_CODE[count & 0xF];
        count++;
        delay();
    }
    return 0;
}

Usa la tabla para registrar lo observado después de cargar hex_counter. El comportamiento esperado ya está incluido. Añade dos dígitos o patrones distintos vistos en HEX0 y selecciona correcto, fallo o no concluyente como resultado.

Registra una comprobación de HEX0 en la placa en directo. Conserva el comportamiento esperado salvo que el docente pida otra prueba, anota dos dígitos o patrones observados y selecciona correcto, fallo o no concluyente.

Comportamiento esperado Primer dígito o patrón observado Segundo dígito o patrón observado Resultado (correcto/fallo/no concluyente)

¿Por qué usa el ejemplo una tabla de consulta de patrones de segmentos en vez de escribir directamente en el registro HEX los valores enteros 0, 1, 2, etc.?

3

Temporizador de intervalo

22 min

El ejemplo timer_blink programa el temporizador de intervalo de la FPGA con dirección base 0xFF202000. Establece un periodo, inicia el temporizador, sondea el bit de fin de periodo, lo borra y conmuta LEDR0.

El reloj del temporizador es de 100 MHz, por lo que 50.000.000 de ciclos equivalen aproximadamente a medio segundo. El periodo de 32 bits se divide en dos registros de 16 bits porque la interfaz del temporizador almacena por separado las mitades inferior y superior.

Registros del temporizador utilizados:

- STATUS en el desplazamiento +0x0: el bit 0, TO, pasa a 1 cuando termina el periodo.
- CONTROL en el desplazamiento +0x4: STOP, START y CONT controlan si el temporizador funciona de forma continua.
- PERIOD_LO en el desplazamiento +0x8: 16 bits inferiores del periodo.
- PERIOD_HI en el desplazamiento +0xC: 16 bits superiores del periodo.

  1. Sustituye el código C por el código de timer_blink siguiente.

  2. Haz clic en Build ELF y, después, en Enviar a la FPGA.

  3. Observa LEDR0 durante al menos 10 segundos.

  4. Registra al menos dos momentos en que cambie el estado del LED.

  5. Estima si el parpadeo es lo bastante estable para utilizarlo como fuente de temporización.

Usa este código para timer_blink:

Selecciona el bloque completo antes de copiarlo en main.c; debes sustituir todo el código anterior.

/* DE1-SoC Computer with Nios V -- E/S mapeada en memoria */
volatile int *LEDS = (int *) 0xFF200000;  /* LEDs rojos */

#define TIMER_BASE      0xFF202000
#define TIMER_STATUS    (*(volatile short *)(TIMER_BASE + 0x0))
#define TIMER_CONTROL   (*(volatile short *)(TIMER_BASE + 0x4))
#define TIMER_PERIOD_LO (*(volatile short *)(TIMER_BASE + 0x8))
#define TIMER_PERIOD_HI (*(volatile short *)(TIMER_BASE + 0xC))

#define TIMER_TO        0x1
#define TIMER_CONT      0x2
#define TIMER_START     0x4
#define TIMER_STOP      0x8

int main(void)
{
    const unsigned int half_second = 50000000u;  /* reloj del temporizador a 100 MHz */
    int led = 0;

    TIMER_CONTROL = TIMER_STOP;
    TIMER_PERIOD_LO = (short)(half_second & 0xFFFFu);
    TIMER_PERIOD_HI = (short)((half_second >> 16) & 0xFFFFu);
    TIMER_STATUS = 0;  /* borrar TO */
    TIMER_CONTROL = TIMER_CONT | TIMER_START;

    while (1) {
        if ((TIMER_STATUS & TIMER_TO) != 0) {
            TIMER_STATUS = 0;  /* borrar TO */
            led ^= 1;
            *LEDS = led;
        }
    }
    return 0;
}

Usa la tabla para registrar el parpadeo controlado por el temporizador. Conserva la ventana de 10 segundos salvo que el docente pida una prueba más larga. En la columna de evidencia, escribe qué cambió —por ejemplo, apagado -> encendido -> apagado—, valora si la temporización parece lo bastante estable para el uso previsto y selecciona después correcto, fallo o no concluyente.

Registra una observación del temporizador. Usa una ventana de 10 segundos, describe los cambios de estado de LEDR0 que hayas visto, valora la estabilidad aparente de la temporización y selecciona correcto, fallo o no concluyente.

Ventana de observación (s) Cambios de estado observados en LEDR0 Comportamiento esperado Estabilidad aparente de la temporización Resultado (correcto/fallo/no concluyente)

¿En qué se diferencia este parpadeo controlado por el temporizador de un bucle de espera por software? Explica cómo PERIOD_LO y PERIOD_HI establecen el periodo, cómo START y CONT en CONTROL inician el funcionamiento continuo, cómo el programa detecta y borra TO en STATUS, y una razón por la que un temporizador de hardware puede resultar útil en software para sistemas empotrados.

4

Pequeña modificación de un periférico

18 min

Elige uno de los ejemplos validados y realiza un cambio pequeño y observable.

Ejemplos:

- En hex_counter, cambia la secuencia para que cuente solo valores hexadecimales pares.
- En hex_counter, controla dos dígitos HEX en vez de solo HEX0.
- En timer_blink, cambia el periodo para que LEDR0 parpadee más deprisa o más despacio.
- En timer_blink, haz conmutar otro bit de LEDR.
- Trabajo opcional con botones: lee los bits 0 a 3 de JP1 desde NB0..NB3 y muéstralos en LEDR0..LEDR3.

  1. Elige el ejemplo HEX o el del temporizador.

  2. Realiza un cambio pequeño en el código.

  3. Haz clic en Build ELF y, después, en Enviar a la FPGA.

  4. Observa la placa y anota cómo cambió el comportamiento.

Entrega las líneas de código modificadas e indica a qué registro mapeado en memoria afecta cada una.

El cambio debe ser lo bastante pequeño para validarlo en una sola sesión con la placa. Una buena entrega modifica un comportamiento y permite comprobarlo con una o dos observaciones.

Entrega una nota de observación breve: qué cambiaste, qué esperabas ver y qué mostró la placa en directo.

5

Opcional: botones lógicos NB

Los botones lógicos remotos NB0..NB3 están validados mediante los bits 0 a 3 del registro de datos de JP1. Son útiles para un ejercicio rápido de sondeo, pero no son el puerto KEY de FPGAcademy ni acceden a su registro de datos mediante los controles actuales del navegador.

Patrón mínimo en C:

volatile int *LEDS = (int *) 0xFF200000;
volatile int *JP1 = (int *) 0xFF200060;
volatile int *JP1_DIR = (int *) 0xFF200064;

int main(void)
{
    *JP1_DIR = 0;
    while (1) {
        *LEDS = (*JP1) & 0xF;   // NB0..NB3 -> LEDR0..LEDR3
    }
    return 0;
}

¿Por qué lee este ejercicio opcional los bits 0 a 3 de JP1 en vez del registro KEY de FPGAcademy situado en 0xFF200050?

Si realizas el ejercicio opcional, anota en qué botón NB has hecho clic y qué bit de LEDR ha cambiado.

6

Preparar el proyecto final

8 min

El proyecto final debe usar NSW0..NSW9 y LEDR0..LEDR9, además de al menos un periférico de extensión validado en esta lección.

¿Qué periférico de extensión es más probable que uses en el proyecto final?

Describe un comportamiento para el proyecto final que combine NSW/LEDR con el periférico de extensión elegido. Incluye la dirección o direcciones de registro que esperas utilizar.

Convierte esta vista previa en una sesión de clase real

Activa LabsLand Teach para usar esta lección con tus estudiantes. La primera vez que actives Teach, podrás realizar una sesión de clase sin costo.