# Lab. 4: Microcontrolador
## 1. Abreviaturas y definiciones
- **FPGA**: Field Programmable Gate Arrays
- **UART**: Universal Asynchronous Receiver / Transmitter
- **RISC-V**: Reduced Instruction Set Computer-V
## 2. Referencias
[0] David Harris y Sarah Harris. *Digital Design and Computer Architecture. RISC-V Edition.* Morgan Kaufmann, 2022. ISBN: 978-0-12-820064-3
## 3. Desarrollo
### 3.1 Microprocesador monociclo
La arquitectura del microprocesador desarrollado se basa en los siguientes módulos:
* `module_riscvsingle.sv`
* `module_controller.sv`
* `module_datapath.sv`
* `module_main_decoder.sv`
* `module_alu_decoder.sv`
* `module_adder.sv`
* `module_alu.sv`
* `module_extend.sv`
* `module_flopr.sv`
* `module_mux_2_a_1.sv`
* `module_mux_3_a_1.sv`
* `module_regfile.sv`
### 3.2 module_riscvsingle
Este es el módulo del microprocesador, por lo que en él se instancian los módulos del controlador y el datapath.
#### 1. Encabezado del módulo
```SystemVerilog
module module_riscvsingle_v2(
input logic clk_i,
input logic rst_i,
input logic [31 : 0] ProgIn_i,
input logic [31 : 0] Data_In_i,
output logic we_o,
output logic [31 : 0] ProgAddress_o,
output logic [31 : 0] DataAddress_o,
output logic [31 : 0] DataOut_o
);
```
#### 2. Parámetros
Este módulo no tiene parámetros.
#### 3. Entradas y salidas:
- `clk_i`: señal del reloj de 10 MHz.
- `rst_i`: reset del sistema.
- `ProgIn_i`: entrada de la memoria de instrucciones.
- `Data_In_i`: entrada de la memoria de datos.
- `we_o`: señal de write enable.
- `ProgAddress_o`: address de la memoria de instrucciones.
- `DataAddress_o`: address de la memoria de datos.
- `DataOut_o`: datos de la salida.
#### 4. Criterios de diseño
Para el diseño del microprocesador se hizo uso de la literatura recomendada para el curso, dada en [0].
#### 4. Testbench
Este módulo no tiene testbench.
### 3.3 module_controller
Este corresponde al controlador principal del microprocesador monociclo.
#### 1. Encabezado del módulo
```SystemVerilog
module module_controller(
input logic funct7b5_i,
input logic zero_i,
input logic [6 : 0] op_i,
input logic [2 : 0] funct3_i,
output logic mem_write_o,
output logic pc_src_o,
output logic alu_src_o,
output logic reg_write_o,
output logic jump_o,
output logic [1 : 0] result_src_o,
output logic [1 : 0] imm_src_o,
output logic [2 : 0] alu_control_o
);
```
#### 2. Parámetros
Este módulo no tiene parámetros.
#### 3. Entradas y salidas:
- `funct7b5_i`: señal de entrada de 1 bit.
- `zero_i`: entrada del indicar de resultado 0 en la ALU.
- `op_i`: dato de 7 bits que contiene la operación por realizar.
- `funct3_i`: señal de entrada de 3 bits.
- `mem_write_o`: señal de salida del write enable.
- `pc_src_o`: señal de salida de 1 bit.
- `alu_src_o`: señal de salida de 1 bit.
- `reg_write_o`: señal de escritura en el registro.
- `jump_o`: señal de salida de 1 bit.
- `result_src_o`:señal de salida de 2 bits.
- `imm_src_o`: señal de salida de 2 bits.
- `alu_control_o`: señal de 3 bits que controla la operación de la ALU.
#### 4. Testbench
Este módulo no tiene testbench.
### 3.4 module_main_decoder
Este corresponde al decodificador principal del microprocesador monociclo.
#### 1. Encabezado del módulo
```SystemVerilog
module module_main_decoder (
input logic [6:0] op_i,
output logic mem_write_o,
output logic branch_o,
output logic alu_src_o,
output logic reg_write_o,
output logic jump_o,
output logic [1:0] alu_op_o,
output logic [1:0] result_src_o,
output logic [1:0] imm_src_o
);
```
#### 2. Parámetros
Este módulo no tiene parámetros.
#### 3. Entradas y salidas:
- `op_i`: señal de entrada de 7 bits.
- `mem_write_o`: señal de salida de write enable.
- `branch_o`: señal de salida de 1 bit que permite hacer branch.
- `alu_src_o`: señal de salida de 1 bit.
- `reg_write_o`: señal de escritura en el registro.
- `jump_o`: señal de salida de 1 bit.
- `alu_op_o`: señal de 2 bits que indica la operación en la ALU.
- `result_src_o`; señal de salida de 2 bits.
- `imm_src_o`: señal de salida de 2 bits.
#### 4. Testbench
Este módulo no tiene testbench.
### 3.5 module_alu_decoder
Este corresponde al decodificador de la ALU del microprocesador monociclo.
#### 1. Encabezado del módulo
```SystemVerilog
module module_alu_decoder (
input logic opb5_i,
input logic [2 : 0] funct3_i,
input logic funct7b5_i,
input logic [1 : 0] alu_op_i,
output logic [2 : 0] alu_control_o
);
```
#### 2. Parámetros
Este módulo no tiene parámetros.
#### 3. Entradas y salidas:
- `opb5_i`: señal de entrada de 1 bit.
- `funct3_i`: señal de entrada de 3 bits.
- `funct7b5_i`: señal de entrada de 1 bit.
- `alu_op_i`: señal de entrada de 2 bits para seleccionar la funcionalidad.
- `alu_control_o`: señal de salida de 3 bits que controla la ALU.
#### 4. Testbench
Este módulo no tiene testbench.
### 3.6 module_datapath
Corresponde al datapath del microprocesador monociclo.
#### 1. Encabezado del módulo
```SystemVerilog
module module_datapath (
input logic clk_i,
input logic rst_i,
input logic pc_src_i,
input logic alu_src_i,
input logic reg_write_i,
input logic [1:0] result_src_i,
input logic [1:0] imm_src_i,
input logic [2:0] alu_control_i,
input logic [31:0] instr_i,
input logic [31:0] read_data_i,
output logic zero_o,
output logic [31:0] pc_o,
output logic [31:0] alu_out_o,
output logic [31:0] write_data_o
);
```
#### 2. Parámetros
Este módulo no tiene parámetros.
#### 3. Entradas y salidas:
- `clk_i`: señal de entrada del reloj.
- `rst_i`: señal de entrada del reset.
- `pc_src_i`: señal de entrada para habilitar el program counter.
- `alu_src_i`: señal de entrada de 1 bit.
- `reg_write_i`: señal de entrada para escritura de registro.
- `result_src_i`: señal de entrada de 2 bits de los resultados
- `imm_src_i`: señal de 2 bits de entrada.
- `alu_control_i`: señal de entrada de 3 bits del control de la ALU.
- `instr_i`: señal de entrada de 32 bits.
- `read_data_i`: señal de entrada de 32 bits.
- `zero_o`: señal de salida del zero flag.
- `pc_o`: salida de 32 bits del program counter.
- `alu_out_o`: salida de 32 bits de la ALU.
- `write_data_o`: salida de 32 bits de los datos a escribir en memoria RAM.
#### 4. Testbench
Este módulo no tiene testbench.
### 3.7 module_flopr
Corresponde a un módulo parametrizable de un flip-flop tipo D.
#### 1. Encabezado del módulo
```SystemVerilog
module module_flopr #(parameter WIDTH = 8)(
input logic clk_i,
input logic rst_i,
input logic [WIDTH - 1: 0] d_i,
output logic [WIDTH - 1: 0] q_o
);
```
#### 2. Parámetros
- `WIDTH`: ancho de los bits de entrada
#### 3. Entradas y salidas:
- `clk_i`: señal de entrada del reloj.
- `rst_i`: señal de reset.
- `d_i`: dato de entrada.
- `q_o`: salida del flip-flop.
#### 4. Testbench
Este módulo no tiene testbench.
### 3.8 module_adder
Corresponde a un módulo sumador de datos de 32 bits.
#### 1. Encabezado del módulo
```SystemVerilog
module module_adder(
input logic [31 : 0] a_i,
input logic [31 : 0] b_i,
output logic [31 : 0] y_o
);
```
#### 2. Parámetros
Este módulo no tiene parámetros.
#### 3. Entradas y salidas:
- `a_i`: sumando 1.
- `b_i`: sumando 2.
- `y_o`: resultado de la suma.
#### 4. Testbench
Este módulo no tiene testbench.
### 3.9 module_mux_2_a_1
Corresponde a un multiplexor 2 a 1 parametrizable.
#### 1. Encabezado del módulo
```SystemVerilog
module module_mux_2_a_1 #(parameter WIDTH = 8)(
input logic s_i,
input logic [WIDTH - 1 : 0] d0_i,
input logic [WIDTH - 1 : 0] d1_i,
output logic [WIDTH - 1 : 0] y_o
);
```
#### 2. Parámetros
- `WIDTH`: ancho de los datos de entrada
#### 3. Entradas y salidas:
- `s_i`: bit de selección del mux.
- `d0_i`: dato 1.
- `d1_i`: dato 2.
- `y_o`: dato de salida.
#### 4. Testbench
Este módulo no tiene testbench.
### 3.10 module_regfile
Corresponde al banco de registros del microprocesador.
#### 1. Encabezado del módulo
```SystemVerilog
module module_regfile(
input logic clk_i,
input logic rst_i,
input logic we3_i,
input logic [4 : 0] a1_i,
input logic [4 : 0] a2_i,
input logic [4 : 0] a3_i,
input logic [31 : 0] wd3_i,
output logic [31 : 0] rd1_o,
output logic [31 : 0] rd2_o
);
```
#### 2. Parámetros
Este módulo no tiene parámetros.
#### 3. Entradas y salidas:
- `clk_i`: señal del reloj del sistema.
- `rst_i`: reset del sistema.
- `we3_i`: señal de write enable.
- `a1_i`: dirección 1.
- `a2_i`: dirección 2.
- `a3_i`: dirección 3, usada para escribir en los registros.
- `wd3_i`: dato de 32 bits que se desea escribir en los registros.
- `rd1_o`: dato leído 1, controlado por `a1_i`.
- `rd2_o`: dato leído 2, controlado por `a2_i`.
#### 4. Testbench
Este módulo no tiene testbench.
### 3.11 module_extend
Corresponde al decodificador de instrucciones, ya que recibe una instrucción y devuelve otra en la salida.
#### 1. Encabezado del módulo
```SystemVerilog
module module_extend(
input logic [31:7] instr_i,
input logic [1:0] imm_src_i,
output logic [31:0] imm_ext_o
);
```
#### 2. Parámetros
Este módulo no tiene parámetros.
#### 3. Entradas y salidas:
- `instr_i`: señal de entrada de 24 bits de instrucción.
- `imm_src_i`: señal de entrada de 2 bits.
- `imm_ext_o`: señal de salida de 32 bits.
#### 4. Testbench
Este módulo no tiene testbench.
### 3.12 module_mux_3_a_1
Corresponde a un mux 3 a 1.
#### 1. Encabezado del módulo
```SystemVerilog
module module_mux_3_a_1 #(parameter WIDTH = 8)(
input logic [1 : 0] s_i,
input logic [WIDTH - 1 : 0] d0_i,
input logic [WIDTH - 1 : 0] d1_i,
input logic [WIDTH - 1 : 0] d2_i,
output logic [WIDTH - 1: 0] y_o
);
```
#### 2. Parámetros
- `WIDTH`: ancho de los datos de entrada
#### 3. Entradas y salidas:
- `s_i`: selección del mux.
- `d0_i`: dato 1.
- `d1_i`: dato 2.
- `d2_i`: dato 3.
- `y_o`: salida del mux.
#### 4. Testbench
Este módulo no tiene testbench.
### 3.13 module_alu
Corresponde a la ALU del microprocesador.
#### 1. Encabezado del módulo
```SystemVerilog
module module_alu(
input logic [31 : 0] dato1_i,
input logic [31 : 0] dato2_i,
input logic [2 : 0] alu_control_i,
output logic zero_o,
output logic [31 : 0] alu_out_o
);
```
#### 2. Parámetros
Este módulo no tiene parámetros.
#### 3. Entradas y salidas:
- `dato1_i`: operando 1.
- `dato2_i`: operando 2.
- `alu_control_i`: selector de operaciones de la ALU.
- `zero_o`: flag de resultado igual a cero en la ALU.
- `alu_out_o`: salida de la ALU.
#### 4. Testbench
Este módulo no tiene testbench.
### 3.14 top_riscv_single_cycle_processor_v2
Corresponde a un módulo TOP creado para probar el correcto funcionamiento del microprocesador.
#### 1. Encabezado del módulo
```SystemVerilog
module top_riscv_single_cycle_processor_v2(
input logic clk_100m_i,
input logic rst_i,
output logic [31 : 0] write_data,
output logic [31 : 0] alu_out,
output logic mem_write
);
```
#### 2. Parámetros
Este módulo no tiene parámetros.
#### 3. Entradas y salidas:
- `clk_100m_i`: señal de entrada del reloj de 100 MHz.
- `rst_i`: señal de entrada del reset del sistema.
- `write_data`: datos de entrada provenientes de la memoria RAM.
- `alu_out`: señal de address de la RAM.
- `mem_write`: señal del write enable de la RAM.
#### 4. Criterios de diseño
Este módulo fue creado únicamente para probar el microprocesador antes de proceder a montar el sistema empotrado final. La programación en ensamblador se encuentra en el archivo `prueba_harris_v2.asm`, este código fue provisto por el libro principal del curso, dado en [0]. En él se prueban todas las instrucciones que es capaz de realizar el microprocesador.
En este módulo se instancian tanto el microprocesador, como los IP-cores de la memoria RAM, ROM y el Clocking Wizard.
#### 5. Testbench
El archivo de testbench se encuentra en `tb_top_single_cycle_processor.sv`. Como se mencionó anteriormente, en este módulo se prueban todas las instrucciones soportadas por el microprocesador monociclo. Por lo que en caso de ejecutar todas las instrucciones correctamente, el microprocesador debería escribir el valor de 4140 (0x102C) en el address 216 (0xd8).
La siguiente figura corresponde a la simulación de comportamiento, la cual muestra el correcto funcionamiento del microprocesador, ya que a los 10.1 ns, se escribe en la memoria RAM un 4140 en la dirección 216.

### 4.1 Bus Driver
Corresponde al módulo creado para la comunicación entre los periféricos y el microprocesador.
#### 1. Encabezado del módulo
```SystemVerilog
module module_conductor_de_bus(
input logic we_i,
input logic [31 : 0] addr_i,
input logic [31 : 0] do_ram_i,
input logic [31 : 0] do_switches_i,
input logic [31 : 0] do_uart_a_i,
input logic [31 : 0] do_uart_b_i,
input logic [31 : 0] do_uart_c_i,
output logic we_ram_o,
output logic we_leds_o,
output logic we_7seg_o,
output logic we_uart_a_o,
output logic we_uart_b_o,
output logic we_uart_c_o,
output logic [31 : 0] d_out_o
);
```
#### 2. Parámetros
Este módulo no tiene parámetros.
#### 3. Entradas y salidas:
- `we_i`: Señal de write enable proveniente del microrocesador, entra al `DEMUX`.
- `addr_i`: Dirección proveniente del microprocesador.
- `do_ram_i`: datos de entrada provenientes de la memoria RAM.
- `do_switches_i`: Datos provenientes de los switches.
- `do_uart_a_i`: Datos provenientes del UART A.
- `do_uart_b_i`: Datos provenientes del UART B.
- `do_uart_c_i`: Datos provenientes del UART C.
- `we_ram_o`: Señal del write enable de la RAM.
- `we_leds_o`: Señal del write enable de los LED's
- `we_7seg_o`: Señal del write enable del 7 segmentos.
- `we_uart_a_o`: Señal del write enable del `UART A`
- `we_uart_b_o`: Señal del write enable del `UART B`
- `we_uart_c_o`: Señal del write enable del `UART C`
- `d_out_o`: Salida del Mux con el valor de los datos.
#### 4. Criterios de diseño
En la siguiente figura se muestra el diagrama de bloques del bus driver.

Este módulo conta de un DEMUX para la señal de `we_i` que llega hasta los perífericos para poder habilitarlos y poder obtener los datos provenientes de estos.
A la salida del MUX `d_out_o` se asignará el valor del periférico que fue seleccionado a través del microprocesador por medio del dato `addr_i`. Este puntero escoge un valor entre 0x1000 hasta 0x203C, el módulo de bus driver toma este valor y verifica el valor, una vez hecho esto, lo asocia a uno de los periféricos.
#### 5. Testbench
El archivo de testbench se encuentra en `tb_module_conductor_de_bus.sv`. En él se prueban todos los casos en los que puede estar la señal de `addr_i`, además, se asignan valores aleatorios a las señales de salida de los demás periféricos que componen el sistema. En la siguiente imagen se muestra la simulación post-síntesis, en donde se comprueba que el bus driver funciona correctamente.

### 4.1 Display de 7 segmentos
#### 1. Encabezado del módulo
```SystemVerilog
module module_7seg_disp(
input logic clk,
input logic rst,
input logic [31 : 0] data_in,
input logic we,
output logic [7 : 0] an,
output logic [7 : 0] seg
);
```
#### 2. Parámetros
Este módulo no tiene parámetros.
#### 3. Entradas y salidas:
- `clk`: Señal de reloj de 10MHz.
- `rst`: Señal de reset.
- `data_in`: Datos de entrada al 7 segmentos.
- `we`: Señal de write enable para habilitar el 7 segmentos.
- `an`: Habilita los anodos del display.
- `seg`: Habilita los segmentos del display.
#### 4. Criterios de diseño
Este módulo enciende los primeros 4 display del lado derecho de la FPGA Nexys4, se habilita si hay un 1 en el `we` e imprime en el diplay el dato que le llega a través de `data_in`.
#### 5. Testbench
Para este módulo no se generó un testbench.
### 4.2 LED's
#### 1. Encabezado del módulo
```SystemVerilog
module module_leds(
input logic clk_i,
input logic rst_i,
input logic we_leds_i,
input logic [31 : 0] leds_i,
output logic [15 : 0] leds_o
);
```
#### 2. Parámetros
Este módulo no tiene parámetros.
#### 3. Entradas y salidas:
- `clk_i`: Señal de reloj de 10MHz.
- `rst_i`: Señal de reset.
- `we_leds_i`: Señal de write enable para los leds.
- `leds_i`: Dato que entra al módulo de los leds.
- `leds_o`: Dato que sale del módulo de los leds.
#### 4. Criterios de diseño
Este módulo se diseñó para recibir un valor proveniente del bus driver `leds_i`, el cual va a encender los LED's con este mismo valor en binario `leds_o`, el cual se va a habilitar por medio del `we_leds_i`.
#### 5. Testbench
Este módulo no tiene testbench.
### 4.2 Switches
#### 1. Encabezado del módulo
```SystemVerilog
module module_switches(
input logic clk_i,
input logic rst_i,
input logic [19 : 0] sw_bt_i,
output logic [31 : 0] sw_o
);
```
#### 2. Parámetros
Este módulo no tiene parámetros.
#### 3. Entradas y salidas:
- `clk_i`: Señal de reloj de 10MHz.
- `rst_i`: Señal de reset.
- `sw_bt_i`:Entrada a los swtiches.
- `sw_o`: Salida de los switches.
#### 4. Criterios de diseño
Este módulo consta con una entrada de 20 bits a la entrada `sw_bt_i` a la cual se le concatenan 12 ceros para completar un ancho de palabra de 32 bits los cuales son la salida del módulo `sw_o`.
#### 5. Testbench
Este módulo no tiene testbench.
### 4.3 Antirebotes
#### 1. Encabezado del módulo
```SystemVerilog
module module_antirrebote (
input logic clk_i, // Señal de reloj
input logic rst_i, // Señal de reset
input logic btn_i, // Señal de entrada
output logic q_o // Señal de salida
);
```
#### 2. Parámetros
Este módulo no tiene parámetros.
#### 3. Entradas y salidas:
- `clk_i`: Señal de reloj de 10MHz.
- `rst_i`: Señal de reset.
- `btn_i`:Señal de entrada con rebote.
- `q_o`:Señal de salida sin rebote.
#### 4. Criterios de diseño
Para el diseño del bloque Antirebote, se utiliza un latch SR. El módulo tiene como variables locales S y R. La señal de entrada `btn_i` define los valores de S y R: cuando la señal de entrada es valor lógico 1, S y R se colocan en 1 y 0 respectivamente. Estos valores determinan un "set" para el latch SR, y la salida `q_o` se coloca en 1. Cuando la señal de entrada es valor lógico 0, S y R se colocan en 0 y 1 respectivamente. Estos valores determinan un "reset" para el latch SR, y la salida `q_o` se coloca en 0.
#### 5. Testbench
Este módulo no tiene testbench.
### 4.2 Sincronizador
#### 1. Encabezado del módulo
```SystemVerilog
module module_sincronizador (
input logic clk_i, // Señal de reloj
input logic reset_i, // Señal de reset
input logic D0_i, // Dato de entrada
output logic D1_o // Dato de salida
);
```
#### 2. Parámetros
Este módulo no tiene parámetros.
#### 3. Entradas y salidas:
- `clk_i`: Señal de reloj de 10MHz.
- `reset_i`: Señal de reset.
- `D0_i`: Dato de entrada sin sincronizar.
- `D1_o`: Dato de salida sincronizado.
#### 4. Criterios de diseño
Para el diseño del bloque Sincronizador, el problema principal a resolver corresponde a la metaestabilidad, la cual ocurre cuando se intenta utilizar una señal en el proceso de cambiar de estado lógico bajo a alto y viceversa. Al conectar 2 flip-flops en serie, debido a la señal de reloj así como el tiempo de retardo de los componentes, la señal tiene el tiempo suficiente para cambiar su estado lógico y estabilizarse en dicho estado (La señal tiene el tiempo necesario para resolver su posible estado metaestable).
#### 5. Testbench
Este módulo no tiene testbench.
### 4.3 UART
#### 1. Encabezado del módulo
```SystemVerilog
module module_interfaz_UART (
input logic clk_i,
input logic rst_i,
input logic [31 : 0] entrada_i,
input logic reg_sel_i,
input logic wr_i,
input logic addr_i,
input logic rx,
output logic [31 : 0] salida_o,
output logic tx
);
```
#### 2. Parámetros
- Este módulo no posee parámetros.
#### 3. Entradas y salidas:
- `clk_i`: Reloj de 100MHz.
- `rst_i`: Reinicia el sistema, posee lógica positiva.
- `entrada_i`: Entrada del UART para 32 bits.
- `reg_sel_i`: Selecciona entre el registro de datos y el registro de control.
- `wr_i`: Write Enable de la unidad.
- `addr_i`: Punteros de selección entre los registros de datos 0 y 1.
- `rx`: Entrada serial para la recepción.
- `salida_o`: Salida de la unidad `UART` de 32 bits.
- `tx`: Salida serial para la transmisión de datos.
#### 4. Criterios de diseño
En este módulo se unen todos los módulos anteriormente descritos en el laboratorio 3 además de los modulos que se nos fueron brindados por el profesor como insumos para la creación de la unidad `UART`, en este modulo se instancian estos modulos además de que se realizan varios procesos por ejemplo la concatenación de los bits `new_rx` y `send` con 30 ceros para obtener un ancho de 32 bits para el registro de control.
#### 5. Testbench
Para este módulo no se realizó testbench.
### 4.4 Top del sistema empotrado
#### 1. Encabezado del módulo
```SystemVerilog
module top_sistema_empotrado(
input logic clk_100m_i,
input logic rst_i,
input logic [19 : 0] sw_bt_i,
input logic rx_a_i,
input logic rx_b_i,
input logic rx_c_i,
output logic [15 : 0] leds_o,
output logic [7 : 0] an_o,
output logic [7 : 0] seg_o,
output logic tx_a_o,
output logic tx_b_o,
output logic tx_c_o
);
```
#### 2. Parámetros
- Este módulo no posee parámetros.
#### 3. Entradas y salidas:
- `clk_i`: Reloj de 100 MHz.
- `rst_i`: Botón que reinicia el sistema, posee lógica positiva.
- `sw_bt_i`: Entrada de los 16 switches y 4 botones.
- `rx_a_i`: Señal de rx del UART A.
- `rx_b_i`: Señal de rx del UART B.
- `rx_c_i`: Señal de rx del UART C.
- `leds_o`: Señal de salida de los 16 LEDS de la FPGA.
- `an_o`: Señal de 8 bits que controla los ánodos de los 7 segmentos.
- `seg_o`: Señal de 8 bits que controla los segmentos del display.
- `tx_a_o`: Señal de tx del UART A.
- `tx_b_o`: Señal de tx del UART B.
- `tx_c_o`: Señal de tx del UART C.
#### 4. Criterios de diseño
Este módulo corresponde al TOP del sistema empotrado, en él se instancian los demás periféricos que componen al sistema. Es decir, memorias ROM y RAM, Switches, LEDS, 7 segmentos, UART y el bus driver.
#### 5. Testbench
El archivo de testbench del sistema empotrado se encuentra en `tb_top_sistema_empotrado.sv`. En este testbench se define a la FPGA con el identificador 2 en los switches (`sw_bt_i[11:8]`).
En la siguiente imagen se muestra el funcionamiento de los modos: REPOSO -> PROCESAMIENTO -> CONSUMIR. Primeramente, a partir del los 400 us, se recibe el dato 0xA2 por el UART A (`rx_a_i`). Posteriormente, a los 1400 us, en la señal `leds_o` se muestra el aumento en el contador de paquetes recibidos. Luego, como los bits de destino del paquete corresponden a los bits de identificación de `sw_bt_i`, se procede a consumir el paquete recibido y se muestra en los 7 segmentos (señal `data_out[15:0]`).

En la siguiente figura se muestra el funcionamiento de los modos: REPOSO -> PROCESAMIENTO -> RETRANSMITIR. A partir de los 1548 us, se recibe el dato 0x58 a través del UART B (`rx_b_i`). Como los bits de identificación no coinciden con los bits de destino, se procede a retransmitir el paquete por los UART A y C. Se nota que el contador de paquetes recibidos ha aumentado `leds_o`, pero el contador de paquetes consumidos no lo hace `data_out[15:8]`.

Por último, se prueban los modos: REPOSO -> GENERACIÓN. En los 12.96 ms se observa que el dato de `sw_bt_i` cambia al valor 0x102F0. Lo que significa que se presionó el bit de send (`sw_bt_i[16]`), la FPGA tiene identificador igual a 2 y se quiere enviar el dato 0xF al dispositivo 0x0. Como se observa en la figura se envía el dato de los switches por los tres UART.

## 5. Aplicación
En este módulo se diseñó dos sistemas distintos necesarios para la configuración de la Red Daisy Chain, siendo uno un sistema empotrado que es quien me ejecuta la configuración necesaria de cada dispositivo y una aplicación de la PC como centro de control, que se realizó por medio del programa Python, donde se cumplió la relación relacionada a la siguiente figura y los criterios de estos programas se definen a continuación.

Algunos parámetros de funcionamiento son que cada una de las FPGA's tuviera una dirección única de envío y que siempre la PC fuera el dispositivo `0`, para que mediante esta forma no existieran choques en los envíos de los paquetes.
Para enviar los paquetes se tuvo en cuenta el siguiente formato de instrucción.

Donde del bit `0` al bit `3` se definió como la dirección única de destinatario y del bit `4` al bit `7` se definió como el dato que quiero enviar a la dirección seleccionada.
### 5.1. Hola Mundo
Para la creación de la programación en ensamblador del Hola Mundo primero hay que tener en cuenta como funciona la unidad UART de la cual se habló anteriormente, ya que para esto tendremos que poner el bit `send` en 1, además de esto debemos apuntar a la unidad `UART` de interés para este casa va a ser la unidad C puesto que es la que está conectada al PC, está unidad tiene una dirección de establecida que abarca desde la dirección 0x2030 hasta la 0x203C.
El valor a enviar al`UART C` se guarda en el registro de datos 1, el cual tiene la dirección 0x2038. Además de esto se le hizo un contador de 2000 ciclos de reloj al inicio para un mejor funcionamiento del `UART`. A continuación se presenta un diagrama de flujo para este módulo.

### 5.2. Aplicación en el sistema empotrado
#### 1. Criterios de diseño:
La programación en ensamblador se encuentra en el archivo `Primer_intento.asm`. Este sistema fue diseñado por medio de la descripción de las instrucciones en ensamblador, mediante la aplicación RARS, donde se tuvo en cuenta que se necesitaban desarrollar diferentes tipos de funcionamiento, como lo son el modo Reposo, Procesamiento, Generación, Consumir y Retransmitir. Estos módulos tienen un flujo determinado relacionado con la siguiente imagen.

Aquí se muestra como el estado de modo Reposo es el que espera la activación del botón de inicio para pasar al modo generación y enviar el dato del banco de registros definido. Luego el modo Reposo alternativamente se encuentra en un constante sondeo (polling) que donde si se detecta un valor en la entrada del dispositivo, donde puede dividirse en dos modos adicionales, donde si el dato cumple con las características de puerto único ejecutará el modo consumir y al contrario ejecutará el modo retransmitir.
Para implementarlo en el microcontrolador, se cargó los valores obtenidos del sistema RARS en lenguaje de máquina y se configuró dentro de los archivos de ejecución de las memorias ROM quienes ejecutarán estas consultas en conjunto con los demás sistemas para lograr el correcto funcionamiento.
Para las pruebas se necesitó que al configurar la interconexión de cada FPGA existiera una resistencia de Pull-Up, que me permitía mantener los puertos restantes en un valor constante y no me aumentara los contadores de recibidos dentro del sistema.
Por lo que se logró enviar de cada FPGA un valor y se comprobó cada modo de funcionamiento, de manera que los datos si llegaran a la dirección de destino especificada al Bus Driver del microcontrolador.
### 5.2.1 Modo Reposo
En la programación del modo reposo se hace un sondeo constante del botón de envío del bloque switches (`sw[16]`), así como un sondeo de los registros de control de los tres periféricos UART, en concreto el bit de `new_rx`.

### 5.2.2 Modo Generación
Este modo se encarga de monitorear constantemente los switches del sistema, si hay algún cambio en estos y se presiona el botón predefinido para la transmisión del valor binario de los switches se transmite a través del puerto serial de las 3 unidades `UART` (A,B,C). A continuación se presenta un diagrama de flujo de este modo.

### 5.2.3 Modo Procesamiento
A continuación se muestra el diagrama de flujo de la programación del modo de PROCESAMIENTO.

### 5.2.4 Modo Consumir
Se muestra el diagrama de flujo del modo CONSUMIR.

### 5.2.5 Modo Retransmitir
Por último, se tiene el modo RETRANSMITIR. En el cual se identifica por cuál de los 3 periféricos UART se acaba de recibir el paquete. Posteriomente, se prosigue a retransmitir el paquete por los otros 2 UART.

### 5.2.6 Aplicación en la PC.
#### 1. Criterios de diseño
Primeramente, se define la utilización de "Tkinter" para la interfaz gráfica. Además, se requiere la librería "pySerial" para hacer uso de los puertos seriales en la programación de Python.
Se conoce que la ventana de interfaz gráfica creada con Tkinter corresponde a un ciclo infinito para efectos de la programación de Python. Además, como parte de la funcionalidad, la PC debe siempre estar pendiente de si se recibió algún dato por el puerto serial especificado, lo cual también corresponde a un ciclo infinito. Debido a que se deben correr 2 ciclos infinitos (uno para la revisión del puerto serial y otro para la interfaz gráfica) se utilizan los hilos o "threads" de Python. Los hilos corresponden a una librería de Python que permite correr diferentes códigos "en paralelo". Por lo que se crea un hilo para la revisión del puerto serial y otro para la ventana gráfica.
Con respecto a la función de enviar, se realiza mediante el llamado al atributo "nombre_del_puerto.write". Esto permite escribir el dato en bytes al puerto serial y enviarse. La función de revisar el puerto serial se realiza con un ciclo infinito, en el cual existe un condicional con el atributo "nombre_del_puerto.InWaiting". Si dicho atributo es diferente se 0, significa que existe un dato esperando en el puerto serial.
Una vez que se sabe que existe un dato esperando, se captura dicho dato con el atributo "nombre_del_puerto.read" y se aumenta el contador de paquetes recibidos. Después se evalúa el dato recibido para saber si contiene el identificador "0000", el cual corresponde al identificador asignado para la PC. Si el mensaje tiene como destinatario la PC, en la ventana de interfaz gráfica se imprime el dato y se aumenta el contador de paquetes procesados. Si este no es el caso, sólo se aumenta el contador de paquetes recibidos.
La siguiente figura es como se ve la interfaz de usuario donde se tienen dos label color rojo y verde asignados a los contadores anteriormente descritos, dos cajas de registro para el dato a enviar y el ID de destinatario respectivamente de izquierda a derecha, el botón de enviar lo registrado anteriormente y el último label color azul que registra el dato recibido en caso de que se le envíe a la PC algún mensaje. También tenemos la lista desplegable de los puertos disponibles de la sección COM que me aporta información útil para el funcionamiento.
