--- title: Lista de Exercícios - ENGG56 --- **Escola Politecnica da Universidade Federal da Bahia** **Departamento de Engenharia Eletrica** **Componente Curricular:** ENGG56 - Projeto de Circuitos Integrados Digitais **Professor:** Wagner **Turma:** 000100 2° Semestre de 2023 --- <center> **Exercícios** </center> **1. Assinale as alternativas corretas (cada alternativa errada anula uma correta). Considerando todo o processo de síntese:** :::danger ❌ Atrasos de interconexões exatos são conhecidos após a síntese lógica, pois esta é guiada por restrições de área e de tempo fornecidas pelo projetista. > Justificativa: Neste momento ainda não sabemos os atrasos exatos, isso vai ser feito numa etapa posterior dentro do Place/Route ::: :::success ✅ As 3 principais etapas da síntese lógica são: tradução (do código HDL para uma biblioteca genérica de células lógicas), otimização (do circuito lógico) e mapeamento (para uma biblioteca de células lógicas para um dado processo fabril ou para uma biblioteca de células lógicas genérica). ::: :::success ✅ O comando elaborate do DC serve para resolver referências no código (por exemplo, operadores aritméticos). ::: :::success ✅ A síntese lógica tem por objetivo principal a obtenção de uma netlist em nível de portas. ::: :::danger ❌ As bibliotecas target são utilizadas na obtenção de células genéricas, durante a síntese lógica. > Justificativa: Não, elas são usadas para obtenção de uma célula lógica para dado processo fabril ::: :::danger ❌ O floorplanning visa a obtenção da microarquitetura inicial do sistema. > Justificativa: Microarquitetura tá antes do Design ::: :::danger ❌ Blocos de RAM são posicionados durante o roteamento. > Eles são posicionados no Floorplanning ::: :::danger ❌ A árvore de clock tem por objetivo principal reduzir o atraso de propagação do sinal de clock, desde o terminal de entrada do chip até a região central do mesmo. > Justificativa: Na veradade o principal objetivo é reduzir a diferença de fase _skew_ e a latência. ::: :::danger ❌ Os algoritmos de roteamento mais otimizados buscam a resolução completa do problema em uma única passagem, para reduzir o tempo total de processamento. > Justificativa: Eles fazem um routeamento preliminar para verificar se há colisões antes, então não é em uma tentativa só ::: :::success ✅ Blockages são utilizados para impedir que fios passem por determinadas áreas, como, por exemplo, o entorno de memórias. ::: --- **2. Assinale as alternativas corretas (cada alternativa errada anula uma correta). Considerando restrições temporais:** :::danger ❌ `create_clock` serve para restringir o tempo disponível para execução dos blocos combinacionais internos do circuito a ser sintetizado, entre os flip-flops e entre estes e as portas de E/S do projeto sob síntese. > Justificativa: Ele só restrige entre flip-flops ::: :::danger ❌ A temporização CLK-Q incorpora a temporização de hold e de setup. > Justificativa: Não, ela não incorpora setup.. Setup tem a ver com chegada ::: :::success ✅ Por default, a verificação de violação de setup é feita na borda de clock imediatamente seguinte (capture edge), em relação à borda de emissão do dado (launch edge), enquanto a violação de hold é verificada, por default, uma borda de clock antes da borda de verificação de setup - tais especificações podem ser alteradas pelo comando `set_multicycle_path`. > Justificativa: Apesar do tempo de hold estar relacionado com o launch edge, assim como o capture estar relacionado com o tempo de setup, o comando set_multicycle_path não está relacionado diretamente com essas especificações, mas com projetos assíncronos em que há um multicycle path(projetos assíncronos). ::: :::danger ❌ Clocks virtuais e caminhos falsos devem sempre ser definidos quando do interfaceamento entre circuitos assíncronos. > Justificativa: Clocks virtuais são para multiclocks síncronos, tem o mesmo ponto de origem (mesmo PLL) ::: :::danger ❌ Ao usar `set_output_delay` sobre uma determinada porta de saída, deve-se fornecer o tempo gasto pelo bloco combinacional interno do circuito a ser sintetizado, associado a tal porta de saída. > Justificativa: Na verdade, as restrições são definidas para o cara a ser sintetizado com a quantidade de tempo gasto pelo bloco combinacional externo, lá ele que se vira pra fazer o corre. ::: --- **3. Considerando o fluxo de projeto básico, diferencie implementação de verificação.** :::success Conjunto de etapas que garantem a transformação de representações desde as especificações iniciais até a etapa de representação em um arquivo GSDII. Estas etapas podem ser divididas em 2 grande partes: frontend: etapa que vai desde os requisitos de mais alto nível até síntese lógica e backend: inicia no floorplaning e vai até a etapa do GDSII. Já a verificação, é um conjunto de processos que visa garantir que os requisitos foram mantidos ao longo das varias camadas de representação. Há vários tipos de verificação, a verificação assegura a funcionalidade, temporização e integridade do projeto. ::: --- **4. O fluxo de implementação trabalha com diferentes representações de hardware: especificação; microarquitetura; RTL; portas sintetizadas; portas posicionadas (placed) e roteadas (routed); e GDSII (Graphic Data System). Quais são as características principais de cada uma dessas representações?** :::success **Especificação:** Porta de entrada do projeto, basicamente você tem informações de diferentes áreas e envolve pessoas de diferentes áreas como marketing, investidores, chip leader, entre outros. Normalmente se trabalha com planilhas, gráficos e algoritmos de alto nível que explicam o objetivo do projeto. O produto da especificação são requisitos de mais alto nível e como saída você pode ter diagramas de blocos de mais alto nível. **Microarquitetura:** A microarquitetura é sobre transformar os blocos que estão em alto nível em algo mais palpável. Nesta etapa são criadas os blocos estruturais a partir de blocos funcionais. Além disso são especificadas as interfaces entre os blocos, os módulso IPs e questões de desempenho já são pensadas. **RTL:** A representação em RTL é uma representação algoritmica e buscar construir um código correspondente a partir da microarquitetura. Nesta etapa os blocos são de fato desenvolvidos e ao final tempos uma representação a nível Register Transfer Level. **Portas sintetizadas:** As portas sintetizadas são obtidas a partir da síntese lógica, em que a partir de uma representação em RTL, isto é combinado com restrições de tempo, área e consumo e podem ser sintetizadas para uma biblioteca target gerando uma representação em netlist. **Portas posicionadas (placed) e roteadas (routed):** Na etapa de placement, o netlist é posicionadas ao longo do die. Entre essas etapas também tempos a etapa da síntese da árvore de clock em que é planejado o clock para atender o sistema e na última etapa é a fase de roteamento de fato, de conexão física entre as portas. É importante salientar que entre estas etapas há fases de otimização e pós otimização. **GDSII (Graphic Data System):** Esta última etapa é obtida uma representação física do projeto que vai ser submetida para foundry. ::: --- **5. O que é realizado durante a síntese lógica? Por que restrições temporais são importantes para este processo?** :::success Durante o processo de síntese lógica acontece uma série de processos (parsing, tradução, otimização e mapping) de um verilog comportamental para um verilog estrutural, conhecido como netlist. É também durante esse processo que acontece o mapeamento entre portas lógicas e a biblioteca target. Além disso, restrições são impostas durante o processo de síntese lógica com o objetivo de restringir as células que serão escolhidas na biblioteca, assim como definir a viabilidade do projeto. ::: --- **6. Escreva blocos always para os seguintes circuitos:** <center> <img src="https://i.imgur.com/kIt396o.png"> </center> :::success a) ```verilog= module ffd_6 ( input wire a, clock, rst, output reg b ); always @(posedge clock, posedge rst) begin if (rst) b <= 0; else b <= a; end endmodule ``` ![](https://hackmd.io/_uploads/HyZ9q6uba.png) ::: :::success b) ```verilog= module ffd_6 ( input wire a, clock, rst, output reg b ); always @(posedge clock) begin if (rst) b <= 1'b0; else b <= a; end endmodule // iverilog -t null ffd_6*.v ``` ![](https://hackmd.io/_uploads/SJYYq6_-a.png) ::: :::success ```verilog= module ffd_6 ( input wire D, A, reset, clock, output reg C ); (* synthesis, async_set_reset = "reset, clock" *) always @(posedge A, posedge reset, posedge clock) begin if (reset) begin C <= 1; end else begin if (clock) C <= 0; else C <= D; end end endmodule ``` > It's a question of FPGA hardware properties, not software behaviour. > > > Starting with Cyclone II, asynchronous preset and load of FPGA core registers have been abandoned, the registers have only an asynchronous clear since then. If you need asynchronous load, or both reset and preset of registers, the function needs to be emulated by additional logic cells and latches (the latter implemented as combinational loops). > > > The below gate level schematic shows the involved logic. It's rather obvious, why it will be "glitchy" and slower than a basic register. The priority of rst_n should be observed according to the RTL schematic, however. > > https://community.intel.com/t5/Intel-Quartus-Prime-Software/Defining-Flops-with-Async-Set-Reset/td-p/115545 ![](https://hackmd.io/_uploads/Hy4vwp_Za.png) https://www.intel.com/content/www/us/en/programmable/quartushelp/18.1/index.htm#hdl/vlog/vlog_file_dir.htm https://blog.yosyshq.com/p/async-load-ff/ ::: :::success d) ```verilog= module ffd_6 ( input wire D, A, E, output reg [1:0] B ); always @(E, A, D) begin if (E) begin B <= A+D; end else begin B <= B; end end endmodule ``` ![](https://hackmd.io/_uploads/Sk6vqTdb6.png) ::: --- **7. Cite e corrija ao menos 1 erro em cada um dos trechos de código a seguir.** ```verilog= reg next_state, current_state; always @(*) begin if(current_state == STATE_INIT) next_state = STATE_1 end ``` :::success ```verilog= reg next_state, current_state; always @(*) begin if(current_state == STATE_INIT) next_state = STATE_1; else next_state = current_state; end ``` ::: ```verilog= always @(a or b) begin a = b; b = a; end ``` :::success ```verilog= always @(posedge clk) begin a <= b; b <= a; end ``` ::: ```verilog= reg next_state, current_state; always @(posedge clk) begin if (reset) current_state <= STATE_INIT; else current_state <= next_state; if(current_state == STATE_INIT) next_state = STATE_1 end ``` :::success ```verilog= reg next_state, current_state; always @(posedge clk) begin if (reset) current_state <= STATE_INIT; else current_state <= next_state; end always @(*) begin if(current_state == STATE_INIT) next_state = STATE_1; else next_state = current_state; end ``` ::: ```verilog= always @(*) begin y = y + a end ``` :::success ```verilog= always @(posedge clk) begin y <= y + a; end ``` ::: --- **8. O circuito abaixo permite a realização de um somatório, a partir de dados provenientes de uma memória:** <center> ![](https://imgur.com/VRgrW1O.png) </center> **a)** Faça a representação gráfica (diagrama de blocos) e implemente um módulo em Verilog estrutural, denominado **TOP**. Externamente, **TOP** faz interface com dois blocos: uma **Memória Externa** e um **Controlador**. O **Controlador** deverá enviar sinais de controle **Clock** e **Reset** para **TOP**, recebendo deste o sinal **Ready** (explicado adiante). A **Memória Externa** é uma SRAM, com profundidade de 32 endereços e largura de 16 bits, portas de entrada **DataIN**, **Address**, **ReadEnable** e **WriteEnable**, e porta de saída **DataOut**. Internamente, **TOP** deverá instanciar os módulos denominados **Acumulador** e **FSM**, conforme especificados a seguir. Obs.: **Controlador** é um módulo externo, o qual não é de interesse para o problema aqui tratado, exceto pelos sinais de interfaceamento. :::success ![](https://hackmd.io/_uploads/r1dEqoqMa.png) ::: :::success ![](https://hackmd.io/_uploads/r1ZnYipf6.png) ::: **b)** Baseando-se no circuito da figura acima (utilize os mesmos sinais de controle e adapte os barramentos de dados), faça um módulo em Verilog denominado **Acumulador**, para a realização de somas em 16 bits. :::success ```verilog= module acumulador #( parameter DATA_WIDTH = 16 ) ( input wire clear, transfer, load, input wire [DATA_WIDTH-1:0] data_in, output reg [DATA_WIDTH-1:0] data_out ); reg [DATA_WIDTH-1:0] regB; always @(posedge load) begin regB <= data_in; end always @(posedge transfer, negedge clear) begin if (!clear) begin data_out <= 0; end else if(transfer) begin data_out <= regB + data_out; end end endmodule // iverilog -t null acumulador*.v // iverilog -o a.out ffd_6.v ffd_6_tb.v && vvp a.out // gtkwave ffd_6.vcd & ``` ::: c) Faça um módulo em Verilog denominado **FSM**, o qual envie sinais de controle para uma instância do módulo **Acumulador** e para a **Memória Externa**. Tal FSM deverá fazer o somatório de 4 conjuntos de endereços contínuos: 0 a 6; 8 a 14; 16 a 22; e 24 a 30. Ao final da soma de cada 7 números, o resultado obtido deverá ser gravado no endereço imediatamente seguinte. Ao final da operação sobre os 4 conjuntos, um sinal de Ready deverá ser ativado por pelo menos 1 pulso de clock, de forma a avisar para um circuito externo sobre o término da operação. Após tal ciclo, a FSM deverá iniciar as operações novamente. Em relação aos sinais de controle para a **Memória Externa**, após a habilitação da operação (leitura ou escrita), a memória consumirá 1 pulso de clock para realização da mesma – no caso de leitura, a porta de saída irá para alta impedância tão logo o sinal de ativação seja retirado. :::success ```verilog= module fsm ( input wire clk, rst, counter_save, counter_memory_full, output reg ready, rst_counter, counter_enable, output reg load, clear, transfer, output reg read_enable, write_enable ); localparam INIT = 0, GET_MEM = 1, GET_REGB = 2, ACC = 3, VERIFY = 4, WRITE = 5, FINISHED = 6, COUNTER = 7, READY=8; reg [3:0] state, next_state; always @(posedge clk, posedge rst) begin if (rst) begin state <= 0; end else begin state <= next_state; end end always @(*) begin case (state) INIT: next_state = GET_MEM; GET_MEM: next_state = GET_REGB; GET_REGB: next_state = ACC; ACC: next_state = VERIFY; VERIFY: next_state = counter_save ? WRITE : GET_MEM; WRITE: next_state = FINISHED; FINISHED: next_state = counter_memory_full ? READY : COUNTER; COUNTER: next_state = GET_MEM; READY: next_state = INIT; default: next_state = INIT; endcase end always @(*) begin case (state) INIT: begin ready = 0; load = 0; transfer = 0; clear = 1; read_enable = 0; write_enable = 0; rst_counter = 1; counter_enable = 0; end GET_MEM: begin ready = 0; load = 0; transfer = 0; clear = 0; read_enable = 1; write_enable = 0; rst_counter = 0; counter_enable = 0; end GET_REGB: begin ready = 0; load = 1; transfer = 0; clear = 0; read_enable = 0; write_enable = 0; rst_counter = 0; counter_enable = 0; end ACC: begin ready = 0; load = 0; transfer = 1; clear = 0; read_enable = 1; write_enable = 0; rst_counter = 0; counter_enable = 1; end VERIFY: begin ready = 0; load = 0; transfer = 0; clear = 0; read_enable = 0; write_enable = 0; rst_counter = 0; counter_enable = 0; end WRITE: begin ready = 0; load = 0; transfer = 0; clear = 0; read_enable = 0; write_enable = 1; rst_counter = 0; counter_enable = 0; end FINISHED: begin ready = 0; load = 0; transfer = 0; clear = 0; read_enable = 0; write_enable = 0; rst_counter = 0; counter_enable = 0; end COUNTER: begin ready = 0; load = 0; transfer = 0; clear = 0; read_enable = 0; write_enable = 0; rst_counter = 0; counter_enable = 1; end READY: begin ready = 1; load = 0; transfer = 0; clear = 0; read_enable = 0; write_enable = 0; rst_counter = 0; counter_enable = 0; end default: begin ready = 0; load = 0; transfer = 0; clear = 0; read_enable = 0; write_enable = 0; rst_counter = 0; counter_enable = 0; end endcase end endmodule // ------------------- // iverilog -t null *.v // iverilog -o a.out ffd_6.v ffd_6_tb.v && vvp a.out // gtkwave ffd_6.vcd & ``` ::: **d)** Faça um testbench para validar o módulo **TOP**. :::success ```verilog= `include "src/top.v" `include "src/memory.v" module top_tb; // Parameters // Ports reg clk; reg rst; wire [15:0] data_out; wire ready; wire read_enable; wire write_enable; wire [4:0] address; wire [15:0] data_in; integer i; top top_inst ( .clk(clk), .rst(rst), .data_out(data_out), .ready(ready), .read_enable(read_enable), .write_enable(write_enable), .address(address), .data_in(data_in) ); memory memory_inst ( .addr(address), .wr(write_enable), .rd(read_enable), .data_in(data_in), .data_out(data_out) ); initial begin // Dump variables to VCD file $dumpfile("top.vcd"); $dumpvars(0, top_tb); end initial forever begin #1 clk=1; #1 clk=0; end initial @(negedge clk) begin : TEST for (i=0; i<31; ++i) begin memory_inst.memory[i] = 5*(i+1); end rst = 0; #1 rst = 1; #1 rst = 0; wait(ready); if (data_in == 2640) begin $display("TEST PASSED"); $finish; end $display("TEST FAIL"); $finish; end //always #5 clk = ! clk ; endmodule ``` ::: --- **9. No processo de codificação de vídeo MPEG, usa-se a transformada coseno discreta para passar as amostras dos componentes de brilho e de cor dos pixels, do domínio espacial para o domínio das frequências. Trata-se de uma reorganização da informação de brilho/cor (aplicada a blocos de 8x8 pixels), visando posterior eliminação de amplitudes baixas e deamplitudes de altas frequências, num processo denominado quantização. A transformada inversa, utilizada pelos reprodutores de vídeo MPEG pode ser resumida na forma seguinte, na qual $f(x,y)$ é o valor restaurado das amostras de um bloco de 8x8 pixels (N = 8), cada qual de 9 bits:** $$ f(x,y) = \frac{2}{N} \sum_{u=0}^{N-1} \sum_{v=0}^{N-1} C(u) C(v) F(u,v) cos\frac{(2x+1)u\pi}{2N} cos\frac{(2y+1)v\pi}{2N} $$ **Na expressão acima, $x$ e $y$ são valores das coordenadas dos pixels no domínio espacial (entre $0$ e $7$), $u$ e $v$ são valores das coordenadas dos pixels no domínio de frequência (entre $0$ e $7$), $F(u,v)$ são valores dos coeficientes no domínio de frequência (provenientes de uma memória SRAM, cada qual de $12$ bits), e as demais funções são obtidas por _lookup tables_ (associadas a módulos específicos). Tal expressão pode ser calculada a partir do seguinte circuito:** <center> ![](https://i.imgur.com/dYr6iod.png) ![](https://i.imgur.com/6gQaPZ1.png) </center> a) Considerando que os módulos **C_Function**, **Cos_Function** e **MAC** estão prontos, faça em Verilog o módulo denominado **FSM_Control**, o qual envia parâmetros para os demais módulos e faz o controle de operações de leitura da **SRAM**, na qual os coeficientes $F(u,v)$ estão disponíveis. Os sinais enviados para a **SRAM** são **Address** e **Read_Enable** (em pulsos distintos), enquanto a leitura é realizada através do barramento de dados **Data_Out** (12 bits), o qual deverá ser lido 1 pulso de clock após a ativação de **Read_Enable**. Com o dado disponível em **Data_Out**, deverá ser ativado o sinal **Active_MAC** por 1 pulso de clock, de forma a sinalizar a MAC a presença de dados válidos. Um novo **Address** só poderá ser enviado 1 pulso de clock após a desativação de **Read_Enable**. Considere que o módulo **FSM_Control** é ativado após o sinal **Start** ir para 1, encerrando sua operação após o último cálculo ser realizado, o que deverá ser indicado pela ativação do sinal **Ready**. :::success ![](https://hackmd.io/_uploads/HkriUeizp.png) ```verilog= `include "src/9/register.v" module fsm ( input wire clock, input wire reset, input wire start, output wire [5:0] address, output reg acc, output reg read_enable, output reg ready, output wire [2:0] u,v,x,y ); reg rst_counter_v, counter_enable_v; reg rst_counter_u, counter_enable_u; reg rst_counter_x, counter_enable_x; reg rst_counter_y, counter_enable_y; reg counter_enable_address; reg reset_address; reg started; wire v_full; wire u_full; wire x_full; wire y_full; register # ( .RWIDTH(6) ) counter_address_inst ( .clk(clock), .rst_counter(reset_address), .counter_enable(counter_enable_address), .dout(address) ); register counter_u_inst ( .clk(clock), .rst_counter(rst_counter_u), .counter_enable(counter_enable_u), .dout(u), .full(u_full) ); register counter_v_inst ( .clk(clock), .rst_counter(rst_counter_v), .counter_enable(counter_enable_v), .dout(v), .full(v_full) ); register counter_x_inst ( .clk(clock), .rst_counter(rst_counter_x), .counter_enable(counter_enable_x), .dout(x), .full(x_full) ); register counter_y_inst ( .clk(clock), .rst_counter(rst_counter_y), .counter_enable(counter_enable_y), .dout(y), .full(y_full) ); reg [3:0] state, next_state; localparam START = 0, ADDRESS = 1, READ_ENABLE = 2, DATA_OUT = 3, ACCUMULATOR = 4, INC_V = 5, INC_U = 6, INC_X = 7, INC_Y = 8, READY = 9; always@(posedge clock, posedge reset) begin if(reset) begin state <= START; started <= 0; end else if (started) begin state <= next_state; end end always@(posedge start) begin if(start) started <= 1; else begin started <= started; end end always@(*) begin case(state) START: next_state = ADDRESS; ADDRESS: next_state = READ_ENABLE; READ_ENABLE: next_state = DATA_OUT; DATA_OUT: next_state = ACCUMULATOR; ACCUMULATOR: next_state = INC_V; INC_V: next_state = v_full ? INC_U : ADDRESS; INC_U: next_state = u_full ? INC_X : ADDRESS; INC_X: next_state = x_full ? INC_Y : ADDRESS; INC_Y: next_state = y_full ? READY : ADDRESS; READY: next_state = START; default: next_state = START; endcase end always@(*) begin case(state) START: begin rst_counter_v = 1; rst_counter_u = 1; rst_counter_x = 1; rst_counter_y = 1; reset_address = 1; read_enable = 0; counter_enable_v = 0; counter_enable_u = 0; counter_enable_x = 0; counter_enable_y = 0; acc = 0; ready = 0; end ADDRESS: begin rst_counter_v = 0; rst_counter_u = 0; rst_counter_x = 0; rst_counter_y = 0; reset_address = 0; counter_enable_address = 1; counter_enable_u = 0; counter_enable_v = 0; counter_enable_x = 0; counter_enable_y = 0; read_enable = 0; acc = 0; ready = 0; end READ_ENABLE: begin rst_counter_v = 0; rst_counter_u = 0; rst_counter_x = 0; rst_counter_y = 0; reset_address = 0; read_enable = 1; counter_enable_u = 0; counter_enable_v = 0; counter_enable_x = 0; counter_enable_y = 0; counter_enable_address = 0; acc = 0; ready = 0; end DATA_OUT: begin rst_counter_v = 0; rst_counter_u = 0; rst_counter_x = 0; rst_counter_y = 0; reset_address = 0; read_enable = 1; counter_enable_address = 0; counter_enable_u = 0; counter_enable_v = 0; counter_enable_x = 0; counter_enable_y = 0; counter_enable_address = 0; acc = 0; ready = 0; end ACCUMULATOR: begin rst_counter_v = 0; rst_counter_u = 0; rst_counter_x = 0; rst_counter_y = 0; reset_address = 0; read_enable = 1; counter_enable_address = 0; counter_enable_u = 0; counter_enable_v = 0; counter_enable_x = 0; counter_enable_y = 0; acc = 1; ready = 0; end INC_V: begin rst_counter_v = 0; rst_counter_u = 0; rst_counter_x = 0; rst_counter_y = 0; reset_address = 0; read_enable = 0; counter_enable_v = 1; counter_enable_u = 0; counter_enable_x = 0; counter_enable_y = 0; acc = 0; ready = 0; end INC_U: begin rst_counter_v = 1; rst_counter_u = 0; rst_counter_x = 0; rst_counter_y = 0; reset_address = 0; read_enable = 0; counter_enable_v = 0; counter_enable_u = 1; counter_enable_x = 0; counter_enable_y = 0; acc = 0; ready = 0; end INC_X: begin rst_counter_v = 0; rst_counter_u = 1; rst_counter_x = 0; rst_counter_y = 0; reset_address = 1; read_enable = 0; counter_enable_v = 0; counter_enable_u = 0; counter_enable_x = 1; counter_enable_y = 0; acc = 0; ready = 0; end INC_Y: begin rst_counter_v = 0; rst_counter_u = 0; rst_counter_x = 1; rst_counter_y = 0; reset_address = 0; read_enable = 0; counter_enable_v = 0; counter_enable_u = 0; counter_enable_x = 0; counter_enable_y = 1; acc = 0; ready = 0; end READY: begin rst_counter_v = 0; rst_counter_u = 0; rst_counter_x = 0; rst_counter_y = 0; reset_address = 0; read_enable = 0; counter_enable_v = 0; counter_enable_u = 0; counter_enable_x = 0; counter_enable_y = 0; acc = 0; ready = 1; end endcase end endmodule ``` ::: b) Implemente o multiplicador/acumulador (**MAC**) em Verilog. :::success ```verilog= `include "src/question_9/register.v" module mac ( input wire clk, rst, input wire [11:0] c_u, c_v, cos_x, cos_y, input wire accumulate, input wire [11:0] f_uv, output reg [8:0] f_xy ); reg rst_accumulator; reg [8:0] out; wire counter_full; register # ( .RWIDTH(6) ) counter_accumulator ( .clk(clk), .rst_counter(rst_accumulator), .counter_enable(accumulate), .full(counter_full) ); endmodule ``` ::: --- **10. Considere um robô que deve acompanhar um muro. A figura abaixo ilustra o problema. Na parte a) da figura, o mundo do robô é uma matriz de células, na qual cada componente é livre (células brancas) ou ocupado por um muro (células escuras). O robô, mostrado como um triângulo, é colocado em qualquer célula livre, respeitando uma das direções paralelas ao gradeado da matriz (horizontal ou vertical), com sua frente voltada para qualquer um dos 4 sentidos possíveis (para cima, para baixo, para a direita ou para a esquerda).** <center> <img src="https://i.imgur.com/wxT2jQo.png"> </center> <br> O robô possui 2 sensores binários: head (sensor situado na frente do robô, que retorna 1 quando a célula situada à frente do robô está ocupada por um muro – caso contrário, retorna 0) e left (sensor situado na lateral esquerda do robô, que retorna 1 quando a célula do lado esquerdo do robô é ocupada por um muro - caso contrário, retorna 0). Em relação à movimentação, o robô é capaz de fazer apenas 2 tipos de movimento: avançar para uma célula livre à sua frente ou rotacionar 90º para a esquerda, mantendo-se na mesma célula em que se encontra. Cada movimento consome 1 pulso de clock. Ao ligar o robô, 4 casos são possíveis, os quais deverão ser tratados como segue: - Caso 1: robô em uma área livre (ambos sensores retornando 0). Neste caso, o robô deverá avançar até o encontro de um muro e acompanhá-lo, dando-lhe o lado esquerdo; - Caso 2: robô com muro à frente e do lado esquerdo (ambos sensores retornando 1). Neste caso, o robô deverá rotacionar até encontrar um muro à sua esquerda que possa ser acompanhado; - Caso 3: robô com muro somente à frente (**head** = 1, **left** = 0). Mesmo comportamento do caso 2; - Caso 4: robô com muro somente à esquerda (**head** = 0, **left** = 1). Neste caso, o robô deverá acompanhar o muro. Em qualquer dos casos citados, o robô deverá acompanhar o muro até que um novo muro seja encontrado ou até que o muro <ins>dobre à esquerda</ins>, como na parte **b)** da figura, fazendo com que o robô também dobre à esquerda e prossiga. Como regra prioritária, após cada rotação, se houver um muro à esquerda do robô, este deverá ser acompanhado. Faça o Diagrama de Estados da FSM correspondente ao problema exposto e implemente tal FSM em Verilog. :::success ![](https://hackmd.io/_uploads/Hyu0Wj6Ma.png) ```verilog= module robo ( input wire clk, rst, head, left, output reg motor ); localparam FIND = 0, FOLLOW_ROTATE = 1, FOLLOW_STRAIGHT = 2, ROTATE = 0, STRAIGHT = 1; reg [1:0] state, next_state; always @(posedge clk, posedge rst) begin if(rst) begin state <= FIND; end else begin state <= next_state; end end always @(*) begin case (state) FIND: case ({head,left}) 2'b00: begin motor = STRAIGHT; next_state = FIND; end 2'b01: begin motor = STRAIGHT; next_state = FOLLOW_STRAIGHT; end default: begin motor = ROTATE; next_state = FOLLOW_ROTATE; end endcase FOLLOW_ROTATE: case ({head,left}) 2'b01: begin motor = STRAIGHT; next_state = FOLLOW_STRAIGHT; end default: begin motor = ROTATE; next_state = FOLLOW_ROTATE; end endcase FOLLOW_STRAIGHT: case ({head,left}) 2'b11: begin motor = ROTATE; next_state = FOLLOW_ROTATE; end 2'b01: begin motor = STRAIGHT; next_state = FOLLOW_STRAIGHT; end default: begin motor = ROTATE; next_state = FOLLOW_STRAIGHT; end endcase endcase end endmodule ``` ::: --- **11. Faça em Verilog um módulo para calcular a expressão matricial C = A x B, onde A é uma matriz 2x3 e B é uma matriz 3x2, usando no máximo 3 multiplicadores. Considere que este módulo obtém e grava dados numa memória SRAM, a qual tem como portas de entrada DataIN, Address, ReadEnable, WriteEnable e Clock e, como porta de saída, DataOut. Após a habilitação da operação (leitura ou escrita), a memória consumirá 1 pulso de clock para realização da mesma – no caso de leitura, a porta de saída irá para alta impedância tão logo o sinal de ativação correspondente seja retirado.** :::success ![](https://hackmd.io/_uploads/BJr3GiTfT.png) ```verilog= module matriz ( input wire clk, rst, input wire [23:0] data_in, output reg [23:0] data_out, output reg [2:0] addr, output reg read_enable, write_enable ); endmodule ``` ::: --- **12. Explique qual o objetivo principal de cada uma das etapas de projeto de um circuito integrado digital.** <center> <img src="https://i.imgur.com/voc5eG6.png"> </center> :::success - Especificação: - Construir um conjunto de blocos comportamentais - Definir escopo e restrições - Definição de interfaces - Sondagem dos IPs a serem utilizados - Microarquitetura: - Definição blocos arquitetuturais - Estabelecimento interfaceamento de blocos - Definição dos IPs utilizados - Descrição algoritmica - RTL: - Construção do verilog comportamental - Detalhamento a nível de bloco definidos - Design e decisões são feitas para cada módulo - Synthesized: - Construção do verilog estrutural - Utilização de informação de células físicas e lógicas - Utilização de restrições de tempo, área e energia (Síntese física) - Otimização - Mapeamento para uma determinada biblioteca alvo - Floorplanning: - Posicionamento e planejamento dos módulos - Definição de áreas blockage - Reduzir área e tempos de interconexão - Placement: - Disposição do netlist no die - Reduzir área e tempos de interconexão - Scan Reorder: - Reorganização das cadeias de varredura - Reduzir área e tempos de interconexão - Desgin Optimization Pre-CTS: - Otimização de caminhos - Adição de buffers - Upsizing/Downsizing - CTS: - Síntese da árvore de clock - Redução do clock skew - Redução da latência de clock - Desgin Optimization Post-CTS: - Otimização de caminhos - Adição de buffers - Upsizing/Downsizing - Modificação na árvore de clock - Route: - Roteamento - Verificação de congestionamentos - Desgin Optimization Post-Route: - Otimização de caminhos - Adição de buffers - Upsizing/Downsizing - Layout - Modificações do arquivo GDSII - Outros - Extraction: Extração de resistências e capacitâncias - Delay calculation - Signal Integrity - Static Timing Analysis ::: --- **13. Explique, com auxílio de ilustrações, o que são launch edge e capture edge.** :::success - Launch edge: Aresta de clock referente ao momento que um dado é enviado. - Capture edge: Momento determinado por uma aresta de clock que um dado é recebido ou detectado. ::: ![](https://hackmd.io/_uploads/HkSew8oW6.png) --- **14. Explique o que são as temporizações de setup, hold e CLK-Q. Relacione setup e hold com launch edge e capture edge.** :::success - **setup:** Tempo necessário de um sistema para que um novo conjunto de dados permaneça estável na sua entrada para que ele seja percebido antes do pulso de clock. - **hold:** Tempo necessário que determinado conjunto de dados seja permaneça estável após ele ser configurado, para que seu valor não se desestabilize. - **clk_Q:** Tempo de propagação interna de um flipflop. Exemplo: tempo entre a subida do clock de um FF para a configuração de um novo dado até este ser propagado para a saída. **Launch Edge**: Relacionado com o **hold**, pois para o dado ser enviado, você deve ter respeitado que ele estava estável em um tempo de hold (de um flip flop anterior). **Capture Edge**: Relacionado com o **setup**, pois para um dado ser capturado, você não pode violar estas condições de tempo, ele deve chegar antes do evento de captura. ::: --- **15. Através de um exemplo de código em Verilog, identifique (faça um círculo) os sete diferentes objetos de projeto considerados pelas ferramentas de síntese lógica.** :::success - Ports - Pins - Net - Design - Cell - Reference - Clock ```verilog= // Design module TopModule( input wire clk, // Port e Clock input wire reset, // Ports output wire data_out // Ports ); wire internal_wire1; // Net wire internal_wire2; // Net // Reference, Cell MyModule Instance1 ( .input_a(clk), // Pin, Net .input_b(reset), // Pin, Net .output_c(internal_wire1) // Pin, Net ); endmodule ``` ::: --- **16. Explique as etapas do fluxo básico da síntese lógica.** <center> <img src="https://i.imgur.com/zyKus6y.png"/> </center> :::success - O primeiro passo é escrever o código Verilog/VHDL. Também conhecida como representação em RTL - Realiza a simulação funcional. É aqui que basicamente acontecem os testes - Se os resultados da simulação forem satisfatórios parte-se para a síntese lógica - Caso contrário reescreve-se o código VHDL/Verilog - O processo de síntese lógica é guiado por restrições de área e temporização - A escolha de portas lógicas e flip-flops mais adequados são feitos com base nas restrições - Caso a síntese lógica tenha um resultado satisfatório em termos das constraints estabelecidas anteriormente, parte-se para a implementação física. - Caso contrário, verifica-se a presença de violações major ou não. - Caso tenha acontecido violações major, volta-se para a etapa de reescrita do código VHDL/Verilog, caso não tenha violações major, segue-se para a síntese assim mesmo. ::: --- **17. Dada a figura abaixo, descreva a função de cada um dos principais comandos utilizados pela ferramenta de síntese lógica (RTL Compiler / DC Compiler) para restringir a temporização dos circuitos combinacionais, de forma a procurar sintetizar tais circuitos adequadamente.** <center> <img src="https://i.imgur.com/og51Pio.png"/> </center> :::success - `create_clock`: Restringe os caminhos lógicos entre registradores. - `set_dont_touch_network`: Restringe a síntese para sinais de clock. - `set_input_delay`: Estabelece o tempo máximo de uma entrada a ser sintetizada, baseada em um atraso conhecido de uma lógica externa. - `set_output_delay`: Estabelece o tempo máximo de uma saída a ser sintetizada, baseada em um atraso conhecido de uma lógica externa. ```tcl create_clock -period 20 [get_ports clk] set_dont_touch_network [get_ports clk] set_input_delay -max 4.2 -clock clk [get_ports A_in] set_output_delay -max 5.2 -clock clk [get_ports A_out] ``` ::: --- **18. Descreva a finalidade de cada um dos comandos:** :::success **`set_operating_conditions`:** Define as condições de ambientais, há diferentes condições de operações como temperatura e tensão além de precisão. **`set_load`:** Define a capacitância máxima de saída de determinadas portas. **`set_driving_cell`:** Define características de drive. Associa os `pin` de uma biblioteca com uma porta de entrada. Assim o comando coloca restrições nas portas de entrada se a célula tiver restrições. **`set_wire_load_model`:** Define o modelo carga dos fios a serem roteados, estes modelos estão relacionados com processo de fabricação. **`set_max_capacitance`.** Determinar a capacitância máxima de nets. ::: --- **19. Qual a importância de um modelo de capacitância e distribuição de fios (wire load model) para a ferramenta de síntese lógica (RTL Compiler / DC Compiler)? Por que ela precisa disso?** :::success <center> <img src="https://hackmd.io/_uploads/rJNDywQL6.png"/> </center> Por que este modelo afeta diretamente nos tempos de propagação e de transição de sinais. Além disso com este modelo definido, a ferramenta de síntese pode realizar as devidas otimizações adequadamente. $$ \tau = R\cdot C $$ ::: --- **20. Como variações no processo de fabricação, temperatura de operação e tensão de operação afetam o desempenho de um circuito integrado?** :::success <center> <img src="https://hackmd.io/_uploads/H1-lbvXUT.png"/> </center> O processo de fabricação é influenciado por diferentes condições no processo de manufatura, a qualidade do processo na precisão do chip como pureza dos dopantes, condições de fabricação como temperatura e pressão afetam o no seu desempenho. Nenhum transistor é igual ao outro! A temperatura de operação está relacionada com a performance, a mobilidade dos portadores de carga é afetada pela tempetura, um aumento de temperatura resulta em perda de desempenho do circuito integrado uma vez que com o aumento da temperatura as lacunas fornecerão uma maior resistência de condução, o efeito contrário também é observado. Por isso é importante determinar as condições de operação do circuito integrado. Com tensões de operação mais altas, os circuitos ficam mais rápidos pois o campo elétrico aplicado nos gates pode atrai mais os portadores de cargas entre a fonte e o dreno, contudo o gasto energético é maior e embora tenhamos um ganho de desempenho há um limite pois a temperatura também é aumentada com uma tensão maior. ::: --- **21. Explique como funciona o mecanismo de verificação temporal STA (Static Timing Analysis).** :::success STA é um método de validar as condições temporais de um design verificando as violações de tempo atraves de todos os caminhos. O mecanismo de funcionamento se baseia em dividir um design em caminhos temporais e através das restrições e definições de atrasos o STA calcula os tempos de propagação e avalia-se os caminhos de pior condição: Como é feita a análise estática de temporização? - Determina se um circuito atende os requisitos de temporização, sem, contudo, fazer a simulação dinâmica, ou seja, não é preciso simular um circuito para saber se ele vai atender temporal ou não. Três passos principais: - 1. Quebrar o projeto em diversos caminhos de temporização - 2. Calcular o atraso de cada um desses caminhos - 3. Checar se esses atrasos atendem as restrições de temporização estabelecidas Como identificar um start-point de um caminho? - Portas de entrada do meu projeto - Pinos de clock (de cada flip-flop). Como identificar um end-point de um caminho? - Portas de saída - Pino D de um flip flop também é considerado como endpoint ::: **22. Na figura abaixo, identifique os caminhos de temporização (timing paths) e os grupos de caminhos (group paths) existentes.** <center> <img src="https://i.imgur.com/po8wWaT.png"/> </center> <br/> :::success <center> <img src="https://hackmd.io/_uploads/BJqtUvQ86.png"/> </center> ::: --- **23. Explique os termos data required time, data arrival time e slack.** :::success <center> <img src="https://hackmd.io/_uploads/rJolKwXUa.png"/> </center> O **data required time** é o tempo máximo permitido para que um determinado dado seja capturado, ele é contabilizado como o momento em que se leva para obter uma aresta de captura após uma aresta de lançamento (um período do clock) acrescido dos atrasos do caminho desde clock até onde o dado vai é requerido. Na imagem abaixo é o tempo do caminho vermelho acrescido de um período (para contabilizar desde que a aresta de captura é disparada), além disso há incertezas de clock, pessimismos de chegada do clock e tempos de subida que também são contabilizados. É importante salientar que quando considerado um determinado output delay, o tempo necessário requerido é diminuído por esta restrição. Desta forma, deve-se considerar um tempo requerido menor, para isso subtrai-se o tempo de saída do _data required time_. $$ T_{data\space required} = T_{period} + T_{d3(clock\space delay)} + \Delta T_{pess+uncer+uTsu} - T_{output} $$ > Resumo: Tempo necessário para se capturar um dado Já o **data arrival time** é o tempo que um determinado dado é propagado desde uma aresta de lançamento até a região do circuito onde ele é requerido, na imagem abaixo ele é o tempo do caminho azul. Ele pode ser contabilizado do duas formas diferentes: caso o atraso do clock seja maior que o tempo de atraso da entrada, apenas o atraso de clock será considerado, e vice-versa. $$ T_{data\space arrival} = max(T_{d1(clock\space delay)}, T_{input+setup}) + T_{clk-q} + T_{d2(data\space delay)} $$ > Resumo: Tempo que o dado levou para ficar pronto para ser capturado ![](https://hackmd.io/_uploads/BJARRK3W6.png) Assim, fica fácil perceber que o tempo que o dado levou para ficar pronto para ser capturado (_data arrival_) deve ser menor do que o tempo necessário para se capturar um dado (_data required_). O **slack** é então a diferença entre estes dois tempos: $$ slack = T_{data\space required} - T_{data\space arrival} $$ Como $T_{data\space arrival}$ deve ser menor que $T_{data\space required}$, numa situação em que se tem uma folga e o circuito não está violando as condições de tempo, devemos ter um slack positivo. ::: --- **24. Explique o que modela cada um dos comandos abaixo:** **`set_clock_latency -source 5 clock`** **`set_clock_latency 5 clock`** :::success **`set_clock_latency -source 5 clock`**: **`set_clock_latency 5 clock`**: Os comandos definem a restrição para latência do clock, isto é, o tempo limite para um clock ser propagado entre uma determinada fonte até a árvore de clock. **`set_clock_latency -source 5 clock`**: O set_clock_latency com a flag -source indica qual o atraso da rede de clock entre a fonte(oscilador, PLL) até a entrada de port. **`set_clock_latency 5 clock`**: O set_clock_latency especifica a latência de clock para todos os pins e ports que estão associados a um clock. Estão associados à latência da rede, mais especificamente da porta de entrada até a rede de clock. ::: --- **25. Considerando o circuito produzido pela síntese lógica com o circuito produzido após a síntese da árvore de clock (CTS), qual a diferença básica, considerando os caminhos de clock? Há alguma forma de fazer com que a ferramenta de síntese lógica leve em consideração tal diferença, de forma a modelar melhor o possível comportamento final do circuito?** <center> <img src="https://i.imgur.com/DnsiI1s.png"> </center> <br> :::success A diferença é que após o CTS são inseridos buffers para adicionar ou reduzir atrasos. Sim, é possível levar em consideração tal diferença, inclusive considerando que já foi otimizado através do comando `set_propagated_clock`. ::: --- **26. Dada a figura abaixo, responda às questões:** <center> <img src="https://i.imgur.com/KpOmydR.png"/> </center> <br/> **a)** O que diferencia um projeto síncrono de um assíncrono? :::success Um projeto síncrono, os dados de entrada e saída são controlados por um mesmo sinal de clock que veio de uma mesma fonte. Já um projeto assíncrono é quando um circuito depende de mais de um clock (com fontes diferentes) ::: **b)** Para que servem clocks virtuais? Na figura acima, quais seriam esses clocks e como eles são definidos (considere uma frequência qualquer)? :::success Os clocks virtuais servem como objetos para o Design Compiler para auxiliar na síntese de projetos síncronos com multiplos clocks. Na figura acima, temos os clocks **CLKA**, **CLKB**, **CLKD** e **CLKE**. ```tcl= # Create virtual clocks create_clock -period 15 -name CLKA create_clock -period 20 -name CLKB create_clock -period 25 -name CLKD create_clock -period 30 -name CLKE # Create clock create_clock -period 50 [get_ports CLKC] set_dont_touch_network [get_clocks CLKC] # Input delay set_input_delay -max 4.5 -clock CLKA [get_ports IN1] set_input_delay -max 5.5 -clock CLKB --add_delay [get_ports IN1] # Output delay set_output_delay -max 2.5 -clock CLKD [get_ports OUT1] set_output_delay -max 4.5 -clock CLKE --add_delay [get_ports OUT1] ``` ::: --- **27. Dados figura e comando abaixo, considerando que os flip-flops têm $t_{clk-Q} = t_{setup} = 0.5 ns$, qual o valor máximo de $t_N$?** <center> <img src="https://i.imgur.com/OVXPsHF.png"/> </center> <br/> ```bash set_input_delay -max 4 -clock CLKA [get_ports IN1] ``` :::success Primeiro, calcula-se o período de cada clock: $$ CLK_A = \frac{9}{300MHz} = 30ns $$ $$ CLK_C = \frac{6}{300MHz} = 20ns $$ Agora, encontra-se a pior restrição temporal entre uma aresta de lançamento e captura ($T_{AC}=10ns$) <center> <img src="https://hackmd.io/_uploads/S1kSHOXU6.png"/> </center> Logo $$ t_N < T_{AC} - T_{max} - T_{setup} $$ $$ t_N < 10ns - 4ns - 0,5ns = 5,5ns $$ <center> <img src="https://hackmd.io/_uploads/B1oDKO7Lp.png"/> </center> ::: --- **28. Na figura abaixo, se ambos os clocks são de $100 MHz$, por que há a necessidade de usar o comando `set_false_path`?** <center> <img src="https://i.imgur.com/UxyLl0k.png"> </center> <br/> :::success Você precisa declarar o setfalse path por que se não o compilador pode querer tentar sintetizar estes caminhos. Embora as frequências sejam a mesma, como elas tem fontes distintas, você pode ter uma diferença de fase entre elas, por isso você deve retirar estes caminhos. Este é um projeto assíncrono. Exemplo: ```tcl= # Cria os dois clocks create_clock -period 10 [get_ports CLKA] create_clock -period 10 [get_ports CLKB] # Não otimize os "crossing clock domains" set_false_path -from [get_clocks CLKA] -to [get_clocks CLKB] set_false_path -from [get_clocks CLKB] -to [get_clocks CLKA] ``` ::: --- **29. Se uma lógica combinacional entre 2 flip-flops for muito grande, não sendo possível estabilizar o circuito no período definido para o clock que alimenta ambos os flip-flops, quais são as alternativas possíveis para sintetizar tal lógica?** :::success - Aumentar o esforço empregado na otimização - Quebrar este caminho em um registrador - Se não form major segue adiante - `set_multicycle_path` ::: --- **30. A checagem de hold é feita um pulso antes da checagem de setup. No caso de multcycle paths, há como alterar tal relação de verificação?** :::success Sim, no caso de multicycle paths, você pode alterar a relação ```tcl=1 set_multicycle_path 4 -setup -from [get_cells FF1] -to [get_cells FF2] set_multicycle_path 3 -hold -from [get_cells FF1] -to [get_cells FF2] ``` No código anterior por exemplo, o comando da linha 2 faz a checagem de hold ser feita 3 pulsos antes da checagem de setup. ::: ___ **31. Dada a figura abaixo:** <center> <img src="https://i.imgur.com/bU3N3rb.png"/> </center> <br/> **a)** Explique as etapas envolvidas no protocolo ACK/REQ de 2 fases. :::success 1. Sender coloca informações no data e comuta o Request 2. Com a comutação do request, o Receiver pega o Dado e comuta ACK ::: **b)** Explique as etapas envolvidas no protocolo ACK/REQ de 4 fases. :::success 1. Sender coloca dados e sobe REQUEST 2. Receiver vê o REQUEST e pega os dados e sobe ACK 3. Sender vê que ACK subiu, e desce o REQUEST 4. Receiver viu que desceu o REQUEST e desce ACK ::: --- **32. Explique o funcionamento de uma FIFO síncrona.** <center> <img src="https://i.imgur.com/rDQ6Sql.png"/> </center> :::success Uma FIFO é um elemento de memória. Ela é usada como um armazenador de informações. Na FIFO síncrona temos uma parte responsável por ler informações e outra para escrever. Módulo WP: Determinar o próximo endereço a ser escrito Módulo RP: Determinar o próximo endereço a ser lido - Write enable: Habilita a escrita (do endereço WP) - Read enable: Habilita a leitura (do endereço RP) - Full e Empty é para saber se a FIFO está cheia ou vazia FIFO síncrona: - Único domínio de clock para todo o circuito ::: --- **33. Refaça a figura da questão anterior, adequando-a para uma FIFO assíncrona.** :::success <center> <img src="https://hackmd.io/_uploads/HyZ-AFmLa.png" /> </center> Problemas de uma FIFO assíncrona: - Circuitos em clocks diferentes - Agora temos write clock e read clock O problema agora é que você tem uma lógica combinacional que depende de dois dados de domínios de clock distintos <center> <img src="https://hackmd.io/_uploads/rJsA0tQ8p.png"/> </center> A ideia é sincronizar os ponteiros de um domínio para o outro utilizando a estratégia do double-FF. (Esta é uma estratégia a ser usada para poucos bits) <center> <img src="https://hackmd.io/_uploads/S17-x5XU6.png" /> </center> Um problema que pode aparecer é o skew entre os bits de um ponteiro. <center> <img src="https://hackmd.io/_uploads/ryTZZ5X8T.png"/> </center> Para resolver isso, você usa o código gray! <center> <img src="https://hackmd.io/_uploads/ryV0b9mUT.png"/> </center> Então a conversão para uma FIFO assíncrona consiste em: - Converter o ponteiro em binário para gray - Sincronizar o código gray com o outro domínio de clock - Converter de volta em binário - Comparar os 2 ponteiros com o mesmo domínio de clock - Gerar a flag de status ::: --- **34. Na FIFO assíncrona, por que há a necessidade de converter os ponteiros de endereços para código Gray?** :::success Para evitar o problema a captura de dados no momento da mudança de mais de um bit nos sinais envolvidos. Com a utilização do código Gray existem 2 possibilidades, ou você utiliza um dado antigo ou o dado atualizado. ::: --- **35. Na geração do flag de full em uma FIFO síncrona, explique o significado das condições referentes à cláusula if imediatamente após o comentário `// Non RESET functionality`. Por que o ponteiro de escrita está na versão next e o de leitura está na versão sem ser next?** ```verilog= // Generating Full Flag always @(posedge clk) begin if (!rst_n) begin full <= 1'b0; end else begin // Non RESET functionality if (wr_ena && !rd_ena) begin if ((n_wr_ptr[ADDR_WIDTH-1:0] == rd_ptr[ADDR_WIDTH-1:0]) && (n_wr_ptr[ADDR_WIDTH] != rd_ptr[ADDR_WIDTH])) begin full <= 1'b1; end else begin full <= 1'b0; end end end // END IF (!Reset) end // END ALWAYS - SYNC: Generate full flag ``` :::success O ponteiro de escrita está na sua versão next por que estamos pegando o dado mais atualizado e estável durante um processo de escrita. Como estamos fazendo uma escrita e não uma leitura, o dado mais estável está em `n_wr_ptr` e não em `wr_ptr`. Pelo mesmo motivo não estamos fazendo uma leitura então o dado mais atualizado para uma leitura é o `rd_ptr`. ::: --- **36. Por que o silício é o material mais largamente utilizado na fabricação de circuitos integrados?** :::success Primeiramente por que ele é um material tetravalente, além disso, comparando com outros materiais tetravalentes, o material é abundante e barato, estável em temperatura ambiente. ::: --- **37. Considerando bandas de energia, o que diferencia materiais isolantes, condutores e semicondutores?** :::success Considerando as bandas de energia, o material isolante tem uma grande banda de energia, ou seja é necessaria uma grande quantidade de energia para condução de corrente elétrica. No material condutor esta banda é pequena, de forma que pouca energia é necessária para conduzir corrente neste material. E para um semicondutor essa banda de energia é itermediária de forma que não seja necessário nem muita nem pouca energia para a condução. ::: --- **38. Dada a figura abaixo:** <center> <img src="https://i.imgur.com/IkIdYlI.png"> </center> <br/> **a)** Através de círculos, identifique os diferentes tipos de material presentes na figura. :::success <center> <img src="https://hackmd.io/_uploads/HJ81r2QI6.png"/> </center> ::: **b)** Descreva os processos utilizados na obtenção de cada material identificado no item anterior. :::success Exemplo para substrato p 1. Crescimento epitaxial Propósito: Criar uma camada de silício de alta qualidade, mininizar os efeitos de baixa qualidade de waffer. Epitaxia permite crescimento do substrato 2. Poço n é necessario para construir transistores canal n Por difusão ou implantação iônica, impurezas n espalham-se pela região delimitada do poço, fazendo que os portadores p originais se revertam a polaridade para n. Quantidade de dopantes n deve superar a de p. A seguir, a lâmina é oxidada para formar uma fina camada para proteger de uma máquina para outra. Substrato p+, Camada epitaxial p-, poço n, óxido 3. Definição da área ativa Onde vai ser de fato os transistores A isolação elétrica entre os componentes que compartilham o substrato é essencial 3.1. Colocar uma camada de Si3N4 usando CVD 3.2 photoresist é depositado sobre o Si3N4 3.3 Com o emprego da corrosão por plasma a estrutura definida no photoresist é transferida ao nitreto de silício 3.4 Área não coberta pelo nitreto será oxidada 4. Formação do óxido de porta Por corrosão é removido o nitreto de silício Lâmina é submetida a uma atmosfera de oxigênnio seco Para formar o óxido de porta 5. Deposição do polisilício (p ou n) Esse cara é para ser usado nos eletrodos das portas Utiliza-se o CVD para depositar Proteger, através da mascara com photoresist e depois faz a corrosão 6. Formação do transistor canal p Após a corrosão, regiões de dreno e fonte ficam expostas Então você protege regiões e dopa as que vc precisa 7. Formação do transistor canal n Semelhante ao item anterior, substituindo o dopante 8. Recozimento Reordenar a rede cristalina, remover deformações 9. Isolação e abertura dos contatos Joga uma camada de SiO2 ou SiN4 por toda a superfícies Imprime a máscara de abertura Abertura de contatos por corrosão do plasma do SiO2/Si3N4 10. Deposição do metal 1 Metalização da superfície da lâmina Pode ser por evaporação ou borrifamento O mais adequado seria borrifamento Impressão de máscara para definir interconexões Corrosão do cobre não desejado Planarização > Há outras etapas ainda no processo que foram omitidas ::: --- **39. Você vai ser aprovado(a)? Tem certeza?** :::success Claro!!! :smile: :::