Teach lesson
Nios V na DE1-SoC (4/5): display HEX e temporizador
Compile e envie exemplos em C para o HEX0 e o temporizador de intervalo do Nios V e observe o comportamento de HEX0 e LEDR0 na DE1-SoC.
New to LabsLand? Create your teacher account
Learning Outcomes
Usar periféricos validados de display e temporizador mapeados em memória no sistema Nios V fixo.
Explicar por que displays de sete segmentos precisam de padrões de segmentos codificados.
Configurar e consultar o temporizador de intervalo da FPGA em
0xFF202000.Distinguir as entradas lógicas validadas
NB0..NB3via JP1/GPIO do caminho não compatível das teclas KEY da FPGAcademy no navegador.Coletar evidências ao vivo do comportamento dos periféricos em uma placa DE1-SoC real.
Student activity preview
Activity Content
Preview only. In a class session, students can fill in responses and submit their work to the teacher.
De GPIO a periféricos
5 min
Nas lições anteriores, você usou E/S mapeada em memória com controles simples: entradas NSW do navegador, dados GPIO do JP1 e saídas LEDR. Esta lição mantém a mesma ideia, mas usa dois periféricos mais completos já incorporados ao sistema fixo da FPGA.
Um periférico é um bloco de hardware que o processador Nios V controla ao ler ou gravar um endereço específico. Você não modificará o projeto da FPGA nesta lição. Substituirá main.c por pequenos exemplos em C, compilará um arquivo ELF, enviará esse arquivo e verificará se o comportamento da placa corresponde à explicação no nível dos registradores.
Os dois exemplos obrigatórios são:
- hex_counter, que grava padrões codificados em HEX0.
- timer_blink, que configura o temporizador de intervalo e alterna LEDR0.
Para consultar o mapa completo de registradores, use o manual FPGAcademy DE1-SoC Computer with Nios V. Esta atividade apresenta o subconjunto necessário: HEX3_HEX0 em 0xFF200020 e o temporizador de intervalo em 0xFF202000.
Esta lição usa dois caminhos de registradores validados do sistema Nios V fixo: a saída do display HEX e a temporização de LED controlada pelo temporizador de intervalo.
O navegador mostra controles de botões lógicos específicos do Nios V, com os rótulos NB0..NB3. Essas são entradas validadas via JP1/GPIO, e não o registrador KEY da FPGAcademy em 0xFF200050.
Para o trabalho obrigatório desta lição, use os exemplos de HEX e temporizador abaixo. A seção opcional de botões é independente caso seja atribuída: use NB0..NB3 como entradas lógicas do JP1 e evite a nomenclatura KEY0..KEY3.
Considere um periférico pronto para o curso somente quando houver evidência ao vivo no perfil atual do laboratório LabsLand. Um registrador pode existir no sistema de referência e ainda assim não servir para uma atividade remota se o caminho do controle no navegador não estiver conectado a ele.
Registrador de saída HEX
22 min
Os displays HEX são displays de sete segmentos. Um dígito não é gravado como o número 3; ele é gravado como um padrão de bits que acende ou apaga segmentos individuais.
O exemplo hex_counter grava padrões de segmentos em HEX3_HEX0, no endereço 0xFF200020.
Cada byte de HEX3_HEX0 controla um display. Neste programa inicial, somente o byte menos significativo é usado; portanto, apenas HEX0 muda. Um valor como 0x3F não é o número zero no sentido habitual: é o padrão de segmentos que acende os segmentos necessários para formar 0.
Exemplos:
- O dígito 0 usa o padrão 0x3F.
- O dígito 1 usa o padrão 0x06.
- O dígito A usa o padrão 0x77.
Abra
Nios V C IDE for DE1-SoC.Substitua o código inicial pelo código de
hex_counterabaixo.Clique em
Build ELF(Compilar ELF) e envie o arquivo para a FPGA comUpload to FPGA.Observe HEX0 na visualização da placa por pelo menos dois dígitos diferentes.
Registre se HEX0 percorre valores hexadecimais.
Use este código para hex_counter:
Selecione todo o bloco de código antes de copiá-lo para main.c; substitua todo o código inicial.
/* Computador DE1-SoC com Nios V — E/S mapeada em memória */
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;
}
Use a tabela para registrar o que você viu depois de enviar hex_counter. O comportamento esperado já está preenchido. Adicione dois dígitos ou padrões diferentes vistos em HEX0 e selecione passou, falhou ou incerto na coluna de resultado.
Registre uma verificação de HEX0 na placa ao vivo. Mantenha o comportamento esperado, a menos que o professor peça outro teste; anote dois dígitos ou padrões observados e selecione passou, falhou ou incerto.
| Comportamento esperado | Primeiro dígito ou padrão observado | Segundo dígito ou padrão observado | Resultado |
|---|---|---|---|
Por que o exemplo usa uma tabela de consulta de padrões de segmentos em vez de gravar os valores inteiros 0, 1, 2 e assim por diante diretamente no registrador HEX?
Temporizador de intervalo
22 min
O exemplo timer_blink programa o temporizador de intervalo da FPGA no endereço-base 0xFF202000. Ele define um período, inicia o temporizador, consulta o bit de fim de período, limpa esse bit e alterna LEDR0.
O clock do temporizador é de 100 MHz; portanto, 50.000.000 de pulsos correspondem a aproximadamente meio segundo. O período de 32 bits é dividido em dois registradores de 16 bits porque a interface do temporizador armazena separadamente as metades menos e mais significativas.
Registradores do temporizador usados aqui:
- STATUS no deslocamento +0x0: o bit 0, TO, passa a 1 quando o período termina.
- CONTROL no deslocamento +0x4: STOP, START e CONT controlam se o temporizador funciona continuamente.
- PERIOD_LO no deslocamento +0x8: 16 bits menos significativos do período.
- PERIOD_HI no deslocamento +0xC: 16 bits mais significativos do período.
Substitua o código C pelo código de
timer_blinkabaixo.Clique em
Build ELF(Compilar ELF) e envie comUpload to FPGA.Observe
LEDR0por pelo menos 10 segundos.Registre pelo menos dois momentos em que o estado do LED muda.
Avalie se a alternância é estável o bastante para servir como fonte de temporização.
Use este código para timer_blink:
Selecione todo o bloco de código antes de copiá-lo para main.c; substitua todo o código anterior.
/* Computador DE1-SoC com Nios V — E/S mapeada em memória */
volatile int *LEDS = (int *) 0xFF200000; /* LEDs vermelhos */
#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; /* clock do temporizador: 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; /* limpar TO */
TIMER_CONTROL = TIMER_CONT | TIMER_START;
while (1) {
if ((TIMER_STATUS & TIMER_TO) != 0) {
TIMER_STATUS = 0; /* limpar TO */
led ^= 1;
*LEDS = led;
}
}
return 0;
}
Use a tabela para registrar a alternância controlada pelo temporizador. Mantenha a janela de 10 segundos, a menos que o professor solicite um teste mais longo. Na coluna de evidência, escreva o que mudou, por exemplo, apagado -> aceso -> apagado, e selecione passou, falhou ou incerto.
Registre uma observação do temporizador. Use uma janela de 10 segundos, descreva as mudanças de estado observadas em LEDR0 e selecione passou, falhou ou incerto.
| Janela de observação (s) | Mudanças de estado observadas em LEDR0 | Comportamento esperado | Resultado |
|---|---|---|---|
Qual é a diferença entre esta alternância controlada pelo temporizador e um laço de espera por software? Mencione os registradores de período, o bit de fim de período e uma razão pela qual um temporizador de hardware pode ser útil em software embarcado.
Uma pequena modificação no periférico
18 min
Escolha um dos exemplos validados e faça uma mudança pequena e observável.
Exemplos:
- Em hex_counter, mude a sequência para contar somente valores hexadecimais pares.
- Em hex_counter, controle dois dígitos HEX em vez de apenas HEX0.
- Em timer_blink, mude o período para que LEDR0 alterne mais rápido ou mais devagar.
- Em timer_blink, alterne outro bit de LED.
- Trabalho opcional com botões: leia os bits 0 a 3 do JP1 por meio de NB0..NB3 e mostre-os em LEDR0..LEDR3.
Escolha o exemplo de HEX ou de temporizador.
Faça uma pequena alteração no código.
Compile e envie o arquivo ELF.
Observe a placa e registre como o comportamento mudou.
Envie as linhas de código alteradas e identifique qual registrador mapeado em memória cada linha afeta.
Mantenha a modificação pequena o bastante para validá-la em uma única sessão da placa. Uma boa entrega altera um comportamento e pode ser verificada com uma ou duas observações.
Envie uma nota de observação concisa: o que mudou, o que você esperava ver e o que a placa ao vivo mostrou.
Opcional: botões lógicos NB
Os botões lógicos NB0..NB3 foram validados nos bits 0 a 3 do registrador de dados JP1. Eles servem para um exercício rápido de consulta, mas não correspondem à porta KEY3..KEY0 da FPGAcademy.
Padrão mínimo em C:
volatile int *LEDS = (int *) 0xFF200000;
volatile int *JP1 = (int *) 0xFF200060;
volatile int *JP1_DIR = (int *) 0xFF200064;
*JP1_DIR = 0;
while (1) {
*LEDS = (*JP1) & 0xF; // NB0..NB3 -> LEDR0..LEDR3
}Por que este exercício opcional lê os bits 0 a 3 do JP1 em vez de ler o registrador KEY da FPGAcademy em 0xFF200050?
Se você executar o exercício opcional, registre um botão NB que pressionou e o bit de LED que mudou.
Prepare o projeto final
8 min
O projeto final deve usar NSW0..NSW9 e LEDR0..LEDR9, além de pelo menos um periférico de extensão validado nesta lição.
Qual periférico de extensão você provavelmente usará no projeto final?
Descreva um comportamento do projeto final que combine NSW/LEDR com o periférico de extensão escolhido. Inclua o endereço ou os endereços de registradores que pretende usar.