k0b0's record.

Computer Engineering, Arts and Books

Raspberry Pi 4

 Raspberry Pi FoundationがRaspberry Pi 4を発表したみたい。

[主な仕様]
 ・プロセッサ:4コアARM Cortex A72(1.5GHz)(性能が先代の3倍以上)
 ・HDMIポート:type-Aからtype-Dの2ポートになり、60fpsの4K動画に対応。
 ・価格:RAMの容量により異なり、1GBが35ドル、2GBは45ドル、4GBは55ドル。
 ・ケース:通常は5ドル、USB Type-Cの電源は8ドル。

詳細は以下のページにて。
www.raspberrypi.org

宣言されていない信号線を幅1bitの信号線(wire)として暗黙的に解釈することを回避する

 VerilogHDLの言語仕様ではwireとして宣言されていない信号線は暗黙的に1bitのwireとして解釈される。一応、Warningとしてコンパイラが教えてくれるのだが、これが原因で何時間もデバッグする羽目になる事もある。。。

 そこで、"`default_nettype wire”宣言と"`default_nettype wire"宣言を用いて、暗黙的な解釈を回避する。
記述例は以下の通りである。

`default_nettype wire
module module_name();

(...回路記述...)

endmodule
`default_nettype wire

これで、暗黙的な解釈はされず、wireとして宣言されていない信号線はエラーとしてコンパイラが教えてくれる。

Quartus PrimeでMIF(Memory Initialization File)を作成してみる。

MIF(Memory Initialization File)を作成してみる。

 Quartus PrimeのIPcatalogから生成するメモリモジュールに初期値を設定するために、MIFを作成する。

[File] -> [New]よりMemory Initialization Fileを選択する。
f:id:k0b0:20190614162708j:plain

メモリのワード数とワード幅を設定する。
f:id:k0b0:20190614162723j:plain

初期値を10進数で設定する。
初期値の設定が完了したら、[File] -> [Save]で作成したMIFを保存する。
f:id:k0b0:20190614162736j:plain

Verilog/SystemVerilogでincludeするヘッダファイルの競合を回避する。

 複数のモジュール内で同じヘッダファイルをincludeしたSystemVerilog記述をQuartus Primeでコンパイルしたところ、競合が生じてエラーが出た。
 ModelSimでの論理シミュレーション時は大丈夫だったのだが、Quartus Primeのコンパイラは厳しいようである。

 と言うわけで、競合を回避するために以下の記述を各モジュールに追記し、競合を回避した。

`ifndef DEF_HEADDER
    `include "def.h"
    `define DEF_HEADDER
`endif

Quartus Prime のIP Catalogを使ってシングルポートRAM(同期書き込み、非同期読み出し)を生成してみる。@2019/06/14 追記

IP Catalogを使ってシングルポートRAM(同期書き込み、非同期読み出し)を生成してみる。

 FPGA(MAX10)でそこそこの容量のメモリを使いたいのだが、レジスタで構成すると、LEをかなり消費する。というわけで、IP Catalogで用意されている、シングルポートRAM(同期書き込み、同期読み出し)を生成してみる。

メニューバーの[Tools] -> [IP Catalog]を選択する。
[IP Catalog]の[On Chip Memory]から[RAM: 1-PORT]を選択する。
f:id:k0b0:20190605130354j:plain

生成するシングルポートRAMの名前と保存先を入力し、MegaWizardを立ち上げる。
(ここでは、名前を[ram1port_8]とし、生成するコードはVerilogHDLとした。)
注意:MegaWizardの画面表示が小さいと操作の途中でなぜかフリーズする。立ち上げてからまず、スクロールバーが消えるくらい画面を大きくするとフリーズせずスムーズに作業を進めることができる。
f:id:k0b0:20190605130427j:plain

データ幅、メモリ容量、メモリブロックタイプを指定する。
(ここでは、データ幅を8とし、メモリ容量を256、メモリブロックタイプをM9Kとした。)
f:id:k0b0:20190605130449j:plain

「Which ports should be registerd ?」の「'q' output port」のチェックマークを外す。
(チェックマークを外さない場合は同期書き込み・同期読み出しのシングルポートRAMを生成することとなる。)
f:id:k0b0:20190605130502j:plain

「Single Port Write During Read Option」を「New Data」に設定する。
f:id:k0b0:20190605130514j:plain

特に何も指定せず、「Next」を選択する。
f:id:k0b0:20190605131927j:plain

生成したいファイルにチェックマークをつけて「Finish」を選択する。
f:id:k0b0:20190605134118j:plain

「yes」を選択する。
(これで、シングルポートRAMの生成は完了。)
f:id:k0b0:20190605141520j:plain

参考サイト

www.lab3.kuis.kyoto-u.ac.jp

VerilogHDLでクロック分周器を記述してみる

クロック分周器

FPGAボードを使って、7セグメントLEDに結果を表示させたい時がある。
けれど、MHz〜GHzで動作されたんでは確認できない。
という事で、クロック分周器(50MHz -> 1Hz)を2つ記述してみる。
(どちらの記述も分周するのだけれど、出力される波形が微妙に違うので、
適材適所で使い分けますかね。)

クロック分周器(clk_divider.v)

/* clk_divider.v */
`define HLZ_1     // 50MHzを1HZに分周 
//`define HLZ_1M  // 50MHzを1MHzに分周
//`define HLZ_16M // 50MHzを16MHzに分周
//`define HLZ_32M // 50MHzを32MHzに分周

module clk_divider(input   clk, rst,
                   output   en1hz);

reg  [25:0] cnt;

always @( posedge clk or posedge rst) begin
    if (rst)
        cnt <= 26'd0;
    else if ( en1hz_wire )
        cnt <= 26'd0;
    else
        cnt <= cnt + 26'd1;
end

`ifdef HLZ_1
    wire en1hz_wire = (cnt==26'd49_999_999);
`elsif HLZ_1M
    wire en1hz_wire = (cnt==26'd47);
`elsif HLZ_16M
    wire en1hz_wire = (cnt==26'd2);
`elsif HLZ_32M
    wire en1hz_wire = (cnt==26'd1);
`else
    wire en1hz_wire = (cnt==26'd49_999_999);
`endif

assign en1hz = en1hz_wire;

endmodule

clk_divider.vを論理合成した結果(Quartus PrimeのRTL Viewerで確認)

f:id:k0b0:20190525172127p:plain

クロック分周器 その2 (clk_divider_0.v)

こちらの記述がオーソドックスな分周器かな(?)
上記の記述(clk_divider.v)に比べて、カウントする値を少なくできる。

/* clk_divider_0.v */
/* 50MHz -> 1Hz */
module clk_divider_0(input   clk, rst,
                     output reg divid_clk);

reg [25:0] cnt;

wire cntend = (cnt==26'd24_999_999);

always @(posedge clk or posedge rst)
begin
    if(rst)
        cnt <= 26'd0;
    else if(cntend)
        cnt <= 26'd0;
    else
        cnt <= cnt + 26'd1;
end

always @(posedge clk or posedge rst) 
begin
    if(rst)
        divid_clk <= 1'b0;
    else if(cntend)
        divid_clk <= ~(divid_clk);
end

endmodule

clk_divider_0.vを論理合成した結果(Quartus PrimeのRTL Viewerで確認)

f:id:k0b0:20190529133105j:plain

SystemVerilogでチャタリング除去回路を記述してみる。

チャタリング除去回路を記述してみる

FPGAボードを使っているとスイッチをよく使う。
スイッチを押すとノイズ(チャタリング)が起こる。
というわけで、色々と参考にしてチャタリング除去回路を書いたのでメモしておく。

チャタリング除去回路(chatter.sv)

/* chatter.sv */
module chatter (input  logic clk,     // クロック 
                input  logic reset,   // リセット
                input  logic sw,      // スイッチ入力(立ち下がり)
                output logic sw_out); // 出力(1パルス)

/* cntの値はクロック周波数をどのくらい分周するかによって調整する */
logic [20:0] cnt;
wire en_N_hz = (cnt == 1200000);

/* クロックをカウントして分周 */
always_ff @(posedge clk) 
begin
    if (reset)
        cnt <= 21'b0;
    else if ( en_N_hz )
        cnt <= 21'b0;
    else
        cnt <= cnt + 21'b1;
end

/* スイッチ入力をシフトレジスタ(2つのFF)に入力 */
logic ff_0, ff_1;
always_ff @( posedge clk ) 
begin
    if (reset) 
    begin
        ff_1 <= 1'b0;
        ff_0 <= 1'b0;
    end
    else if ( en_N_hz ) begin
        ff_1 <= ff_0;
        ff_0 <= sw;
    end
end

/* シフトレジスタの各出力とクロック(分周)のANDをとりノイズを消去 */
wire tmp = ~(ff_0) & ff_1 & en_N_hz;

always_ff @(posedge clk) 
begin
    if (reset)
        sw_out <= 1'b0;
    else
        sw_out <= tmp;
end

endmodule

chatter.svを論理合成した結果(Quartus PrimeのRTL Viewerで確認)

f:id:k0b0:20190526111309j:plain