2019/09/22

ROMの実装方法

ROMの実装方法を調べていたらいろいろ方法があったので紹介.

intel FPGAが推奨するHDLの構文が『Intel Quartus Prime Pro Edition User Guide: Design Recommendations』[1]に記載されているが, その中のROMの記述が普段使っているものと違ったので比較してみた.

例として以前素数を数えるFPGAを作ったときの素数テーブルを実装する.

toms.log: ハードウェアで素数を数える

VHDL constant宣言

constant宣言を使った実装はconstantな配列を宣言してそれをそのまま使うという方法. 『VHDLデジタル回路設計 標準講座』[2]に載ってた.

-- =====================================================================
-- Title : Prime number ROM
--
-- File Name : PRIME_ROM.vhd
-- Project :
-- Block :
-- Tree :
-- Designer : toms74209200 <https://github.com/toms74209200>
-- Created : 2019/09/22
-- Copyright : 2019 toms74209200
-- License : MIT License.
-- http://opensource.org/licenses/mit-license.php
-- =====================================================================
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity PRIME_ROM is
port(
-- System --
CLK : in std_logic; --(p) Clock
-- ROM interface --
ADDRESS : in std_logic_vector(10 downto 0); --(p) Address
DATA : out std_logic_vector(15 downto 0) --(p) Data
);
end PRIME_ROM;
architecture RTL of PRIME_ROM is
-- Internal signals --
signal data_i : std_logic_vector(DATA'range); -- Data
-- ROM table --
type PrimeDatTyp is array(0 to 1227) of std_logic_vector(15 downto 0);
constant rom_prime : PrimeDatTyp :=
(
X"0003",
X"0005",
X"0007",
~~
X"26EF",
X"26F5"
);
begin
-- ***********************************************************
-- ROM output
-- ***********************************************************
process (CLK) begin
if (CLK'event and CLK = '1') then
data_i <= rom_prime(CONV_INTEGER(ADDRESS));
end if;
end process;
DATA <= data_i;
end RTL; --PRIME_ROM

https://github.com/toms74209200/PRIME_ROM/tree/master/vhdl_constant/PRIME_ROM.vhd

VHDL case文

『Intel~』[1]で推奨される記述. 配列を使わずにcase文で値をスイッチしている感じ. 動作と定数テーブルがくっついているのでめっちゃ記述しにくい.

-- =====================================================================
-- Title : Prime number ROM
--
-- File Name : PRIME_ROM.vhd
-- Project :
-- Block :
-- Tree :
-- Designer : toms74209200 <https://github.com/toms74209200>
-- Created : 2019/09/22
-- Copyright : 2019 toms74209200
-- License : MIT License.
-- http://opensource.org/licenses/mit-license.php
-- =====================================================================
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity PRIME_ROM is
port(
-- System --
CLK : in std_logic; --(p) Clock
-- ROM interface --
ADDRESS : in std_logic_vector(10 downto 0); --(p) Address
DATA : out std_logic_vector(15 downto 0) --(p) Data
);
end PRIME_ROM;
architecture RTL of PRIME_ROM is
-- Internal signals --
signal data_i : std_logic_vector(DATA'range); -- Data
begin
-- ***********************************************************
-- ROM output
-- ***********************************************************
process (CLK) begin
if (CLK'event and CLK = '1') then
case (CONV_INTEGER(ADDRESS)) is
when 0 => data_i <= X"0003";
when 1 => data_i <= X"0005";
when 2 => data_i <= X"0007";
~~
when 1226 => data_i <= X"26EF";
when 1227 => data_i <= X"26F5";
when others => data_i <= data_i;
end case;
end if;
end process;
DATA <= data_i;
end RTL; --PRIME_ROM

https://github.com/toms74209200/PRIME_ROM/blob/master/vhdl_case/PRIME_ROM.vhd

Verilog case文

Verilog-HDLの場合もVHDLと同じくcase文で書くことが推奨されるらしい.

/* ============================================================================
* Title : Prime number ROM
*
* File Name : PRIME_ROM.v
* Project :
* Block :
* Tree :
* Designer : toms74209200 <https://github.com/toms74209200>
* Created : 2019/09/22
* Copyright : 2019 toms74209200
* License : MIT License.
* http://opensource.org/licenses/mit-license.php
* ============================================================================*/
module PRIME_ROM
(
// System
CLK, //(p) Clock
// ROM interface
ADDRESS, //(p) Address
DATA //(p) Data
);
// Port
// System
input CLK; //(p) Clock
// ROM interface
input [10:0] ADDRESS; //(p) Address
output [15:0] DATA; //(p) Data
// Internal signals
reg [15:0] data_i; // Data
/* ============================================================================
* ROM output
* ============================================================================*/
always@(posedge CLK) begin
case (ADDRESS)
0 : data_i <= 16'h0003;
1 : data_i <= 16'h0005;
2 : data_i <= 16'h0007;
~~
1226 : data_i <= 16'h26EF;
1227 : data_i <= 16'h26F5;
endcase
end
assign DATA = data_i;
endmodule //PRIME_ROM

https://github.com/toms74209200/PRIME_ROM/blob/master/verilog_case/PRIME_ROM.v

Verilog initial文

Verilog-HDL特有のinitial文を使った記述方法. VHDLのconstantによる実装に近い.

/* ============================================================================
* Title : Prime number ROM
*
* File Name : PRIME_ROM.v
* Project :
* Block :
* Tree :
* Designer : toms74209200 <https://github.com/toms74209200>
* Created : 2019/09/22
* Copyright : 2019 toms74209200
* License : MIT License.
* http://opensource.org/licenses/mit-license.php
* ============================================================================*/
module PRIME_ROM
(
// System
CLK, //(p) Clock
// ROM interface
ADDRESS, //(p) Address
DATA //(p) Data
);
// Port
// System
input CLK; //(p) Clock
// ROM interface
input [10:0] ADDRESS; //(p) Address
output [15:0] DATA; //(p) Data
// Internal signals
reg [15:0] rom_prime[0:1227]; // ROM table
reg [15:0] data_i; // Data
/* ============================================================================
* ROM table
* ============================================================================*/
initial begin
rom_prime[0] = 16'h0003;
rom_prime[1] = 16'h0005;
rom_prime[2] = 16'h0007;
~~
rom_prime[1226] = 16'h26EF;
rom_prime[1227] = 16'h26F5;
end
/* ============================================================================
* ROM output
* ============================================================================*/
always @(posedge CLK) begin
data_i <= rom_prime[ADDRESS];
end
assign DATA = data_i;
endmodule //PRIME_ROM

https://github.com/toms74209200/PRIME_ROM/blob/master/verilog_initial/PRIME_ROM.v

結果

以下に結果を載せる. ターゲットデバイスはCyclone V(5CSEBA6U19C6). コンパイラはQuartus Prime 17.1.0だ.

方式 Logic utilization Total registers Total block memory bits Total RAM Blocks
VHDL constant 224 13 0 0
VHDL case 1,112 13 0 0
Verilog case 1,112 13 0 0
Verilog initial 1 0 19,648 4

驚くべきことにVHDL constantが最も実装量が小さくなった. Verilog-HDLでは実装できない方法なので『Intel~』[1]では載っていないということなんだろうか. 問題がVerilog initial文の方式で, メモリとして実装されてしまい大量のRAMを消費している. Verilog-HDLで記述するときにVHDL constantのような簡単な書き方はできないんだろうか.

参考

[1] Intel Quartus Prime Pro Edition User Guide: Design Recommendations
[2] VHDLデジタル回路設計 標準講座, Mark Zwolinski, 翔泳社 2007

0 件のコメント:

コメントを投稿