LoginSignup
13
10

More than 5 years have passed since last update.

FPGAでハードウェアアクセラレータを作る:①ワークメモリを作る

Last updated at Posted at 2017-10-21

まえおき

以前 投稿しました「Spartan6でmicroblaze mcs を動かす」にて、FPGA上でCPUを動作させることが可能になりました。

今後ハードウェアアクセラレータもどきを増築していきたいと思います。

ハードウェアアクセラレータとは

ハードウェアアクセラレータとはCPUのバスにぶら下がっている専用の演算回路です。
特徴としては以下のようなメリットがあります。

  • 特定の演算処理をCPUに代わって行うハードウェア
  • CPUはアクセラレータに指示を投げて、結果だけをもう
  • アクセラレータが演算中、CPUは他の処理を行うことができる
  • 演算を並列処理できる(作り方次第)

構成

モジュールを以下のように構成します

IP_1.jpg

  • BUS I/F(バス信号のI/F)
    • メモリ(BlockRAM)のリードライトを行う
  • DualPortMEM
    • データを貯めるデュアルポートメモリ
    • AポートはCPUから読み書きできる
    • BポートはLogic部から読み書きできる
    • AポートとBポートは非同期クロック
  • Logic部(演算処理回路)
    • CPUからアクセスできる演算命令用のレジスタを実装する
    • 演算命令に応じてBRAMからデータを取り出し、演算結果をBRAMに書き戻す

今回作る回路

今回はBUS/Fとメモリの部分までを作成することとし、CPUからメモリに読み書きできることを目標にします。
(演算ロジック部分は次回の投稿にします)

CPU バス I/F

CPUバスからのシングルリード/ライトアクセスの概要
IP_2.jpg

Microblaze_MCSのポート名 図中の略称 機能 説明
IO_Addr_Strobe a_stb アドレスストローブ Hのときアドレスが有効
IO_Read_Strobe r_stb リードストローブ Hでリードを要求
IO_Write_Strobe w_stb ライトストローブ Hのときライトデータが有効
IO_Address adr アドレス アクセス先のアドレスを示す
Microblaze_mcsは0xC000_0000がバス空間の先頭アドレス
IO_Byte_Enable be バイトイネーブル 32bitバス(4Byte)のうちアクセス対象Byteを示す。
intでアクセス⇒1111
shortでアクセス⇒0011 or 1100
charでアクセス⇒0001 or 0010 or 0100 or 1000
IO_Write_Data w_dat ライトデータ 書き込みデータです
IO_Read_Data r_dat リードデータ リードストローブが来たらレディがHになる間だけ出力します。
そのほかはL固定(他のモジュールとワイヤーORで共有するので)
IO_Ready rdy レディ応答 リード時:有効なリードデータとともにアサート
ライト時:処理完了後アサート<※>Microblazeはレディが帰ってこないとハングアップするので要注意!!

RTL図

IP_3.jpg

ブロック 概要
入力FF バスの信号を一度叩くFFです
WriteContlorl ブロックRAMのライトイネーブル信号を生成します
上位アドレスがヒットしているBRAMに対してバイトイネーブルとライトストローブのANDを通します。
ReadContlorl 上位アドレスがヒットしているBRAMの出力を後段のセレクタでセレクトするための制御信号を生成します
BRAM メモリ本体です、BRAMを3面インスタンスしています。

VHDLコード

バスの信号を1つづつ毎回記述すると、回路を複製するときに記述が多くなるのは嫌です。
バスの信号はパッケージにユーザー定義型(C言語でいう構造体みたいなもの)に定義して記述しました。

BUS_IF_package.vhd
-----------------------------------------------------------
-- Microblaze_MCSのバス信号 型定義
-----------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;

package BUS_IF_package is

    -------------------------------------------------------
    --バス リクエスト(CPU => IP)
    -------------------------------------------------------
    --型定義
    type t_BUS_REQ is record
        a_stb   :std_logic                      ;--Address Strobe
        adr     :std_logic_vector(31 downto 0)  ;--Address
        w_stb   :std_logic                      ;--Write Strobe
        w_dat   :std_logic_vector(31 downto 0)  ;--Write Data
        be      :std_logic_vector(3 downto 0)   ;--Byte Enable
        r_stb   :std_logic                      ;--Read Strobe
    end record;

    --配列
    type ta_BUS_REQ
        is array(integer range <>) of t_BUS_REQ;

    --初期値
    constant t_BUS_REQ_ini  :t_BUS_REQ:=('0',x"00000000",'0',x"00000000","0000",'0');

    -------------------------------------------------------
    --バス レスポンス(COU <= IP)
    -------------------------------------------------------
    --型定義
    type t_BUS_RES is record
        rdy     :std_logic                      ;--Ready
        r_dat   :std_logic_vector(31 downto 0)  ;--Read Data
    end record;

    --配列
    type ta_BUS_RES
        is array(integer range <>) of t_BUS_RES; 

    --初期値
    constant t_BUS_RES_ini  :t_BUS_RES  :=('0',x"00000000");

end package;
BUS_IF.vhd
--------------------------------------------------------------------
-- CPUバスにぶら下げるワークメモリ
-- DualPortRAM(32bit×512)を2面インスタンスしている
-- 
-- ※今後RAMのデータを演算するロジックを追加して演算アクセラレータにする
--  ------------+--------------------
--  BA + 0x0800 |ワークメモリA面
--      :       |
--  BA + 0x07FF |
--  ------------+--------------------
--  BA + 0x0800 |ワークメモリB面
--      :       |
--  BA + 0x0FFF |
--  ------------+--------------------
--  BA + 0x1000 |ワークメモリC面
--      :       |
--  BA + 0x17FF |
--  ------------+--------------------
--  BA + 0x1000 |ロジック領域
--      :       |(演算命令レジスタ)
--  BA + 0x17FF |※今後追加
--------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

use work.BUS_IF_package.all;--CPUバスをまとめたType宣言を読み込む

    entity BUS_IF is
        generic(
        BASE_ADR    :std_logic_vector(31 downto 0)      );--ベースアドレス
        port(
        i_rst       :in     std_logic                   ;--リセット
        i_bus_clk   :in     std_logic                   ;--クロック
        i_bus       :in     t_BUS_REQ                   ;--CPU_BUS
        o_bus       :out    t_BUS_RES                   );--CPU_BUS
    end entity;

architecture rtl of BUS_IF is
    constant    N   :integer    :=2;--メモリインスタンス数-1
    -----------------------------------------------------------------
    -- Type
    -----------------------------------------------------------------
    --ライトイネーブルをアレイにした型定義
    type typ_WEA is 
        array(integer range <>) of std_logic_vector(3 downto 0);
    --BRAM出力データのアレイ型
    type typ_DOUT is 
        array(integer range <>) of std_logic_vector(31 downto 0);
    -----------------------------------------------------------------
    -- Signal
    -----------------------------------------------------------------
    --入力FF
    signal  be      :std_logic_vector(3 downto 0)   :=(others=>'0') ;
    signal  adr     :std_logic_vector(31 downto 0)  :=(others=>'0') ;
    signal  w_stb   :std_logic                      :='0'           ;
    signal  w_dat   :std_logic_vector(31 downto 0)  :=(others=>'0') ;
    signal  r_stb   :std_logic                      :='0'           ;
    --
    signal  rd_cnt  :std_logic_vector(0 to N)       :=(others=>'0') ;
    signal  r_valid :std_logic_vector(0 to N)       :=(others=>'0') ;
    --
    signal  rdy_or  :std_logic                                      ;
    signal  rdy     :std_logic                      :='0'           ;
    signal  r_dat   :std_logic_vector(31 downto 0)  :=(others=>'0') ;
    signal  hit_mem :std_logic_vector(0 to N)                       ;
    --Memory I/F
    signal  rsta    :std_logic_vector(N downto 0)   :=(others=>'0') ;
    --Memory I/F(A side)
    signal  wea     :typ_WEA(0 to N)                :=(others=>x"0");
    signal  addra   :std_logic_vector(8 downto 0)                   ;
    signal  dina    :std_logic_vector(31 downto 0)                  ;
    signal  douta   :typ_DOUT(0 to N)                           ;
    --Memory I/F(B side)
    signal  web     :std_logic_vector(3 downto 0)   :=(others=>'0') ;
    signal  addrb   :std_logic_vector(8 downto 0)   :=(others=>'0') ;
    signal  dinb    :std_logic_vector(31 downto 0)  :=(others=>'0') ;
    signal  doutb   :typ_DOUT(0 to N)                               ;

begin   

    ---------------------------------------
    --CPUバスインターフェース
    ---------------------------------------
    process(i_bus_clk)begin
        if(Rising_edge(i_bus_clk))then
            ------------------------
            --Stage1:入力信号受けFF
            ------------------------
            --アドレス
            if(i_bus.a_stb='1')then
                adr <=i_bus.adr;
            end if;
            --バイトイネーブル
            be(0)   <=i_bus.be(0);
            be(1)   <=i_bus.be(1);
            be(2)   <=i_bus.be(2);
            be(3)   <=i_bus.be(3);
            --ライトストローブ
            w_stb   <=i_bus.w_stb;
            --ライトデータ
            if(i_bus.w_stb='1')then
                w_dat   <=i_bus.w_dat;
            end if;
            --リードストローブ
            r_stb   <=i_bus.r_stb;

            --------------------------
            --Stage2:
            --------------------------
            --メモリリードデータ有効
            r_valid <=rd_cnt;

            --------------------------
            --Stage3
            --------------------------
            --読み出しデータ
            case(r_valid)is
                when "100"  =>r_dat <=douta(0);--A面
                when "010"  =>r_dat <=douta(1);--B面
                when "001"  =>r_dat <=douta(2);--C面
                when others =>r_dat <=(others=>'0');--応答時以外0固定
            end case;

            --レディ応答
            rdy     <=rdy_or;
        end if;
    end process;

    ---------------------------------------
    --メモリアクセス制御
    ---------------------------------------
    MEM_CONTLORL:for i in 0 to N generate
        --アドレス上位ヒット判定
        hit_mem(i)  <='1' when (adr(31 downto 11)=BASE_ADR(31 downto 11)+i)else '0';

        --ライトコントロール
        wea(i)  <=be when (hit_mem(i)='1') and (w_stb='1') else "0000";

        --リードコントロール
        rd_cnt(i)   <='1' when (hit_mem(i)='1') and (r_stb='1') else '0';
    end generate;

    --レディ応答条件
    rdy_or  <='1' when 
        (r_valid/="000" ) or
        (wea(0) /="0000") or
        (wea(1) /="0000") or
        (wea(2) /="0000") else '0';

    --BRAM物理アドレス:512word =>9bit分接続 (1word = 4Byteなので下位2bitは捨て)
    addra(8 downto 0)   <=adr(10 downto 2);

    --BRAMライトデータ:32bitそのまま接続
    dina(31 downto 0)   <=w_dat(31 downto 0);

    --2KByte(32bit×512)デュアルポートメモリ(2面インスタンス)
    MEM:for i in 0 to N generate
        mWORK_MEM:entity work.WORK_MEM
        port map
        --A port(CPU side)-------
        (clka   =>i_bus_clk
        ,rsta   =>rsta(i)   
        ,wea    =>wea(i)    
        ,addra  =>addra     
        ,dina   =>dina      
        ,douta  =>douta(i)  
        --B port(Logic side)-----
        ,clkb   =>i_bus_clk     --未使用
        ,web    =>"0000"        --未使用
        ,addrb  =>"000000000"   --未使用
        ,dinb   =>x"00000000"   --未使用
        ,doutb  =>doutb(i)      --未使用
        );
    end generate;

    --Output Port
    o_bus.rdy   <=rdy   ;
    o_bus.r_dat <=r_dat ;

end architecture;

検証用ソフト

検証用のCのコードを作成します。

検証内容 検証目的
char,short,int型のサイズを調べる 32bbitバスなのでint=4Byteのはずだけど本当か?
BRAM3面分の初期値を読みだす 書き込む前の値を確認する
RAM-A面にcharでインクリメントデータを書き込む 1Byte毎にインクリメントしているはず
RAM-B面にshortでインクリメントデータを書き込む 2Byte毎にインクリメントしているはず
RAM-C面にintでインクリメントデータを書き込む 4Byte毎にインクリメントしているはず
3つのRAMをすべてcharで読みだす 上記3つの「~Byte毎にインクリメントしているはず」が正しいか確認
main.c
#include "platform.h"       //とりあえず必要
#include "mb_interface.h"   //とりあえず必要
#include "ADR_MAP.h"        //自前のヘッダファイル

//ASCIIコードのバイナリ定義
    #define BS      0x08    //バックスペース
    #define CR      0x0D    //復帰
    #define LF      0x0A    //改行
    #define ESC     0x1B    //エスケープ

//-----------------------------
//グローバル変数
//-----------------------------
    unsigned char g_led=0x7F;

//-------------------------------------------------------------------------------
//割込みハンドラ
//-------------------------------------------------------------------------------
void Int_Handl(void) {
    unsigned char msg;
    int i;
    unsigned char p=0;
    unsigned char n;

    //割り込みフラグ落とす
    IRQ_ACK = 0xFFFFFFFF;

    //受信文字を持ってくる
    msg=UART_RX;

    //エコーバック
    xil_printf("%c",msg);

    //受信文字に応じた処理
    switch(msg){
        case CR://エンター
            //LEDをインクリメント
            g_led++;
            GPO1=g_led;
            break;
        case BS://バックスペース
            //LEDをデクリメント
            g_led--;
            GPO1=g_led;
            break;
        default://
            //なにもしない
            break;
    }//switch
}
//============================================================
//256Byte読み出し:char型
//============================================================
void ReaderChar(unsigned char* StartPoint){
    unsigned int    i , j;
    unsigned char*  pt;

    pt = StartPoint;
    xil_printf("----------------------------------------------------------\r");
    xil_printf(" Char Read : Start Addres = 0x%08X\r",pt);
    xil_printf("----------------------------------------------------------\r");
    xil_printf("  Address |+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F\r");
    for(i=0; i<16; i++){
        xil_printf("0x%04X|",pt);
        for(j=0; j<16; j++){
            xil_printf("%02X ",*pt);
            pt++;
        }
        xil_printf("\r");
    }
}
//============================================================
//256Byte読み出し:short型
//============================================================
void ReaderShort(unsigned short* StartPoint){
    unsigned int    i , j;
    unsigned short* pt;

    pt = StartPoint;
    xil_printf("--------------------------------------------------\r");
    xil_printf(" Short Read : Start Addres = 0x%08X\r",pt);
    xil_printf("--------------------------------------------------\r");
    xil_printf("  Address | +0   +2   +4   +6   +8   +A   +C   +E \r");
    for(i=0; i<16; i++){
        xil_printf("0x%04X|",pt);
        for(j=0; j<8; j++){
            xil_printf("%04X ",*pt);
            pt++;
        }
        xil_printf("\r");
    }
}
//============================================================
//256Byte読み出し:int型
//============================================================
void ReaderInt(unsigned int* StartPoint){
    unsigned int    i , j;
    unsigned int*   pt;

    pt = StartPoint;
    xil_printf("----------------------------------------------\r");
    xil_printf(" Int Read : Start Addres = 0x%08X\r",pt);
    xil_printf("----------------------------------------------\r");
    xil_printf("  Address |   +0       +4       +8       +C\r");
    for(i=0; i<16; i++){
        xil_printf("0x%04X|",pt);
        for(j=0; j<4; j++){
            xil_printf("%08X ",*pt);
            pt++;
        }
        xil_printf("\r");
    }
}
//============================================================
//256Byteゼロフィル
//============================================================
void ZeroClear(unsigned int* StartPoint){
    unsigned int    i;
    unsigned int*   pt;
    pt = StartPoint;
    xil_printf("-----------------------------------------\r");
    xil_printf(" Zero clear : Start Addres = 0x%08X\r",pt);
    xil_printf("-----------------------------------------\r");
    for(i=0; i<256; i++){
        *pt=0;
        pt++;
    }
}
//============================================================
//メインループ
//============================================================
void main()
{
    unsigned int*       start_adr=0;
    unsigned int        i=0;
    unsigned char*      pt_c;//
    unsigned short*     pt_s;//
    unsigned int*       pt_i;//

    //================================================
    //ハードの初期化
        init_platform();
    //割込みハンドラの登録
        microblaze_register_handler((XInterruptHandler)Int_Handl,(void*)0);
    //使用する割込み選択(bit[2]⇒UART割り込み)
        IRQ_ENABLE = 0x00000004;
    //割り込みを有効にする
        microblaze_enable_interrupts();
    //================================================

    xil_printf("*******************\r");
    xil_printf("Start!!\r");
    xil_printf("Size of char =%d\r",sizeof(unsigned char));
    xil_printf("Size of short=%d\r",sizeof(unsigned short));
    xil_printf("Size of int  =%d\r",sizeof(unsigned int));
    xil_printf("Size of long =%d\r",sizeof(unsigned long));
    xil_printf("*******************\r");

    //初期値読み出し
    start_adr=0xC0000000;
        ReaderChar(0xC0000000);     //A面
        ReaderShort(0xC0000800);    //B面
        ReaderInt(0xC0001000);      //C面
    ///////////////////////////////////////
    //メモリAにキャラで書き込み
    xil_printf("Write increment dta\r");
    pt_c=0xC0000000;
    pt_s=0xC0000800;
    pt_i=0xC0001000;

    for(i=0; i<256; i++){
        *pt_c = (unsigned char)i;
        pt_c++;
    }
    //メモリBにショート型で書き込み
    for(i=0; i<128; i++){
        *pt_s = (unsigned short)i;
        pt_s++;
    }
    //メモリCにイントき込み
    for(i=0; i<64; i++){
        *pt_i = (unsigned int)i;
        pt_i++;
    }
    ///////////////////////////////////////

    //読み出し(あえて全部キャラで読む)
        ReaderChar(0xC0000000); //A面
        ReaderChar(0xC0000800); //B面
        ReaderChar(0xC0001000); //C面

    //--------------------------------------------
    //メインループ
    //--------------------------------------------
    while(1){

    }

}

実機検証結果

ターミナルのログを確認しました。
* intは4byte、shortは2byteでした想定通りの動作でした。
* charで読みだした結果、Byte単位でLSBファーストでした。

*******************
Start!!
Size of char =1
Size of short=2
Size of int  =4
Size of long =4
*******************
----------------------------------------------------------
 Char Read : Start Addres = 0xC0000000
----------------------------------------------------------
  Address |+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
0xC0000000|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0xC0000010|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0xC0000020|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0xC0000030|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0xC0000040|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0xC0000050|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0xC0000060|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0xC0000070|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0xC0000080|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0xC0000090|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0xC00000A0|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0xC00000B0|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0xC00000C0|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0xC00000D0|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0xC00000E0|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0xC00000F0|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
--------------------------------------------------
 Short Read : Start Addres = 0xC0000800
--------------------------------------------------
  Address | +0   +2   +4   +6   +8   +A   +C   +E
0xC0000800|0000 0000 0000 0000 0000 0000 0000 0000
0xC0000810|0000 0000 0000 0000 0000 0000 0000 0000
0xC0000820|0000 0000 0000 0000 0000 0000 0000 0000
0xC0000830|0000 0000 0000 0000 0000 0000 0000 0000
0xC0000840|0000 0000 0000 0000 0000 0000 0000 0000
0xC0000850|0000 0000 0000 0000 0000 0000 0000 0000
0xC0000860|0000 0000 0000 0000 0000 0000 0000 0000
0xC0000870|0000 0000 0000 0000 0000 0000 0000 0000
0xC0000880|0000 0000 0000 0000 0000 0000 0000 0000
0xC0000890|0000 0000 0000 0000 0000 0000 0000 0000
0xC00008A0|0000 0000 0000 0000 0000 0000 0000 0000
0xC00008B0|0000 0000 0000 0000 0000 0000 0000 0000
0xC00008C0|0000 0000 0000 0000 0000 0000 0000 0000
0xC00008D0|0000 0000 0000 0000 0000 0000 0000 0000
0xC00008E0|0000 0000 0000 0000 0000 0000 0000 0000
0xC00008F0|0000 0000 0000 0000 0000 0000 0000 0000
----------------------------------------------
 Int Read : Start Addres = 0xC0001000
----------------------------------------------
  Address |   +0       +4       +8       +C
0xC0001000|00000000 00000000 00000000 00000000
0xC0001010|00000000 00000000 00000000 00000000
0xC0001020|00000000 00000000 00000000 00000000
0xC0001030|00000000 00000000 00000000 00000000
0xC0001040|00000000 00000000 00000000 00000000
0xC0001050|00000000 00000000 00000000 00000000
0xC0001060|00000000 00000000 00000000 00000000
0xC0001070|00000000 00000000 00000000 00000000
0xC0001080|00000000 00000000 00000000 00000000
0xC0001090|00000000 00000000 00000000 00000000
0xC00010A0|00000000 00000000 00000000 00000000
0xC00010B0|00000000 00000000 00000000 00000000
0xC00010C0|00000000 00000000 00000000 00000000
0xC00010D0|00000000 00000000 00000000 00000000
0xC00010E0|00000000 00000000 00000000 00000000
0xC00010F0|00000000 00000000 00000000 00000000
Write increment dta
----------------------------------------------------------
 Char Read : Start Addres = 0xC0000000
----------------------------------------------------------
  Address |+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
0xC0000000|00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
0xC0000010|10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
0xC0000020|20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
0xC0000030|30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
0xC0000040|40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
0xC0000050|50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
0xC0000060|60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
0xC0000070|70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
0xC0000080|80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
0xC0000090|90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
0xC00000A0|A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
0xC00000B0|B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
0xC00000C0|C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
0xC00000D0|D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
0xC00000E0|E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
0xC00000F0|F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
----------------------------------------------------------
 Char Read : Start Addres = 0xC0000800
----------------------------------------------------------
  Address |+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
0xC0000800|00 00 01 00 02 00 03 00 04 00 05 00 06 00 07 00
0xC0000810|08 00 09 00 0A 00 0B 00 0C 00 0D 00 0E 00 0F 00
0xC0000820|10 00 11 00 12 00 13 00 14 00 15 00 16 00 17 00
0xC0000830|18 00 19 00 1A 00 1B 00 1C 00 1D 00 1E 00 1F 00
0xC0000840|20 00 21 00 22 00 23 00 24 00 25 00 26 00 27 00
0xC0000850|28 00 29 00 2A 00 2B 00 2C 00 2D 00 2E 00 2F 00
0xC0000860|30 00 31 00 32 00 33 00 34 00 35 00 36 00 37 00
0xC0000870|38 00 39 00 3A 00 3B 00 3C 00 3D 00 3E 00 3F 00
0xC0000880|40 00 41 00 42 00 43 00 44 00 45 00 46 00 47 00
0xC0000890|48 00 49 00 4A 00 4B 00 4C 00 4D 00 4E 00 4F 00
0xC00008A0|50 00 51 00 52 00 53 00 54 00 55 00 56 00 57 00
0xC00008B0|58 00 59 00 5A 00 5B 00 5C 00 5D 00 5E 00 5F 00
0xC00008C0|60 00 61 00 62 00 63 00 64 00 65 00 66 00 67 00
0xC00008D0|68 00 69 00 6A 00 6B 00 6C 00 6D 00 6E 00 6F 00
0xC00008E0|70 00 71 00 72 00 73 00 74 00 75 00 76 00 77 00
0xC00008F0|78 00 79 00 7A 00 7B 00 7C 00 7D 00 7E 00 7F 00
----------------------------------------------------------
 Char Read : Start Addres = 0xC0001000
----------------------------------------------------------
  Address |+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
0xC0001000|00 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00
0xC0001010|04 00 00 00 05 00 00 00 06 00 00 00 07 00 00 00
0xC0001020|08 00 00 00 09 00 00 00 0A 00 00 00 0B 00 00 00
0xC0001030|0C 00 00 00 0D 00 00 00 0E 00 00 00 0F 00 00 00
0xC0001040|10 00 00 00 11 00 00 00 12 00 00 00 13 00 00 00
0xC0001050|14 00 00 00 15 00 00 00 16 00 00 00 17 00 00 00
0xC0001060|18 00 00 00 19 00 00 00 1A 00 00 00 1B 00 00 00
0xC0001070|1C 00 00 00 1D 00 00 00 1E 00 00 00 1F 00 00 00
0xC0001080|20 00 00 00 21 00 00 00 22 00 00 00 23 00 00 00
0xC0001090|24 00 00 00 25 00 00 00 26 00 00 00 27 00 00 00
0xC00010A0|28 00 00 00 29 00 00 00 2A 00 00 00 2B 00 00 00
0xC00010B0|2C 00 00 00 2D 00 00 00 2E 00 00 00 2F 00 00 00
0xC00010C0|30 00 00 00 31 00 00 00 32 00 00 00 33 00 00 00
0xC00010D0|34 00 00 00 35 00 00 00 36 00 00 00 37 00 00 00
0xC00010E0|38 00 00 00 39 00 00 00 3A 00 00 00 3B 00 00 00
0xC00010F0|3C 00 00 00 3D 00 00 00 3E 00 00 00 3F 00 00 00

今後は、演算処理を追加してゆきたいと思います。

13
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
10