FPGA評価キット (4)

usbblaster

PICボード(MAX10-JB)は、USB-Blasterダウンロードケーブルのように動作するはずですが、どこかで何かがおかしいようです。

% dmesg
[   99.874756] usb 3-6: new full-speed USB device number 5 using xhci_hcd
[  100.005217] usb 3-6: New USB device found, idVendor=09fb, idProduct=6001
[  100.005224] usb 3-6: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[  100.005229] usb 3-6: Product: USB-Blaster
[  100.005232] usb 3-6: Manufacturer: Altera

% lsusb
Bus 003 Device 005: ID 09fb:6001 Altera Blaster

% sudo ./jtagd --foreground --debug
JTAG daemon started
Using config file /etc/jtagd/jtagd.conf
Remote JTAG permitted when password set
USB-Blaster added "USB-Blaster [3-6]"

USB-Blaster port (/dev/bus/usb/003/005) opened
USB-Blaster port (/dev/bus/usb/003/005) opened

% ls -l /dev/bus/usb/003/005
crw-rw-rw- 1 root root 189, 260 May 18 16:30 /dev/bus/usb/003/005

% cat /etc/udev/rules.d/51-usbblaster.rules 
# Altera USB-Blaster for Quartus FPGA Software 
SUBSYSTEMS=="usb", ATTR{idVendor}=="09fb", ATTR{idProduct}=="6001", MODE="0666" 
SUBSYSTEMS=="usb", ATTR{idVendor}=="09fb", ATTR{idProduct}=="6002", MODE="0666" 
SUBSYSTEMS=="usb", ATTR{idVendor}=="09fb", ATTR{idProduct}=="6003", MODE="0666" 

FPGA評価キット(3)

extpow

直流電源(+5V)を、USBインターフェースから受け取るのは、標準あるいは非標準のプロトコールが含まれていてやや複雑です。 D+とD-の信号線が、情報を伝送するために用いられている場合があります。

dcp

maxim2

https://www.maximintegrated.com/en/app-notes/index.mvp/id/5801

tps2540

http://www.ti.com/lit/ds/symlink/tps2540a.pdf

このことは、PICボード(MAX10-JB)において問題をもたらします。何故ならば、PICマイクロコントローラの幾つかのI/Oピンは、USBインターフェースのD+とD-信号線と、フラッシュプログラムメモリへの書き込みの両方に用いられているからです。

干渉を避けるために、私は、フラッシュメモリをプログラムしている間だけは、USBケーブルを抜いて外部電源を用いました。

FPGA評価ボード(MAX10-FB)の緑に点滅しているLEDは、フラッシュメモリへの書き込みが成功して、ベリフィケーションがOKであったことを示しています。

推奨される慣習 (2)

4-state-moore-vlog

これは、AlteraによるHDLデザインの例です。

https://www.altera.co.jp/support/support-resources/design-examples/design-software/verilog/ver-state-machine.html

// 4-State Moore state machine

// A Moore machine's outputs are dependent only on the current state.
// The output is written only when the state changes.  (State
// transitions are synchronous.)

module moore_mac
(
	input	clk, data_in, reset,
	output reg [1:0] data_out
);
	
	// Declare state register
	reg		[1:0]state;
	
	// Declare states
	parameter S0 = 0, S1 = 1, S2 = 2, S3 = 3;
	
	// Output depends only on the state
	always @ (state) begin
		case (state)
			S0:
				data_out = 2'b01;
			S1:
				data_out = 2'b10;
			S2:
				data_out = 2'b11;
			S3:
				data_out = 2'b00;
			default:
				data_out = 2'b00;
		endcase
	end
	
	// Determine the next state
	always @ (posedge clk or posedge reset) begin
		if (reset)
			state <= S0;
		else
			case (state)
				S0:
					state <= S1;
				S1:
					if (data_in)
						state <= S2;
					else
						state <= S1;
				S2:
					if (data_in)
						state <= S3;
					else
						state <= S1;
				S3:
					if (data_in)
						state <= S2;
					else
						state <= S3;
			endcase
	end
	
endmodule

あなたはこのような例をコピー・ペーストすることもできるし、もし、Quartus Primeを使っているのであれば、テンプレートを挿入することもできます。

template

FPGA評価キット (2)

LED

PICボード(MAX10-JB)が、FPGA評価ボード(MAX10-FB)の上にプラグインされています。明るい白いLEDが点滅しているので、マウント済みのFPGAがあらかじめプログラムされた構成で動作していることが確認できます。

このPICボードは、AlteraのUSB-Blasterダウンロードケーブルのように動作します。

推奨される慣習

registerChains
https://www.altera.com/en_US/pdfs/literature/hb/qts/qts-qps-handbook.pdf

殆ど全ての分野において、推奨される慣習というものがあります。

例えば、The ARRL Operating Manual には、”CQに応答するときは、両方のコールサイン、あなたのとCQをしている局の、を明確に与えなさい。”と書かれています。

なので、私は今、FPGAに関する推奨されるデザイン慣習とコーディングスタイルについて学んでいます。勿論、これらは用いるデバイスと開発環境とによって大いに異なりますが。

FPGA評価キット

max_10m50m_front

色んな種類の評価キットが入手可能です。このAlteraのボードは、HDMI出力も可能で非常に良さそうです。
https://www.altera.com/products/boards_and_kits/dev-kits/altera/kit-max-10m50-evaluation.html

max10

これが私が使おうとしているボードです。AlteraのMAX 10 FPGA (10M08SAE144C8G)は、マウント済みですが、他の部品、256kbit SDRAMや28MHz 水晶発振器等はハンダ付けをしなければいけません。

このボードのより詳細な説明は、ここにあります。
(いいえ、英語で書かれたページは無いようです。)

FPGA CW Keyer (4)

waveform7

スクィーズ動作を実現するには、状態遷移表を用いたほうが簡単かも知れません。

//------- ELK Test Bench ---------
`timescale 1ms/1us

module tb_elk;

    reg RST_N;
    reg CLK;
    reg IN_DOT;
    reg IN_DASH;

ELK ELK_0(.RST_N   (RST_N),
          .CLK     (CLK)  ,
          .IN_DOT  (IN_DOT)  ,
          .IN_DASH (IN_DASH)  ,
          .KEY_OUT (KEY_OUT)   );

initial begin
    CLK <= 1'b1;
    forever begin
        #10;
        CLK <= ~CLK;
    end
end

initial begin
    RST_N <= 1'b0;
     #50;
    RST_N <= 1'b1;
    #1100000;
    $finish;
end

initial begin
    IN_DOT <= 1'b1; #063;
    IN_DOT <= 1'b0; #073;
    IN_DOT <= 1'b1; #323;
    IN_DOT <= 1'b0; #223;
    IN_DOT <= 1'b1; #243;
    IN_DOT <= 1'b0; #023;
    IN_DOT <= 1'b1; #1000000;
end

initial begin
    IN_DASH <= 1'b1; #183;
    IN_DASH <= 1'b0; #123;
    IN_DASH <= 1'b1; #223;
    IN_DASH <= 1'b0; #023;
    IN_DASH <= 1'b1; #260;
    IN_DASH <= 1'b0; #300;
    IN_DASH <= 1'b1; #1000000;
end

endmodule
module ELK(RST_N, CLK, IN_DOT, IN_DASH, KEY_OUT);

    input RST_N;
    input CLK;
    input IN_DOT;
    input IN_DASH;
    output KEY_OUT;

    reg      KEY_OUT;
    reg      m_dot;
    reg      m_dash;
    reg[2:0] r_state;

//--------- dot memory ---------------------
    always @ (negedge IN_DOT or negedge RST_N) begin
        if ( RST_N == 1'b0 ) begin
            m_dot  <= 1'b0;
        end if ( IN_DOT == 1'b0) begin
            m_dot  <= 1'b1;
        end
    end

//--------- dash memory ---------------------
    always @ (negedge IN_DASH or negedge RST_N) begin
        if ( RST_N == 1'b0 ) begin
            m_dash  <= 1'b0;
        end if ( IN_DASH == 1'b0) begin
            m_dash  <= 1'b1;
        end
    end

//--------- state output ---------------------
    always @ (r_state) begin
        case(r_state)
            3'b000: begin KEY_OUT <= 1'b0; end
            3'b001: begin KEY_OUT <= 1'b1; end
            3'b010: begin KEY_OUT <= 1'b1; end
            3'b011: begin KEY_OUT <= 1'b1; end
            3'b100: begin KEY_OUT <= 1'b0; end
            3'b101: begin KEY_OUT <= 1'b1; end
            3'b110: begin KEY_OUT <= 1'b0; end
        default:begin
        end
        endcase
    end

//--------- state transition ---------------------
    always @ (posedge CLK or negedge RST_N) begin
        if ( RST_N == 1'b0 ) begin
            r_state <= 3'b000;
        end else
        case (r_state)
        3'b000:begin // idle
            if(IN_DASH == 1'b0) begin
                r_state <= 3'b001;
            end else if(IN_DOT == 1'b0) begin
                r_state <= 3'b101;
            end
        end
        3'b001:begin // dash running 1
                r_state <= 3'b010;
                m_dash  <= 1'b0;
        end
        3'b010:begin // dash running 2
                r_state <= 3'b011;
        end
        3'b011:begin // dash running 3
                r_state <= 3'b100;
        end
        3'b100:begin // dash running 4
            if(IN_DOT == 1'b0 || m_dot == 1'b1) begin
                r_state <= 3'b101;
                m_dot   <= 1'b0;
            end else if(IN_DASH == 1'b0) begin
                r_state <= 3'b001;
            end else begin
                r_state <= 3'b000;
            end
        end
        3'b101:begin // dot running 1
                r_state <= 3'b110;
                m_dot   <= 1'b0;
        end
        3'b110:begin // dot running 2
            if(IN_DASH == 1'b0 || m_dash == 1'b1) begin
                r_state <= 3'b001;
                m_dash  <= 1'b0;
            end else if(IN_DOT == 1'b0) begin
                r_state <= 3'b101;
            end else begin
                r_state <= 3'b000;
            end
        end
        default:begin
        end
        endcase
    end

endmodule

FPGA CW Keyer (3)

waveform3

次は、ダッシュのみです。

    reg[1:0] r_dash; 
    wire     w_dash; 

//---------- generate dash ---------------------
    always @ ( posedge CLK or negedge RST_N) begin
        if ( RST_N == 1'b0 ) begin 
            r_dash <= 2'h0;
        end     
        else if ( IN_DASH == 1'b0 || r_dash != 2'h0 ) begin 
            if ( r_dash == 2'h3 ) begin 
                r_dash <= 2'h0;
            end     
            else begin
                r_dash <= r_dash + 2'h1; 
            end     
        end     
        else begin
            r_dash <= 2'h0;
        end     
    end

//---------- w_dash ----------------------------

    assign w_dash = ( r_dash == 2'h0 ) ? 1'b0 : 1'b1;