FPGA開発日記

FPGAというより、コンピュータアーキテクチャかもね! カテゴリ別記事インデックス https://sites.google.com/site/fpgadevelopindex/

ISSからハードウェアデコーダを自動生成してみる(3)

続き。とりあえずデコードテーブルを作ってみたところから。

## start of RISC-V instructions
#                       ['BITFIELD'                                        31-26,    25-21,   20-16    15-11    10-06     05-00                                                                    ]
#                       ['DECODE-KEY',                                     'OPCODE', 'RS'     'RT',    'RD',    'SHAMT',  'FUNCT'   'TYPE'    'KEY_TABLE'                                          ]
$arch_table[  0] = Array['add     d[15:11],d[25:21],d[20:16]',             '000000', 'XXXXX', 'XXXXX', 'XXXXX', '00000',  '100000', 'ALU',    Array[            'DST_RD', 'R1_RS', 'R2_RT',                    'ALU_SIGN_ADD'  ], Array['OPCODE', 'FUNCT', 'SHAMT'], ]
$arch_table[  1] = Array['addi    d[20:16],d[25:21],h[15:0]',              '001000', 'XXXXX', 'XXXXX', 'XXXXX', 'XXXXX',  'XXXXXX', 'ALU',    Array[            'DST_RT', 'R1_RS',            'IMM',           'ALU_SIGN_ADD'  ], Array['OPCODE']]
$arch_table[  2] = Array['addiu   d[20:16],d[25:21],h[15:0]',              '001001', 'XXXXX', 'XXXXX', 'XXXXX', 'XXXXX',  'XXXXXX', 'ALU',    Array[            'DST_RT', 'R1_RS',            'IMM',           'ALU_USIGN_ADD' ], Array['OPCODE']]
$arch_table[  3] = Array['addu    d[15:11],d[25:21],d[20:16]',             '000000', 'XXXXX', 'XXXXX', 'XXXXX', '00000',  '100001', 'ALU',    Array[            'DST_RD', 'R1_RS', 'R2_RT',                    'ALU_USIGN_ADD' ], Array['OPCODE', 'FUNCT', 'SHAMT']]
$arch_table[  4] = Array['clo     d[15:11],d[25:21]',                      '011100', 'XXXXX', 'XXXXX', 'XXXXX', '00000',  '100001', 'ALU',    Array[            'DST_RD', 'R1_RS',                             'ALU_COUNT_ONE' ], Array['OPCODE', 'FUNCT', 'SHAMT']]
$arch_table[  5] = Array['clz     d[15:11],d[25:21]',                      '011100', 'XXXXX', 'XXXXX', 'XXXXX', '00000',  '100000', 'ALU',    Array[            'DST_RD', 'R1_RS',                             'ALU_COUNT_ZERO'], Array['OPCODE', 'FUNCT', 'SHAMT']]
$arch_table[  6] = Array['div     d[25:21],d[20:16]',                      '000000', 'XXXXX', 'XXXXX', '00000', '00000',  '011010', 'ALU',    Array['SEPARATE', 'DST_M',  'R1_RS', 'R2_RT',                    'ALU_SIGN_DIV'  ], Array['OPCODE', 'FUNCT', 'RD', 'SHAMT']]
$arch_table[  7] = Array['divu    d[25:21],d[20:16]',                      '000000', 'XXXXX', 'XXXXX', '00000', '00000',  '011011', 'ALU',    Array['SEPARATE', 'DST_M',  'R1_RS', 'R2_RT',                    'ALU_USIGN_DIV' ], Array['OPCODE', 'FUNCT', 'RD', 'SHAMT']]
$arch_table[  8] = Array['madd    d[25:21],d[20:16]',                      '011100', 'XXXXX', 'XXXXX', '00000', '00000',  '000000', 'ALU',    Array['SEPARATE', 'DST_M',  'R1_RS', 'R2_RT',                    'ALU_SIGN_MADD' ], Array['OPCODE', 'FUNCT', 'RD', 'SHAMT']]
$arch_table[  9] = Array['maddu   d[25:21],d[20:16]',                      '011100', 'XXXXX', 'XXXXX', '00000', '00000',  '000001', 'ALU',    Array['SEPARATE', 'DST_M',  'R1_RS', 'R2_RT',                    'ALU_USIGN_MADD'], Array['OPCODE', 'FUNCT', 'RD', 'SHAMT']]
$arch_table[ 10] = Array['msub    d[25:21],d[20:16]',                      '011100', 'XXXXX', 'XXXXX', '00000', '00000',  '000100', 'ALU',    Array['SEPARATE', 'DST_M',  'R1_RS', 'R2_RT',                    'ALU_SIGN_MSUB' ], Array['OPCODE', 'FUNCT', 'RD', 'SHAMT']]
$arch_table[ 11] = Array['msubu   d[25:21],d[20:16]',                      '011100', 'XXXXX', 'XXXXX', '00000', '00000',  '000101', 'ALU',    Array['SEPARATE', 'DST_M',  'R1_RS', 'R2_RT',                    'ALU_USIGN_MSUB'], Array['OPCODE', 'FUNCT', 'RD', 'SHAMT']]
$arch_table[ 12] = Array['mul     d[25:21],d[20:16]',                      '011100', 'XXXXX', 'XXXXX', 'XXXXX', '00000',  '000010', 'ALU',    Array[            'DST_RD', 'R1_RS', 'R2_RT',                    'ALU_SIGN_MULT' ], Array['OPCODE', 'FUNCT', 'SHAMT']]
$arch_table[ 13] = Array['mult    d[25:21],d[20:16]',                      '000000', 'XXXXX', 'XXXXX', '00000', '00000',  '011000', 'ALU',    Array['SEPARATE', 'DST_M',  'R1_RS', 'R2_RT',                    'ALU_SIGN_MULT' ], Array['OPCODE', 'FUNCT', 'RD', 'SHAMT']]
$arch_table[ 14] = Array['multu   d[25:21],d[20:16]',                      '000000', 'XXXXX', 'XXXXX', '00000', '00000',  '011001', 'ALU',    Array['SEPARATE', 'DST_M',  'R1_RS', 'R2_RT',                    'ALU_USIGN_MULT'], Array['OPCODE', 'FUNCT', 'RD', 'SHAMT']]
$arch_table[ 15] = Array['seb     d[15:11],d[20:16]',                      '011111', '00000', 'XXXXX', 'XXXXX', '10000',  '100000', 'ALU',    Array[            'DST_RD', 'R1_RS', 'R2_RT',                    'ALU_SIGN_EXT_B'], Array['OPCODE', 'FUNCT', 'RS', 'SHAMT']]
$arch_table[ 16] = Array['seh     d[15:11],d[20:16]',                      '011111', '00000', 'XXXXX', 'XXXXX', '11000',  '100000', 'ALU',    Array[            'DST_RD', 'R1_RS', 'R2_RT',                    'ALU_SIGN_EXT_H'], Array['OPCODE', 'FUNCT', 'RS', 'SHAMT']]
$arch_table[ 17] = Array['slt     d[15:11],d[25:21],d[20:16]',             '000000', 'XXXXX', 'XXXXX', 'XXXXX', '00000',  '101010', 'ALU',    Array[            'DST_RD', 'R1_RS', 'R2_RT',                    'ALU_SIGN_SLT'  ], Array['OPCODE', 'FUNCT', 'SHAMT']]
$arch_table[ 18] = Array['slti    d[20:16],d[25:21],h[15:0]',              '001010', 'XXXXX', 'XXXXX', 'XXXXX', 'XXXXX',  'XXXXXX', 'ALU',    Array[            'DST_RT', 'R1_RS',            'IMM',           'ALU_SIGN_SLT'  ], Array['OPCODE']]
$arch_table[ 19] = Array['sltiu   d[20:16],d[25:21],h[15:0]',              '001011', 'XXXXX', 'XXXXX', 'XXXXX', 'XXXXX',  'XXXXXX', 'ALU',    Array[            'DST_RT', 'R1_RS',            'IMM',           'ALU_USIGN_SLT' ], Array['OPCODE']]
$arch_table[ 20] = Array['sltu    d[15:11],d[25:21],d[20:16]',             '000000', 'XXXXX', 'XXXXX', 'XXXXX', '00000',  '101011', 'ALU',    Array[            'DST_RD', 'R1_RS', 'R2_RT',                    'ALU_USIGN_SLT' ], Array['OPCODE', 'FUNCT', 'SHAMT']]
$arch_table[ 21] = Array['sub     d[15:11],d[25:21],d[20:16]',             '000000', 'XXXXX', 'XXXXX', 'XXXXX', '00000',  '100010', 'ALU',    Array[            'DST_RD', 'R1_RS', 'R2_RT',                    'ALU_SIGN_SUB'  ], Array['OPCODE', 'FUNCT', 'SHAMT']]
$arch_table[ 22] = Array['subu    d[15:11],d[25:21],d[20:16]',             '000000', 'XXXXX', 'XXXXX', 'XXXXX', '00000',  '100011', 'ALU',    Array[            'DST_RD', 'R1_RS', 'R2_RT',                    'ALU_USIGN_SUB' ], Array['OPCODE', 'FUNCT', 'SHAMT']]

ここで、

'ALU'

とか書いてあるのが命令の種類に相当する。ここでは、'ALU', 'BRANCH', 'LOAD', 'STORE' の4つが存在する。 まずは、これらを区分するための制御信号を生成する。

inst_define_fp.printf("\n// declaration of instruction type\n")

inst_dec_type.each_with_index {|type, index|
  inst_define_fp.printf("`define INST_TYPE_%s\t\t%d'b", type, inst_dec_type.size)
  bit_i = 0
  while bit_i < inst_dec_type.size do
    if bit_i == index then
      inst_define_fp.printf("1")
    else
      inst_define_fp.printf("0")
    end
    bit_i = bit_i + 1
  end
  inst_define_fp.puts("\n")
}

これにより、以下のような信号定義が自動的に生成される。

// declaration of instruction type
`define INST_TYPE_ALU       4'b1000
`define INST_TYPE_BRANCH        4'b0100
`define INST_TYPE_LOAD      4'b0010
`define INST_TYPE_STORE     4'b0001

続いて、制御信号の生成だ。