SPI Bridge Scope(2)Qsysコンポーネント作成


FPGA内のデータを記録するQsysコンポーネントを作ります。Qsys(Platform Designer)を起動して、IP CatalogのNew Componentをダブルクリックするか、[New…]ボタンをクリックしてComponent Editorを起動します。

コンポーネントに名前を付けます。

メニューからテンプレートを選択します。

信号線avs_s0_waitrequestは使わないので右クリックのメニューで削除します。

Verilogファイルを出力します。

ダイアログでファイル名を変更できないのでnew_component.vのまま保存して、エクスプローラ等で変更します。今回はMyMonitor.vに変更しました。

Qsys(Platform Designer)を開いたまま、Quartusに戻ってMyMonitor.vをプロジェクトに追加します。これは編集するMyMonitor.vをAnalysis & Synthesisでチェックするためで、コンポーネントが完成したあとプロジェクトから削除します。

16bits x 512wordsのデータを2チャンネル分記録したいので、32bits x 512wordsのRAM 2-PORTを作ります。ファイル名はram2_32x512.vにしました。

 

MyMonitor.vを編集します。次のようなメモリマップにするのでAvalonバスのアドレスavs_s0_addressは10ビットに変更します。

word 0-511: bit 31-16: CH2 memory, bit 15-0: CH1 memory
word 512: bit 0: Write enable
word 513: bit 3-0: Clock division ratio
`timescale 1 ps / 1 ps
 
 
module MyMonitor (
		input  wire [9:0]  avs_s0_address,   // avs_s0.address
		input  wire        avs_s0_read,      //       .read
		output wire [31:0] avs_s0_readdata,  //       .readdata
		input  wire        avs_s0_write,     //       .write
		input  wire [31:0] avs_s0_writedata, //       .writedata
		input  wire        clock_clk,        //  clock.clk
		input  wire        reset_reset,      //  reset.reset

		input  wire [31:0] coe_monitor       //  monitor
	);

	reg wren;
	reg [3:0] div;
	
	reg [15:0] div_cnt;
	reg [8:0] addr;
	reg [31:0] coe_monitor_d;
	
	wire [31:0] q;
	
	always @(posedge clock_clk)
	begin
		if (reset_reset) begin
			wren <= 1;
			div <= 0;
		end
		else if (avs_s0_write && avs_s0_address == 10'h200)
			wren <= avs_s0_writedata[0];
		else if (avs_s0_write && avs_s0_address == 10'h201)
			div <= avs_s0_writedata[3:0];
	end
	

	always @(posedge clock_clk)
	begin
		if (reset_reset) begin
			div_cnt <= 0;
			addr <= 0;
			coe_monitor_d <= 0;
		end
		else if (wren) begin
			div_cnt <= div_cnt + 1;		
			if ((div_cnt & ((1 << div) - 1)) == 0) begin
				addr <= addr + 1;
				coe_monitor_d <= coe_monitor;
			end
		end
	end
		
	ram2_32x512 ram2_32x512_inst (
		.clock(clock_clk),
		.wraddress(addr),
		.data(coe_monitor_d),
		.wren(wren),
		.rdaddress((addr + 1) + avs_s0_address),
		.q(q)
	);
	
	assign avs_s0_readdata = (avs_s0_address == 10'h200) ? wren :
									 (avs_s0_address == 10'h201) ? div :
									 (avs_s0_address == 10'h1ff) ? coe_monitor_d : q;

endmodule

Analysis & Synthesisでチェックしてエラーがなくなったなら、Qsys(Platform Designer)のComponent Editorに戻ります。new_component.vを削除、代わりにMyMonitor.vを追加してAnalyze Synthesis Filesをクリックします。信号名にavs_、coe_、clock_、reset_を付けているので信号の種類が自動で判別されます。エラーがなければBlock Symbol画面を確認してComponent Editorを終了します。

avs_s0_addressが10ビットに変更され、16bits2チャンネルのデータを入力するコンジット型が追加されています。

Qsys(Platform Designer)に完成したMyMonitorコンポーネントを追加します。

接続します。

アドレスがぶつからないようにMyMonitorの開始アドレスを0x10000に変更します。

エラーがなければ[Generate HDL…]をクリックします。テンプレートを参考にしてトップモジュールを編集します。

16bits x 512wordsの2チャンネルの配線をmonitor1、monitor2という名前にしています。A/Dコンバータの出力をminitor1に接続しています。

`define CYCLE_1SEC 50000000


module SPIbridge
(
	input wire RST_N,
	input wire CLK,
	
	input wire SPI_NSS,
	input wire SPI_SCLK,
	output wire SPI_MISO,
	input wire SPI_MOSI,
	
	output wire [3:0] LED,
	
	input wire [7:0] ADC,
	output wire ENCODE,

	output wire I2S_SCK,
	output wire I2S_BCK,
	output wire I2S_LRCK,
	output wire I2S_DATA,
	
	output reg [7:0] DACA,
	output reg [7:0] DACB
);
...
	wire clk; // 73.75M

	wire [31:0] pio0;
	wire [31:0] pio1;

	wire [15:0] monitor1;
	wire [15:0] monitor2;
...	
	reg [9:0] uadc_r;
	wire signed [9:0] adc;
...		
	pll	pll_inst (
		.inclk0 (CLK),
		.c0 (clk)
	);	

	QsysCore QsysCore_inst (
		.clk_clk (clk),
		.reset_reset_n (RST_N),
		.spi_slave_to_avalon_mm_master_bridge_0_export_0_mosi_to_the_spislave_inst_for_spichain (SPI_MOSI),
		.spi_slave_to_avalon_mm_master_bridge_0_export_0_nss_to_the_spislave_inst_for_spichain (SPI_NSS),
		.spi_slave_to_avalon_mm_master_bridge_0_export_0_miso_to_and_from_the_spislave_inst_for_spichain (SPI_MISO),
		.spi_slave_to_avalon_mm_master_bridge_0_export_0_sclk_to_the_spislave_inst_for_spichain (SPI_SCLK),
		.pio_0_external_connection_export (pio0),
		.pio_1_external_connection_export (pio1),
		.mymonitor_0_conduit_end_0_export ({ monitor2, monitor1 })
	);

	assign LED = ~pio0[3:0];
...
	always @(posedge clk) begin
		uadc_r <= { ADC, 2'b00 };
	end
	assign ENCODE = clk;
	assign adc = (uadc_r[9] == 0) ? uadc_r + 10'h200 : uadc_r - 10'h200;
...
	assign monitor1 = { adc, 6'h00 };
	assign monitor2 = 16'h0000;
...
endmodule

EP4CE6E22 AM/FMステレオラジオにMyMonitorコンポーネントを追加して、A/Dコンバータの出力をWindows版アプリで表示してみました。FMの放送局が6つ判別できます。クロックが73.75MHzなので82.5MHzの東京FMが8.75MHzに現れています。