ROMの実装方法を調べていたらいろいろ方法があったので紹介.
intel FPGAが推奨するHDLの構文が『Intel Quartus Prime Pro Edition User Guide: Design Recommendations』[1]に記載されているが, その中のROMの記述が普段使っているものと違ったので比較してみた.
例として以前素数を数えるFPGAを作ったときの素数テーブルを実装する.
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 件のコメント:
コメントを投稿