Difference between revisions of "Extend IOP16 minimal example"

From Land Boards Wiki
Jump to navigation Jump to search
 
(110 intermediate revisions by the same user not shown)
Line 1: Line 1:
 
= Overview =
 
= Overview =
  
* This is a guide to extending the [https://github.com/douggilliland/IOP16/tree/main/Higher_Level_Examples/TestIOP16_Minimal minimal IOP example] by adding [[IOP16_Peripheral_Support|IOP16 Peripherals]] to the minimal design
+
This is a guide to extending the [https://github.com/douggilliland/IOP16/tree/main/Higher_Level_Examples/TestIOP16_Minimal minimal IOP example] by adding [[IOP16_Peripheral_Support|IOP16 Peripherals]] to the minimal design
 +
 
 
* This is not the same as [[Embed_IOP16|Embedding the IOP16 into another design]]
 
* This is not the same as [[Embed_IOP16|Embedding the IOP16 into another design]]
 
* This guide requires general familiarity with [[IOP16_16-bit_I/O_CPU_Design|IOP16 16-bit I/O CPU Design]]
 
* This guide requires general familiarity with [[IOP16_16-bit_I/O_CPU_Design|IOP16 16-bit I/O CPU Design]]
 +
* This example does not cover porting to a different FPGA card
 +
** Will need to adjust I/O pin assignments if a different FPGA is used
  
== Clone Sources ==
+
== Steps ==
 +
 
 +
* Start with baseline (minimal) design
 +
* Copy/clone baseline (minimal) design
 +
* Build baseline (minimal) design
 +
* Copy design to new folder
 +
* Select/add peripherals
 +
* Create new peripherals
 +
* Write assembly code
 +
* Build/test
 +
 
 +
== Baseline Design ==
 +
 
 +
Starts from [https://github.com/douggilliland/IOP16/tree/main/Higher_Level_Examples/TestIOP16_Minimal|minimal IOP example]
 +
 
 +
* Similar to [https://www.arduino.cc/en/pmwiki.php?n=Tutorial/Blink Arduino "Blink Sketch"] and uses the following resources
 +
** Timer Unit - 1 second timer
 +
*** The Timer unit can be removed if not needed
 +
*** Timer makes Blink easier
 +
** On-board LED
 +
 
 +
= Copy/Clone Sources =
  
 
* Clone the two repositories to the same directory level since relative paths are used for source files
 
* Clone the two repositories to the same directory level since relative paths are used for source files
 
** [https://github.com/douggilliland/IOP16 IOP16 GitHub repository]
 
** [https://github.com/douggilliland/IOP16 IOP16 GitHub repository]
 
** [https://github.com/douggilliland/Design_A_CPU Design a CPU GitHub repository]
 
** [https://github.com/douggilliland/Design_A_CPU Design a CPU GitHub repository]
 +
* Example copies files to TestBuild folder
 +
* There are a lot of extra files in the two unzipped folders (380MB)
  
=== Alternately download ZIP files ===
+
== Alternately download ZIP files ==
  
 
* Alternately you can download the two ZIP files from GitHub
 
* Alternately you can download the two ZIP files from GitHub
Line 17: Line 43:
 
[[file:IOP16_PortingGuide_Download-Zip-Files.PNG]]
 
[[file:IOP16_PortingGuide_Download-Zip-Files.PNG]]
  
* Unzipped into the same folder  
+
* Unzip these two folders into the same folder  
  
 
[[file:IOP16_PortingGuide_Unzipped-to-Folder.PNG]]
 
[[file:IOP16_PortingGuide_Unzipped-to-Folder.PNG]]
Line 25: Line 51:
 
[[file:IOP16_PortingGuide_Remove-main.PNG]]
 
[[file:IOP16_PortingGuide_Remove-main.PNG]]
  
== Build Minimal Example ==
+
* Result
 +
 
 +
[[file:IOP16_PortingGuide_BuildFolderStructure.PNG]]
 +
 
 +
= Build Minimal Design =
  
 
Start by building the [https://github.com/douggilliland/IOP16/tree/main/Higher_Level_Examples/TestIOP16_Minimal minimal example] in Quartus II
 
Start by building the [https://github.com/douggilliland/IOP16/tree/main/Higher_Level_Examples/TestIOP16_Minimal minimal example] in Quartus II
  
* Open the Project file in Quartus II
+
* Open the Project file (TestIOP16B.qpf) in Quartus II
 +
* Relative path: ..\TestBuild\IOP16\Higher_Level_Examples\TestIOP16_Minimal
  
 
[[file:IOP16_PortingGuide_Open-Project-File.PNG]]
 
[[file:IOP16_PortingGuide_Open-Project-File.PNG]]
Line 37: Line 68:
 
[[file:IOP16_PortingGuide_Entities.PNG]]
 
[[file:IOP16_PortingGuide_Entities.PNG]]
  
* This example does not cover porting to a different FPGA card
+
* Build FPGA (click the blue "Start Compilation arrow)
** Will need to adjust I/O pin assignments if a different FPGA is used
+
 
* May need to re-point to the ROM .MIF file since Quartus II sometimes "forgets"
+
== Fix ROM File Path ==
** Double clicking on the IOP_ROM file
+
 
 +
* Quartus does not verify the ROM file was correct
 +
** Could be buried in the status messages
 +
** Likely need to re-point to the ROM .MIF file since Quartus II sometimes "forgets"
 +
** Double click on the IOP_ROM file
  
 
[[file:IOP16_PortingGuide_Selecting_ROM_2.PNG]]
 
[[file:IOP16_PortingGuide_Selecting_ROM_2.PNG]]
  
== Steps ==
+
* Hit finish
 +
** Check for error message
 +
 
 +
[[file:IOP16_PortingGuide_ROM_Error.PNG]]
 +
 
 +
* Re-point to the ROM file
 +
* Make sure to select .MIF file extension
 +
 
 +
[[file:IOP16_PortingGuide_ROM_TestTimer.PNG]]
 +
 
 +
== Build Again / Download ==
 +
 
 +
* Build again
 +
* Should be no error messages
 +
* Result
 +
 
 +
[[file:IOP16_PortingGuide_FirstBuildResults.PNG]]
 +
 
 +
* Download to FPGA
 +
* Make sure pointing to the right folder
 +
 
 +
[[file:IOP16_PortingGuide_DownloadFPGA.PNG]]
 +
 
 +
* User LED should be blinking
 +
 
 +
= Copy Design to new folder =
 +
 
 +
* Copy from folder ..\TestBuild\IOP16\Higher_Level_Examples\TestIOP16_Minimal
 +
 
 +
[[file:IOP16_PortingGuide_CopyFrom.PNG]]
 +
 
 +
* Copy to folder ..\TestBuild\IOP16\Higher_Level_Examples\TestIOP16_UART_Loopback
 +
 
 +
[[file:IOP16_PortingGuide_CopyTo.PNG]]
  
* Copy baseline design
+
* Build (as above)
* Select/add peripherals
 
* Create new peripherals
 
* Write assembly code
 
  
= Baseline Design =
+
[[file:IOP16_PortingGuide_Open-UART_Project-File.PNG]]
  
* Starts from [https://github.com/douggilliland/IOP16/tree/main/Higher_Level_Examples/TestIOP16_Minimal|minimal IOP example]
+
* Make sure to update ROM file (as above)
** Similar to Arduino "Blink Sketch" and uses the resources
+
* Make sure pointing to the right folder when downloading
*** Timer Unit 0 1 second timer
+
* Test (as above)
*** On-board LED
 
** The Timer unit could be removed if desired
 
*** Timer makes Blink easier
 
* Copy the [https://github.com/douggilliland/IOP16/tree/main/Higher_Level_Examples/TestIOP16_Minimal|the minimal design] to a new folder
 
  
 
= Select Peripherals =
 
= Select Peripherals =
 +
 +
* Pick from [[IOP16_Peripheral_Support|Supported peripherals list]]
 +
 +
== Select UART for example ==
 +
 +
* This example will add [[IOP16_UART|UART peripheral]]
 +
** Will set up [[IOP16_UART|UART]] in loopback
 +
 +
=== Update Memory Map ===
 +
 +
* Update Memory map in comments at start of TestIOP16B.vhd to add UART addresses
 +
<pre>
 +
-- IOP16 MEMORY Map
 +
-- 0X00      - KEY1 Pushbutton (R)
 +
-- 0X00      - User LED (W)
 +
-- 0x04-0x07 - Timer Unit
 +
-- 0X08      - UART (Cmd/Stat) (r/w)
 +
-- 0X09      - UART (Data) (r/w)
 +
</pre>
 +
 +
=== Add UART files to project ===
 +
 +
[[file:IOP16_PortingGuide_AddFiles.PNG]]
 +
 +
* Select VHDL files from \TestBuild\Design_A_CPU\Peripherals\UART folder
 +
 +
[[file:IOP16_PortingGuide_AddUARTFiles.PNG]]
 +
 +
=== Add UART pins to top level entity pins list ===
 +
 +
<pre>
 +
entity TestIOP16B is
 +
  port
 +
  (
 +
    -- Clock and Reset
 +
    i_clk    : in std_logic := '1'; -- Clock (50 MHz)
 +
    i_n_reset : in std_logic := '1'; -- SW2 on FPGA the card
 +
    -- The key and LED on the FPGA card
 +
    i_key1    : in std_logic := '1'; -- SW1 on the FPGA card
 +
    o_UsrLed  : out std_logic := '1'; -- USR LED on the FPGA card
 +
 +
    rxd1      : in std_logic := '1'; -- Hardware Handshake needed
 +
    txd1      : out std_logic;
 +
    cts1      : in std_logic := '1';
 +
    rts1      : out std_logic;
 +
    ...
 +
</pre>
 +
 +
=== Add to signals list ===
 +
 +
<pre>
 +
-- Decodes/Strobes
 +
signal w_wrUart : std_logic;
 +
signal w_rdUart : std_logic;
 +
...
 +
-- Interfaces
 +
signal w_UartDataOut : std_logic_vector(7 downto 0);
 +
...
 +
-- Serial clock enable
 +
signal serialEn      : std_logic; -- 16x baud rate clock
 +
</pre>
 +
 +
=== Add UART instance to section after begin ===
 +
 +
<pre>
 +
-- 6850 style UART
 +
UART: entity work.bufferedUART
 +
  port map (
 +
    clk    => i_CLOCK_50,
 +
    -- Strobes
 +
    n_wr => not w_wrUart,
 +
    n_rd    => not w_rdUart,
 +
    -- CPU
 +
    regSel  => w_periphAdr(0),
 +
    dataIn  => w_periphOut,
 +
    dataOut => w_UartDataOut,
 +
    -- Clock strobes
 +
    rxClkEn => serialEn,
 +
    txClkEn => serialEn,
 +
  -- Serial I/F
 +
    rxd    => rxd1,
 +
    txd    => txd1,
 +
    n_rts  => rts1,
 +
    n_cts  => cts1
 +
  );
 +
</pre>
 +
 +
=== Add Baud Rate Generator instance ===
 +
 +
* Sets baud rate to 115,200 baud
 +
 +
<pre>
 +
-- Baud Rate Generator
 +
-- These clock enables are asserted for one period of input clk, at 16x the baud rate.
 +
-- Set baud rate in BAUD_RATE generic
 +
BAUDRATEGEN : ENTITY work.BaudRate6850
 +
  GENERIC map (
 +
    BAUD_RATE => 115200
 +
  )
 +
  PORT map (
 +
  i_CLOCK_50 => i_clk,
 +
  o_serialEn => serialEn
 +
);
 +
</pre>
 +
 +
=== Add Chip selects logic ===
 +
 +
* Make sure to set the address of the UART (0x08-0x09 in this instance)
 +
 +
<pre>
 +
-- Strobes/Selects
 +
w_wrUart <= '1' when ((w_periphAdr(7 downto 1)="0000100") and (w_periphWr = '1')) else '0';
 +
w_rdUart <= '1' when ((w_periphAdr(7 downto 1)="0000100") and (w_periphRd = '1')) else '0';
 +
</pre>
 +
 +
=== Add UART output data to w_periphIn ===
 +
 +
* Make sure to set the address of the UART (0x08-0x09 in this instance)
 +
 +
<pre>
 +
-- Peripheral bus read mux
 +
w_periphIn <= "0000000"&w_keyBuff when w_periphAdr=x"00" else
 +
                w_timerOut          when w_periphAdr(7 downto 2) = "000001" else
 +
                w_UartDataOut      when w_periphAdr(7 downto 1) = "0000100" else
 +
                x"00";
 +
</pre>
 +
 +
* May have to fix some signal names
 +
** i_CLOCK_50 -> i_clk
 +
 +
=== Update Pins List ===
 +
 +
* New pins may need to be added
 +
 +
=== Verify no build issues ===
 +
 +
* Fix issues until it builds
 +
* Test nothing broke
 +
** LED should blink
  
 
= Create new peripherals =
 
= Create new peripherals =
 +
 +
* Patterned like above example
 +
* Takes in signals w_periphAdr, w_periphOut, w_periphWr, w_periphRd
 +
* Create out signal and add to mux
 +
* Create needed signals
 +
* Create strobes
  
 
= Write Assembly code =
 
= Write Assembly code =
 +
 +
== Add stack if needed ==
 +
 +
* If code will contain single level subroutine, fix cpu_001 calling instance
 +
<pre>
 +
IOP16: ENTITY work.cpu_001
 +
-- Need to pass down instruction RAM and stack sizes
 +
  generic map (
 +
    INST_ROM_SIZE_PASS => 512, -- Small code size since program is "simple"
 +
    STACK_DEPTH_PASS  => 1    -- Single level subroutine (not nested)
 +
)
 +
</pre>
 +
* If code will contain nested subroutines, fix cpu_001 calling instance
 +
<pre>
 +
IOP16: ENTITY work.cpu_001
 +
-- Need to pass down instruction RAM and stack sizes
 +
  generic map (
 +
    INST_ROM_SIZE_PASS => 512, -- Small code size since program is "simple"
 +
    STACK_DEPTH_PASS  => 4    -- Deeper stack
 +
)
 +
</pre>
 +
 +
== Edit example ==
 +
 +
* Start from existing code example \TestBuild\IOP16\IOP16_Code\testTimer folder
 +
* Copy to \TestBuild\IOP16\IOP16_Code\UART_Loopback folder
 +
 +
[[file:IOP16_PortingGuide_UARTLoopbackFolder.PNG]]
 +
 +
* Open UART_Loopback.csv in spreadsheet program (LibreOffice CALC, Excel, etc)
 +
 +
{| class="wikitable"
 +
! LABEL
 +
! OPCODE
 +
! REG_LABEL
 +
! OFFSET_ADDR
 +
! COMMENT
 +
! V3.0.0
 +
|-
 +
| START
 +
| IOW
 +
| 0X08
 +
| 0X00
 +
| WRITE TO LED
 +
|
 +
|-
 +
|
 +
| LRI
 +
| 0X00
 +
| 0X01
 +
| TIME 1 SEC
 +
|
 +
|-
 +
|
 +
| IOW
 +
| 0X00
 +
| 0X06
 +
| STORE TO START TIMER
 +
|
 +
|-
 +
| WAITDUN
 +
| IOR
 +
| 0X01
 +
| 0X04
 +
| READ TIMER
 +
|
 +
|-
 +
|
 +
| ARI
 +
| 0X01
 +
| 0X01
 +
| CHECK BUSY
 +
|
 +
|-
 +
|
 +
| BNZ
 +
| WAITDUN
 +
|
 +
|
 +
|
 +
|-
 +
|
 +
| IOW
 +
| 0X09
 +
| 0X00
 +
| WRITE TO LED
 +
|
 +
|-
 +
|
 +
| LRI
 +
| 0X00
 +
| 0X01
 +
| TIME 1 SEC
 +
|
 +
|-
 +
|
 +
| IOW
 +
| 0X00
 +
| 0X06
 +
| STORE TO START TIMER
 +
|
 +
|-
 +
| WAITD2
 +
| IOR
 +
| 0X01
 +
| 0X04
 +
| READ TIMER
 +
|
 +
|-
 +
|
 +
| ARI
 +
| 0X01
 +
| 0X01
 +
| CHECK BUSY
 +
|
 +
|-
 +
|
 +
| BNZ
 +
| WAITD2
 +
|
 +
|
 +
|
 +
|-
 +
|
 +
| JMP
 +
| START
 +
|
 +
|
 +
|
 +
|-
 +
|}
 +
 +
* Edit code
 +
* Make sure to save as CSV
 +
 +
{| class="wikitable"
 +
! LABEL
 +
! OPCODE
 +
! REG_LABEL
 +
! OFFSET_ADDR
 +
! COMMENT
 +
! V3.0.0
 +
|-
 +
| START
 +
| JSR
 +
| INITURT
 +
|
 +
| INITIALIZE THE ACIA UART
 +
|
 +
|-
 +
|
 +
| LRI
 +
| 0X03
 +
| 0X01
 +
| LED INITIALLY OFF
 +
|
 +
|-
 +
|
 +
| IOW
 +
| 0X03
 +
| 0X00
 +
| WRITE LED
 +
|
 +
|-
 +
| WAITRXD
 +
| IOR
 +
| 0X00
 +
| 0X08
 +
| READ UART STATUS
 +
|
 +
|-
 +
|
 +
| ARI
 +
| 0X00
 +
| 0X01
 +
| MASK RX DATA PRESENT BIT
 +
|
 +
|-
 +
|
 +
| BEZ
 +
| WAITRXD
 +
|
 +
| NO KBD DATA
 +
|
 +
|-
 +
|
 +
| IOR
 +
| 0X01
 +
| 0X09
 +
| READ UART DATA TO REG1
 +
|
 +
|-
 +
| WAITTXR
 +
| IOR
 +
| 0X00
 +
| 0X08
 +
| READ UART STATUS
 +
|
 +
|-
 +
|
 +
| ARI
 +
| 0X00
 +
| 0X02
 +
| MASK TX EMPTY BIT
 +
|
 +
|-
 +
|
 +
| BEZ
 +
| WAITTXR
 +
|
 +
| TX NOT YET READY
 +
|
 +
|-
 +
|
 +
| IOW
 +
| 0X01
 +
| 0X09
 +
| WRITE OUT DATA TO UART
 +
|
 +
|-
 +
|
 +
| XRI
 +
| 0X03
 +
| 0X01
 +
| TOGGLE THE LED
 +
|
 +
|-
 +
|
 +
| IOW
 +
| 0X03
 +
| 0X00
 +
| WRITE LED
 +
|
 +
|-
 +
|
 +
| JMP
 +
| WAITRXD
 +
|
 +
| RINSE AND REPEAT
 +
|
 +
|-
 +
| INITURT
 +
| LRI
 +
| 0X00
 +
| 0X03
 +
| RESET UART COMMAND
 +
|
 +
|-
 +
|
 +
| IOW
 +
| 0X00
 +
| 0X08
 +
| WRITE UART CMD REG
 +
|
 +
|-
 +
|
 +
| LRI
 +
| 0X00
 +
| 0X20
 +
| TX CTRLS RTS
 +
|
 +
|-
 +
|
 +
| IOW
 +
| 0X00
 +
| 0X08
 +
| WRITE UART CMD REG
 +
|
 +
|-
 +
|
 +
| RTS
 +
|
 +
|
 +
|
 +
|
 +
|-
 +
|}
 +
 +
== Assemble ==
 +
 +
* Use Assembler to create .MIF and .LST files
 +
* Assembler is in \TestBuild\Design_A_CPU\Assembler folder
 +
* If Python 3 is installed double click pyAssemble_cpu_001.py to run
 +
* Browse to .\TestBuild\IOP16\IOP16_Code\UART_Loopback folder
 +
* Select UART_Loopback.csv file
 +
* Output .MIF and .LST files will be written to folder
 +
 +
=== Update .MIF file in ROM ===
 +
 +
* Update (as above)
 +
 +
[[file:IOP16_PortingGuide_Selecting_ROM_2.PNG]]
 +
 +
* Set path to new code
 +
* Make sure to set extension to .MIF
 +
 +
[[file:IOP16_PortingGuide_Selecting_ROM_3.PNG]]
 +
 +
* Resources
 +
 +
[[file:IOP16_PortingGuide_AppResources.PNG]]
  
 
= Test the build =
 
= Test the build =
 +
 +
* Download code to FPGA
 +
* Run puTTY
 +
** 115,200 baud
 +
** RTS/CTS handshake
 +
* Type on keyboard
 +
* Chars will loopback on serial
 +
* LED will toggle on/off with each character
 +
 +
[[file:IOP16_PortingGuide_puTTY_Cap.PNG]]
 +
 +
== UART Loopback build ==
 +
 +
* Branches of the trees that capture these changes
 +
** [https://github.com/douggilliland/IOP16/tree/UARTLoopback IOP-16 UARTLoopback Tree]
 +
** [https://github.com/douggilliland/Design_A_CPU/tree/UARTLoopback Design a CPU UARTLoopback Tree]
 +
 +
= Debug using SignalTap =
 +
 +
* SignalTap is an embedded Logic Analyzer
 +
** Can be used to debug designs
 +
* Right click on device Settings
 +
* Select .stp file
 +
 +
[[file:IOP16_PortingGuide_SignalTapDebug01.PNG]]
 +
 +
* Select Tools, Signal Tap Logic Analyzer
 +
 +
[[file:IOP16_PortingGuide_SignalTapDebug02.PNG]]
 +
 +
* Add nodes
 +
 +
[[file:IOP16_PortingGuide_SignalTapDebug03.PNG]]
 +
 +
# Compile
 +
# Download
 +
# Start capture
 +
# Press reset to trigger
 +
 +
[[file:IOP16_PortingGuide_SignalTapDebug04.PNG]]

Latest revision as of 10:46, 14 April 2022

Overview

This is a guide to extending the minimal IOP example by adding IOP16 Peripherals to the minimal design

Steps

  • Start with baseline (minimal) design
  • Copy/clone baseline (minimal) design
  • Build baseline (minimal) design
  • Copy design to new folder
  • Select/add peripherals
  • Create new peripherals
  • Write assembly code
  • Build/test

Baseline Design

Starts from IOP example

  • Similar to Arduino "Blink Sketch" and uses the following resources
    • Timer Unit - 1 second timer
      • The Timer unit can be removed if not needed
      • Timer makes Blink easier
    • On-board LED

Copy/Clone Sources

Alternately download ZIP files

  • Alternately you can download the two ZIP files from GitHub

IOP16 PortingGuide Download-Zip-Files.PNG

  • Unzip these two folders into the same folder

IOP16 PortingGuide Unzipped-to-Folder.PNG

  • Rename the folders to remove the -main from the folder path

IOP16 PortingGuide Remove-main.PNG

  • Result

IOP16 PortingGuide BuildFolderStructure.PNG

Build Minimal Design

Start by building the minimal example in Quartus II

  • Open the Project file (TestIOP16B.qpf) in Quartus II
  • Relative path: ..\TestBuild\IOP16\Higher_Level_Examples\TestIOP16_Minimal

IOP16 PortingGuide Open-Project-File.PNG

  • Entities in Quartus should look like

IOP16 PortingGuide Entities.PNG

  • Build FPGA (click the blue "Start Compilation arrow)

Fix ROM File Path

  • Quartus does not verify the ROM file was correct
    • Could be buried in the status messages
    • Likely need to re-point to the ROM .MIF file since Quartus II sometimes "forgets"
    • Double click on the IOP_ROM file

IOP16 PortingGuide Selecting ROM 2.PNG

  • Hit finish
    • Check for error message

IOP16 PortingGuide ROM Error.PNG

  • Re-point to the ROM file
  • Make sure to select .MIF file extension

IOP16 PortingGuide ROM TestTimer.PNG

Build Again / Download

  • Build again
  • Should be no error messages
  • Result

IOP16 PortingGuide FirstBuildResults.PNG

  • Download to FPGA
  • Make sure pointing to the right folder

IOP16 PortingGuide DownloadFPGA.PNG

  • User LED should be blinking

Copy Design to new folder

  • Copy from folder ..\TestBuild\IOP16\Higher_Level_Examples\TestIOP16_Minimal

IOP16 PortingGuide CopyFrom.PNG

  • Copy to folder ..\TestBuild\IOP16\Higher_Level_Examples\TestIOP16_UART_Loopback

IOP16 PortingGuide CopyTo.PNG

  • Build (as above)

IOP16 PortingGuide Open-UART Project-File.PNG

  • Make sure to update ROM file (as above)
  • Make sure pointing to the right folder when downloading
  • Test (as above)

Select Peripherals

Select UART for example

Update Memory Map

  • Update Memory map in comments at start of TestIOP16B.vhd to add UART addresses
-- IOP16 MEMORY Map
-- 0X00      - KEY1 Pushbutton (R)
-- 0X00      - User LED (W)
-- 0x04-0x07 - Timer Unit
-- 0X08      - UART (Cmd/Stat) (r/w)
-- 0X09      - UART (Data) (r/w)

Add UART files to project

IOP16 PortingGuide AddFiles.PNG

  • Select VHDL files from \TestBuild\Design_A_CPU\Peripherals\UART folder

IOP16 PortingGuide AddUARTFiles.PNG

Add UART pins to top level entity pins list

entity TestIOP16B is
  port
  (
    -- Clock and Reset
    i_clk     : in std_logic := '1';		-- Clock (50 MHz)
    i_n_reset : in std_logic := '1';		-- SW2 on FPGA the card
    -- The key and LED on the FPGA card 
    i_key1    : in std_logic := '1';		-- SW1 on the FPGA card
    o_UsrLed  : out std_logic := '1';		-- USR LED on the FPGA card
		
    rxd1      : in std_logic := '1';		-- Hardware Handshake needed
    txd1      : out std_logic;
    cts1      : in std_logic := '1';
    rts1      : out std_logic;
    ...

Add to signals list

-- Decodes/Strobes
signal w_wrUart				:	std_logic;
signal w_rdUart				:	std_logic;
...
-- Interfaces
signal w_UartDataOut			:	std_logic_vector(7 downto 0);
...
-- Serial clock enable
signal serialEn      		: std_logic;		-- 16x baud rate clock

Add UART instance to section after begin

-- 6850 style UART
UART: entity work.bufferedUART
  port map (
    clk     			=> i_CLOCK_50,
    -- Strobes
    n_wr				=> not w_wrUart,
    n_rd    			=> not w_rdUart,
    -- CPU 
    regSel  			=> w_periphAdr(0),
    dataIn  			=> w_periphOut,
    dataOut 			=> w_UartDataOut,
    -- Clock strobes
    rxClkEn 			=> serialEn,
    txClkEn 			=> serialEn,
   -- Serial I/F
    rxd     			=> rxd1,
    txd     			=> txd1,
    n_rts   			=> rts1,
    n_cts   			=> cts1
  );

Add Baud Rate Generator instance

  • Sets baud rate to 115,200 baud
-- Baud Rate Generator
-- These clock enables are asserted for one period of input clk, at 16x the baud rate.
-- Set baud rate in BAUD_RATE generic
BAUDRATEGEN	:	ENTITY work.BaudRate6850
  GENERIC map (
    BAUD_RATE	=> 115200
  )
  PORT map (
  i_CLOCK_50	=> i_clk,
  o_serialEn	=> serialEn
);

Add Chip selects logic

  • Make sure to set the address of the UART (0x08-0x09 in this instance)
-- Strobes/Selects
w_wrUart <= '1' when ((w_periphAdr(7 downto 1)="0000100") and (w_periphWr = '1')) else '0';
w_rdUart <= '1' when ((w_periphAdr(7 downto 1)="0000100") and (w_periphRd = '1')) else '0';

Add UART output data to w_periphIn

  • Make sure to set the address of the UART (0x08-0x09 in this instance)
-- Peripheral bus read mux
w_periphIn <=	"0000000"&w_keyBuff when w_periphAdr=x"00"							else
                w_timerOut          when w_periphAdr(7 downto 2) = "000001"	else
                w_UartDataOut       when w_periphAdr(7 downto 1) = "0000100"	else
                x"00";
  • May have to fix some signal names
    • i_CLOCK_50 -> i_clk

Update Pins List

  • New pins may need to be added

Verify no build issues

  • Fix issues until it builds
  • Test nothing broke
    • LED should blink

Create new peripherals

  • Patterned like above example
  • Takes in signals w_periphAdr, w_periphOut, w_periphWr, w_periphRd
  • Create out signal and add to mux
  • Create needed signals
  • Create strobes

Write Assembly code

Add stack if needed

  • If code will contain single level subroutine, fix cpu_001 calling instance
IOP16: ENTITY work.cpu_001
-- Need to pass down instruction RAM and stack sizes
  generic map 	( 
    INST_ROM_SIZE_PASS => 512, -- Small code size since program is "simple"
    STACK_DEPTH_PASS   => 1    -- Single level subroutine (not nested)
)
  • If code will contain nested subroutines, fix cpu_001 calling instance
IOP16: ENTITY work.cpu_001
-- Need to pass down instruction RAM and stack sizes
  generic map 	( 
    INST_ROM_SIZE_PASS => 512, -- Small code size since program is "simple"
    STACK_DEPTH_PASS   => 4    -- Deeper stack
)

Edit example

  • Start from existing code example \TestBuild\IOP16\IOP16_Code\testTimer folder
  • Copy to \TestBuild\IOP16\IOP16_Code\UART_Loopback folder

IOP16 PortingGuide UARTLoopbackFolder.PNG

  • Open UART_Loopback.csv in spreadsheet program (LibreOffice CALC, Excel, etc)
LABEL OPCODE REG_LABEL OFFSET_ADDR COMMENT V3.0.0
START IOW 0X08 0X00 WRITE TO LED
LRI 0X00 0X01 TIME 1 SEC
IOW 0X00 0X06 STORE TO START TIMER
WAITDUN IOR 0X01 0X04 READ TIMER
ARI 0X01 0X01 CHECK BUSY
BNZ WAITDUN
IOW 0X09 0X00 WRITE TO LED
LRI 0X00 0X01 TIME 1 SEC
IOW 0X00 0X06 STORE TO START TIMER
WAITD2 IOR 0X01 0X04 READ TIMER
ARI 0X01 0X01 CHECK BUSY
BNZ WAITD2
JMP START
  • Edit code
  • Make sure to save as CSV
LABEL OPCODE REG_LABEL OFFSET_ADDR COMMENT V3.0.0
START JSR INITURT INITIALIZE THE ACIA UART
LRI 0X03 0X01 LED INITIALLY OFF
IOW 0X03 0X00 WRITE LED
WAITRXD IOR 0X00 0X08 READ UART STATUS
ARI 0X00 0X01 MASK RX DATA PRESENT BIT
BEZ WAITRXD NO KBD DATA
IOR 0X01 0X09 READ UART DATA TO REG1
WAITTXR IOR 0X00 0X08 READ UART STATUS
ARI 0X00 0X02 MASK TX EMPTY BIT
BEZ WAITTXR TX NOT YET READY
IOW 0X01 0X09 WRITE OUT DATA TO UART
XRI 0X03 0X01 TOGGLE THE LED
IOW 0X03 0X00 WRITE LED
JMP WAITRXD RINSE AND REPEAT
INITURT LRI 0X00 0X03 RESET UART COMMAND
IOW 0X00 0X08 WRITE UART CMD REG
LRI 0X00 0X20 TX CTRLS RTS
IOW 0X00 0X08 WRITE UART CMD REG
RTS

Assemble

  • Use Assembler to create .MIF and .LST files
  • Assembler is in \TestBuild\Design_A_CPU\Assembler folder
  • If Python 3 is installed double click pyAssemble_cpu_001.py to run
  • Browse to .\TestBuild\IOP16\IOP16_Code\UART_Loopback folder
  • Select UART_Loopback.csv file
  • Output .MIF and .LST files will be written to folder

Update .MIF file in ROM

  • Update (as above)

IOP16 PortingGuide Selecting ROM 2.PNG

  • Set path to new code
  • Make sure to set extension to .MIF

IOP16 PortingGuide Selecting ROM 3.PNG

  • Resources

IOP16 PortingGuide AppResources.PNG

Test the build

  • Download code to FPGA
  • Run puTTY
    • 115,200 baud
    • RTS/CTS handshake
  • Type on keyboard
  • Chars will loopback on serial
  • LED will toggle on/off with each character

IOP16 PortingGuide puTTY Cap.PNG

UART Loopback build

Debug using SignalTap

  • SignalTap is an embedded Logic Analyzer
    • Can be used to debug designs
  • Right click on device Settings
  • Select .stp file

IOP16 PortingGuide SignalTapDebug01.PNG

  • Select Tools, Signal Tap Logic Analyzer

IOP16 PortingGuide SignalTapDebug02.PNG

  • Add nodes

IOP16 PortingGuide SignalTapDebug03.PNG

  1. Compile
  2. Download
  3. Start capture
  4. Press reset to trigger

IOP16 PortingGuide SignalTapDebug04.PNG