Extend IOP16 minimal example

From Land Boards Wiki
Jump to navigation Jump to search

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;
signal w_UartDataOut			:	std_logic_vector(7 downto 0);
...
-- 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
    urxd     			=> urxd1,
    utxd     			=> utxd1,
    urts   			=> urts1,
    ucts   			=> ucts1
  );

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_CLOCK_50,
  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

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)

IOP16 PortingGuide UARTLoopbackBefore.PNG

  • Edit code
  • Make sure to save as CSV

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

Test the build