# Tutorial BRAM
Pada tutorial ini akan dikerjakan serangkaian tutorial untuk BRAM.
[TOC]
:::success
:tada: Tutorial ini telah selesai dikerjakan :tada:
:::
***
## Bagian 1 - Simulasi Block Memory
Berikut merupakan dual port block RAM yang diambil dari datasheet.

Operasi read/write dari BRAM dideskirpsikan sebagai :
> ### Read Operation
>In latch mode, the read operation uses one clock edge. The read address is registered on the
read port, and the stored data is loaded into the output latches after the RAM access time.
When using the output register, the read operation takes one extra latency cycle.
> ### Write Operation
>A write operation is a single clock-edge operation. The write address is registered on the
write port, and the data input is stored in memory.
> ### Write Modes
>Three settings of the write mode determines the behavior of the data available on the
output latches after a write clock edge: WRITE_FIRST, READ_FIRST, and NO_CHANGE.
Write mode selection is set by configuration. The Write mode attribute can be individually
selected for each port. The default mode is WRITE_FIRST. WRITE_FIRST outputs the
newly written data onto the output bus. READ_FIRST outputs the previously stored data
while new data is being written. NO_CHANGE maintains the output previously
generated by a read operation.
Contoh waveforms untuk mode default WRITE-FIRST :

Block Design dari BRAM yang digunakan adalah :

Setelah mengikuti modul untuk pengujian BRAM dengan block design sebagai berikut,didapatkan hasil simulasi sebagai :

Keluaran akses memori sesuai dengan urutan input.
## Bagian 2 - Implementasi Block Memory
BRAM diimplementasikan pada Vivado dengan blok berikut.

Address dipilih mengikuti datasheet :

Ukuran dipilih 4K sehingga maksimal address berada di 0FFF

Program yang digunakan pada Vitis sebagai PS adalah
```
#include <stdio.h>
#include <stdint.h>
21
#define MEM_INP_BASE 0x40000000 // Sesuaikan dengan address editor
#define MEM_OUT_BASE 0x40002000
uint32_t *meminp_p, *memout_p;
int main()
{
// *** Initialize pointer ***
meminp_p = (uint32_t *)MEM_INP_BASE;
memout_p = (uint32_t *)MEM_OUT_BASE;
// *** Write to block memory input ***
for (int i = 0; i <= 1023; i++)
*(meminp_p+i) = i;
// *** Read from block memory input ***
printf("Block Memory Input:\n");
for (int i = 0; i <= 1023; i++)
printf("%d | ", (unsigned int)*(meminp_p+i));
// *** Write to block memory output ***
for (int i = 0; i <= 1023; i++)
*(memout_p+i) = 1023-i;
// *** Read from block memory output ***
printf("\nBlock Memory Output:\n");
for (int i = 0; i <= 1023; i++)
printf("%d | ", (unsigned int)*(memout_p+i));
return 0;
}
```
Program menggunakan XMD atau dalam versi Vitis IDE XSCT tidak berhasil. Setelah mencoba flash dari Vitis IDE Debugger program terflash namun tidak keluar hasil apapun di Serial monitor. Saat berusaha run program, maka muncul error yang belum bisa diselesaikan.

Setelah **men-generate bitstream ulang dan membuat workspace baru pada Vitis IDE**, program berjalan lancar dan mengeluarkan output sesuai ekspektasi. Proses memrogram aplikasi dilakukan melalui Run Configuration dan bukan melalui XSCT karena lebih mudah dan cepat.

## Bagian 3 - Pembuatan IP Core Multiplier
Blok yang akan dibuat IP nya adalah :

Pada Block Design, blok tersebut diimplementasikan dengan .bd berikut.

Berikut hasil simulasi testbench yang sesuai ekpektasi:

## Bagian 4 - Pembuatan IP Core Control Register
Selanjutnya ditambahkan IP Control Register.

Setelah menyiapkan program testbench dan menguji sistem untuk kondisi yang didefinisikan, Hasil simulasi menunjukan kesesuaian.

## Bagian 5 - Implementasi Keseluruhan Sistem
Blok final yang akan diimplementasikan adalah.

Pada Block Design nampak sebagai berikut.

Implementasi masih tidak dapat dilakukan dan menunjukan beberapa error. Setelah melakukan debugging, didapatkan bahwa kendala terdapat di perbedaan antara address editor Vivado

dengan address yang diakses pada program PS Vitis.

bitsream sempat tidak dapat dibuat karena pin reset belum didefinisikan dalam constraint.

Program PS untuk mengakses memori dalam rangka menulis data dan membaca data setelah perhitungna dilakukan dibuat dengan source code dibawah.
```
// *** Author: Erwin Ouyang
// *** Date : 8 Nov 2018
#include <stdio.h>
#include <stdint.h>
#define MEM_INP_BASE 0x40000000
#define MEM_OUT_BASE 0x41000000
#define CTRL_BASE 0x42000000
#define NUM_OF_INPUT 100
uint32_t *meminp_p, *memout_p, *ctrl_p;
int main()
{
// *** Initialize pointer ***
meminp_p = (uint32_t *)MEM_INP_BASE;
memout_p = (uint32_t *)MEM_OUT_BASE;
ctrl_p = (uint32_t *)CTRL_BASE;
55
// Write gain
*(ctrl_p+1) = 10;
// *** Write input ***
printf("\nInput:\n");
for (int i = 0; i < NUM_OF_INPUT; i++)
{
*(meminp_p+i) = i+1;
printf("%05d | ", (unsigned int)*(meminp_p+i));
}
// Write number of input and set start bit
*(ctrl_p+0) = (1 << 10) | NUM_OF_INPUT*4;
// Polling until process is done
while (!(*(ctrl_p+0) & (1 << 11)));
// *** Read from block memory output ***
printf("\nOutput:\n");
for (int i = 0; i < NUM_OF_INPUT; i++)
printf("%05d | ", (unsigned int)*(memout_p+i));
return 0;
}
```
Sehingga pada akhirnya output berhasil dikeluarkan sesuai ekspektasi.

###### tags: `MBKM` `Reinforcement Learning` `SoC`