Skip to content

Commit

Permalink
Adicionando simple serial transmitter ao projeto (#70)
Browse files Browse the repository at this point in the history
Nesse commit é adicionado ao RISC SoftCore o
simple serial transmitter, sendo ele um projeto dos
alunos: Gabriel Romero e Yuri Marques.

Co-authored-by: yuri-m-b <yuri@DESKTOP-LHBTE9L>
  • Loading branch information
Yuri-m-b and yuri-m-b authored Sep 6, 2024
1 parent c28ec58 commit 02ee6af
Show file tree
Hide file tree
Showing 23 changed files with 2,871 additions and 2 deletions.
84 changes: 84 additions & 0 deletions peripherals/simple_serial_transmitter/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Simple Serial Transmitter

Esse módulo implementa um transmissor serial que converte dados de 8 bits em formato paralelo para um formato serial para transmissão por um único pino de saída. O código inclui uma máquina de estados que controla o processo de transmissão, incluindo a adição de um bit de start, mantendo a saída em nível lógico alto quando inativa.

## Funcionamento
A transmissão inicia com um bit de start em nível baixo, seguido pelo envio serial do endereço (8 bits), seguido pelos dados (8 bits). Após a transmissão, a linha de saída (sdata) retorna para nível lógico alto até a próxima transmissão.

O Simple Serial Transmitter pode ser testado utilizando o modelSim, onde a simulação foi projetada para que seja possível ver o nível lógico da saída, o estado atual da máquina de estados e os bits que estão sendo enviados.

A funcionalidade do circuito pode ser validada em hardware, utilizando um osciloscópio para monitorar a saída serial (sdata).

### Diagrama de blocos do Simple Serial Transmitter
<p align="center">
<img src="./images/diagrama_blocos_sigasi.jpg" height="400">
</p>

### Arquivos

Os códigos utilizados para esse projeto podem ser encontrados nas pastas:

* [Script em C](../../software/simple_serial_transmitter)
* [Script em vhd](../simple_serial_transmitter)

## Máquina de estados

Uma máquina de estados foi usada para gerenciar as diferentes fases da transmissão, incluindo o envio do bit de start, o endereço e os dados.
A máquina de estados com 4 estados pode ser vista no arquivo .vhd do Simple Serial Transmitter, assim como nos diagramas de blocos a seguir, gerados pelo software Sigasi e Quartus respectivamente.

<p align="center">
<img src="./images/maquina_estados_sigasi.jpg" height="400">
</p>
<p align="center">
<img src="./images/maquina_estados_quartus.jpeg" height="400">
</p>

## Resultados esperados para simulação e medições no osciloscópio

O transmissor deve gerar uma sequência de bits como ilustrado abaixo:
```
[Start Bit (0)] [addr (8 bits)] [data (8 bits)]
```
* Start Bit: Um único bit em nível lógico baixo 0 sinalizando o início da transmissão.

* addr: 8 bits do endereço.

* data: 8 bits do dado a ser transmitido.

Enquanto não tiver transmissão, o nível lógico na saída será 1, até o proxímo start bit ser enviado.

### Simulação utilizando ModelSim

<p align="center">
<img src="./images/saida_simulacao.png">
</p>

Nessa imagem podemos examinar todos os estados da máquina de estados, e ver o processo de envio serial dos bits e o comportamento da saída sdata. Lembrando que a saída sdata é a informação utilizada para medição com o uso do osciloscópio.

### Testando em bancada
Após compilar o arquivo ```.c``` do simple serial transmitter, o arquivo ```.hex``` criado é então importado para a memória da placa e de acordo com a síntese do codígo, na saída ```ARDUINO_IO(0)``` é possível ver a saída ```stdata```, como pode ser visto nas imagens a seguir.

<p align="center">
<img src="./images/osciloscopio1.JPG" height="400">
</p>
<p align="center">
<img src="./images/osciloscopio2.JPG" height="400">
</p>
<p align="center">
<img src="./images/working_simple_serial_transmitter.gif" height="400">
</p>

Analisando as imagens anteriores, podemos ver o start bit mudando o nível lógico da saída para 0, e após isso é feito a transmissão do sinal ```addr``` que no momento de execução estava definido como ```0xff```, após a transferência do sinal addr, começa a ser transmitido o sinal ```data``` que no momento de execução estava definido como ```data```, que é um valor int que é incrementado a cada loop.

## Notas finais

Os arquivos utilizados para esse projeto possuem o nome ```simple_serial_transmitter```, com exceção aos arquivos de ```testbench```, ```tb.do``` e o arquivo de síntese do software Quartus.

Os arquivos ```.c``` e ```.h``` são utilizados para a geração e definição dos bits de endereço (addr), dados (data) e start_bit (start).

Também é possível visualizar a informação do ```data``` através dos blinks dos LEDs.

Os arquivos ```testbench``` e ```tb.do``` foram criados para os testes e simulações no software ModelSim.

E por fim os arquivos ```.vhd``` são os arquivos de definição do script do projeto assim como síntese para utilizar no hardware.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
129 changes: 129 additions & 0 deletions peripherals/simple_serial_transmitter/simple_serial_transmitter.vhd
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
-------------------------------------------------------------------
-- Name : simple_serial_transmitter.vhd --
-- Author : Gabriel Romero e Yuri Marques --
-- Description : Simple Serial Transmitter --
-------------------------------------------------------------------

--! Use standard library
library ieee;
--! Use standard logic elements
use ieee.std_logic_1164.all;
--! Use conversion functions
use ieee.numeric_std.all;

entity simple_serial_transmitter is
generic (
--! Chip selec
MY_CHIPSELECT : std_logic_vector(1 downto 0) := "10"; --! Chip select of this device
MY_WORD_ADDRESS : unsigned(15 downto 0) := x"0130"; --! Address of this device
DADDRESS_BUS_SIZE : integer := 32 --! Data bus size
);
port
(
clk : in std_logic;
rst : in std_logic;

-- Core data bus signals
-- ToDo: daddress shoud be unsgined
daddress : in unsigned(DADDRESS_BUS_SIZE-1 downto 0);
ddata_w : in std_logic_vector(31 downto 0);
ddata_r : out std_logic_vector(31 downto 0);
d_we : in std_logic;
d_rd : in std_logic;
dcsel : in std_logic_vector(1 downto 0); --! Chip select
-- ToDo: Module should mask bytes (Word, half word and byte access)
dmask : in std_logic_vector(3 downto 0); --! Byte enable mask

-- hardware input/output signals
sdata : out std_logic
);
end entity simple_serial_transmitter;

architecture rtl of Simple_Serial_Transmitter is

type state_type is (IDLE, ADDR_TR, DATA_TR, DONE);
signal state : state_type := IDLE;
signal start_w : std_logic;
signal addr_w : std_logic_vector(7 downto 0);
signal data_w : std_logic_vector(7 downto 0);
signal databit_transmission : unsigned(0 to 7);
signal sregister : std_logic_vector(15 downto 0) := (others => '0');

begin

process(clk, rst)
begin
if rst = '1' then
start_w <= '0';
addr_w <= (others => '0');
data_w <= (others => '0');
elsif rising_edge(clk) then
if (d_we = '1') and (dcsel = MY_CHIPSELECT) then
if daddress(15 downto 0) = (MY_WORD_ADDRESS + x"0000") then -- addr
addr_w <= ddata_w(7 downto 0);
elsif daddress(15 downto 0) = (MY_WORD_ADDRESS + x"0001") then -- data
data_w <= ddata_w(7 downto 0);
elsif daddress(15 downto 0) = (MY_WORD_ADDRESS + x"0002") then -- start
start_w <= ddata_w(0);
end if;
end if;
end if;
end process;


process(clk, rst)
begin
if rst = '1' then
databit_transmission <= (others => '0');
state <= IDLE;
else
if rising_edge(clk) then
case state is
when IDLE =>
databit_transmission <= (others => '0');
if start_w = '1' then
state <= ADDR_TR;
end if;
when ADDR_TR =>
if databit_transmission = 7 then
databit_transmission <= (others => '0');
state <= DATA_TR;
else
databit_transmission <= databit_transmission + 1;
end if;
when DATA_TR =>
if databit_transmission = 7 then
state <= DONE;
else
databit_transmission <= databit_transmission + 1;
end if;
when DONE =>
if start_w = '0' then
state <= IDLE;
end if;
end case;
end if;
end if;
end process;

process(state, start_w, databit_transmission)
constant NO_TRANSMISSION : std_logic := '1';
begin

sdata <= NO_TRANSMISSION; -- no transmission: sdata = 1;

case state is
when IDLE =>
if start_w = '1' then
sregister <= addr_w & data_w;
sdata <= '0'; -- send start bit = 0;
end if;
when ADDR_TR =>
sdata <= sregister(15 - To_integer(databit_transmission));
when DATA_TR =>
sdata <= sregister(7 - To_integer(databit_transmission));
when DONE =>
end case;
end process;

end architecture rtl;
Loading

0 comments on commit 02ee6af

Please sign in to comment.