Na continuação da construção do multiplicador 8×8, o objetivo desta etapa é examinar a implementação de uma máquina de estados, não há codificação nesta etapa.
O projeto resolvido desta etapa, pode ser baixado diretamente no github <clicando neste link aqui> e no diretório raiz IVER10_1 temos todos os arquivos e instruções dos exercícios.
Se você caiu de paraquedas por aqui e precisa saber como instalar o software Questa para trabalhar com Verilog, leia a série “Instalando Quartus com Questa”, <clicando neste link aqui>.
Objetivo desta etapa:
Examinar a implementação da máquina de estados.
Até o momento, você montou todos os componentes necessários para construir o multiplicador 8×8 bits, faltando a etapa para controlar a máquina de estados.
Tem um projeto na pasta lab5a chamado “mult_control”.
Neste laboratório você estará mais sozinho, não há instruções passo a passo. O arquivo “mult_control.v” contém a entidade de nível superior junto com algumas outras estruturas, conforme indicado abaixo:
// Declaração do "mult_control" module mult_control ( input clk, reset_a, start, // Declarando entradas "clk", "reset_a", "start", "count" input [1:0] count, output reg [1:0] input_sel, shift_sel, // Declarando signais de saída "in_sel", "shift_sel", output reg [2:0] state_out, // "state_out", "done", "clk_ena" and "sclr_n" output reg done, clk_ena, sclr_n ); // Declarando as variaveis "current_state" and "next_state" para serem variáveis de estado. reg [2:0] current_state, next_state; // Declaração dos parametros e estados, 6 valores: "idle", "lsb", "mid", "msb", "calc_done" and "err" parameter idle=0, lsb=1, mid=2, msb=3, calc_done=4, err=5; // Create processo sequencial para controlar as transições de estado e garantindo que o "current_state" receba o valor de "next state" // na subida de borda do clock. Utilizado para controle de "clear" assíncrono. always @(posedge clk, posedge reset_a) begin if (reset_a) current_state <= idle; else current_state <= next_state; end // Criação do processo combinacional e declarações "case" para determinar o próximo estado, baseado no estado atual e entradas. always @ * case (current_state) idle : if (start) next_state = lsb; else next_state = idle; lsb : if (count == 0 && start == 0) next_state = mid; else next_state = err; mid : if (start == 0 && count == 2) next_state = msb; else if (start == 0 && count == 1) next_state = mid; else next_state = err; msb : if (count == 3 && start == 0) next_state = calc_done; else next_state = err; calc_done : if (!start) next_state = idle; else next_state = err; err : if (start) next_state = lsb; else next_state = err; endcase // Criação do processo para "Mealy output logic" para o "input_sel", "shift_sel", "done", "clk_ena" e "sclr_n" (estado atual e funções de saída) always @* begin // Inicializando as saídas para valores default, então só vai funcionar quando ocorrerem mudanças. input_sel = 2'bxx; shift_sel = 2'bxx; done = 1'b0; clk_ena = 1'b0; sclr_n = 1'b1; case (current_state) idle : if (start) begin clk_ena = 1'b1; sclr_n = 1'b0; end lsb : if (count == 0 && start == 0) begin input_sel = 2'd0; shift_sel = 2'd0; clk_ena = 1'b1; end mid : if (count == 2 && start == 0) begin input_sel = 2'd2; shift_sel = 2'd1; clk_ena = 1'b1; end else if (count == 1 && start == 0) begin input_sel = 1'd1; shift_sel = 1'd1; clk_ena = 1'b1; end msb : if (count == 3 && start == 0) begin input_sel = 2'd3; shift_sel = 2'd2; clk_ena = 1'b1; end calc_done : if (!start) done = 1'b1; err : if (start) begin clk_ena = 1'b1; sclr_n = 1'b0; end endcase end // Criando o processo para "Moore output logic" para o "state_out". always @(current_state) begin // Inicializa "state_out" para seu valor default caso somente cubra quando ele mude. state_out = 3'd0; case (current_state) idle : ; lsb : state_out = 3'd1; mid : state_out = 3'd2; msb : state_out = 3'd3; calc_done : state_out = 3'd4; err : state_out = 3'd5; endcase end endmodule
Esta máquina de estados irá gerenciar todas as operações que ocorrem dentro do multiplicador 8×8,usando 6 estados definidos: “IDLE”, “LSB”, “MID”, “MSB”, “CALC_DONE” e “ERR”. Observe o diagrama de estado da Figura abaixo, com outras definições de seu comportamento.
Caso minhas notas sejam de grande valia para ti, vou ficar muito agradecido se você clicar nos anúncios desta página e conferir o que meus patrocinadores tem para lhe oferecer.
No estado “LSB”:
A máquina de estado multiplica os 4 bits mais baixos dos dois estados de 8 bits. multiplicandos
((a[3..0] * b[3..0] ) * 20 )
E este resultado intermediário é salvo em um acumulador.
No estado “MID”:
A máquina de estado realiza multiplicação cruzada
((a[3..0] * b[7..4] ) * 24 ) e (( a[7..4] * b[3..0] ) * 24 )
Isto é feito em ciclos de clock sucessivos. Os produtos de ambas as operações de multiplicação são somados ao conteúdo do acumulador à medida que são concluídos e enviados de volta para o acumulador.
No estado “MSB”:
A máquina de estado multiplica os 4 bits mais altos dos dois estados de 8 bits. multiplicandos
((a[7..4] * b[7..4] ) * 28 )
Este resultado intermediário é adicionado ao conteúdo do acumulador e enviado de volta para o acumulador.
O produto abaixo, é o resultado final:
result [15..0] = ( dataa[7..0] * datab[7..0] ) result [15..0] = ( (a[7..4]*24) + (a[3..0]*20) ) * ( (b[7..4]*24) + (b[3..0]*20) ) = ( (a[7..4] * b[7..4]) * 28 ) + ( (a[7..4] * b[3..0]) * 24 ) + ( (a[3..0] * b[7..4]) * 24 ) + ( (a[3..0] * b[3..0]) * 20 )
Máquina de estado em “CALC_DONE”:
Nesse estado é ativada a saída “done_flag” para indicar que o resultado foi calculado e está pronto para leitura pela lógica downstream.
Máquina de estado em “ERR”:
Neste estado, é indicado que entradas incorretas foram recebidas.
Sinais “start” e “count”:
Há dois sinais para a máquina de estados: “start” e “count”. O sinal “start” é iniciado por um ciclo de clock, definindo o início da operação de multiplicação 8×8 para o próximo ciclo de clock.O sinal “start” é ativado somente por um ciclo de clock, enquanto que o sinal “count” é usado pela máquina de estado para rastrear os ciclos de multiplicação.
Sinal “mult_control”:
A saída “mult_control” de controle da máquina de estado serve para gerenciar os outros blocos no projeto.
Se você chegou até aqui, continue com o próximo exercício:
“Multiplicador 8×8 Exercício lab5b Montagem final“,
que terá as considerações finais.
- Multiplicador 8×8: Exercício lab1a somador 16bits
- Multiplicador 8×8: Exercício lab1b multiplicador 4 bits
- Multiplicador 8×8: Exercício lab2a 4-bits 2:1 Mux
- Multiplicador 8×8 Exercício lab2b 8-16bit left regb
- Multiplicador 8×8 Exercício lab3 Display 7 segmentos
- Multiplicador 8×8 Exercício lab4a Registrador 16bits
- Multiplicador 8×8 Exercício lab4b Contador 2bits assíncrono
- Multiplicador 8×8 Exercício lab5a State Machine <-
- Multiplicador 8×8 Exercício lab5b Montagem final
Publicado por Renato de Pierri em 03/12/2023
Fonte: Manual de exercícios de Introdução ao Verilog, da Intel.