技術コラム

Efinix Trion ビット幅の違うDual-Port Memoryの実装方法

作成者:mou-mou

DPRAMのVerilog-HDLでの記述については、Efinity® Synthesis User Guideの「RAM」チャプターに記載されています。しかし、ビット幅の違うDPRAMの例は記載がありません。そこで、Efinix社のホームページ内をさがしていると、VHDL版のソースコードがありました。

Support Center Home -> Knowledgebase ->  Mixed Width RAM With Single Dual Port / Mixed Width RAM With True Dual Port

中を見てみると、VHDLで記載したコードとVerilog-HDLで記載されたwrapperが用意されていました。

とりあえず、プロジェクトを生成して合成してみました。使用されたリソースは以下の通りでした。

LE: LUTs/Adders2
LE: Registers0
Memory Blocks4

ソースコードをみてみると、そこそこのRTLが記述されていてなかなか大変だなと感じましたが、実際に合成されると、当然といえば当然なのですが、Memory Blockが置かれているだけです。

Parameterの初期値がPort A = 1024 x 8bit Port B 256 x 32bit となっていました。8Kbitなので5KのMemory Blockが2個で実現できるように感じますが、そこはEFX_DPRAM_5Kの制約によるところです。具体的には、Quantum Trion® Primitives User Guide の EFX_DPRAM_5Kの仕様をみると、WIDTHは、1,2,4,8,5,10bitからしか選択できません。32bit幅のメモリを構成するためには、必然的にMemory Blockが4個必要となります。mixed_width_ram.map.vをアドレスには先頭に1ビット’0’が付加されております。あと、不思議なことに、top_efx_mixed_width_ram_tdp.vのParameterは、READ_FIRSTになっているのに、合成してmixed_width_ram.map.vを確認するとWRITE_FIRSTとなっております。

これなら、複雑なRTLを書いてEfinityに解析させるまでもなく、EFX_DPRAM_5K primitiveを使って、都度実装したい仕様がParameterとして明示される形で記述したほうが保守性や可読性が高いと考えます。

以下に、サンプル例と同じPort A = 1024 x 8bit Port B 256 x 32bit の DPRAMを記述してみます。

module mixed_width_ram_user (
		input			clk,
		input			en,
		input			we_a,
		input			we_b,
		input	[9:0]	addr_a,
		input	[7:0]	addr_b,
		input	[7:0]	data_in_a,
		input	[31:0]	data_in_b,
		output	[7:0]	data_out_a,
		output	[31:0]	data_out_b
	);

	generate
		genvar i;
		for (i = 0; i < 4; i = i + 1) begin : gen_dpram
			EFX_DPRAM_5K # (
				.READ_WIDTH_A(2),					// 2 2048x2
				.WRITE_WIDTH_A(2),					// 2 2048x2
				.OUTPUT_REG_A(1'b0),				// 1 add pipe-line read register
				.CLKA_POLARITY(1'b1),				// 0 falling edge, 1 rising edge
				.WEA_POLARITY(1'b1),				// 0 active low, 1 active high
				.CLKEA_POLARITY(1'b1),				// 0 falling edge, 1 rising edge
				.WRITE_MODE_A("READ_FIRST"),		// Output "new" data
				.READ_WIDTH_B(8),					// 4 512x4
				.WRITE_WIDTH_B(8),					// 4 512x4
				.OUTPUT_REG_B(1'b0),				// 1 add pipe-line read register
				.CLKB_POLARITY(1'b1),				// 0 falling edge, 1 rising edge
				.WEB_POLARITY(1'b1),				// 0 active low, 1 active high
				.CLKEB_POLARITY(1'b1),				// 0 falling edge, 1 rising edge
				.WRITE_MODE_B("READ_FIRST"),		// Output "old" data
				.INIT_0(256'h0000000000000000000000000000000000000000000000000000000000000000),
				.INIT_1(256'h0000000000000000000000000000000000000000000000000000000000000000),
				.INIT_2(256'h0000000000000000000000000000000000000000000000000000000000000000),
				.INIT_3(256'h0000000000000000000000000000000000000000000000000000000000000000),
				.INIT_4(256'h0000000000000000000000000000000000000000000000000000000000000000),
				.INIT_5(256'h0000000000000000000000000000000000000000000000000000000000000000),
				.INIT_6(256'h0000000000000000000000000000000000000000000000000000000000000000),
				.INIT_7(256'h0000000000000000000000000000000000000000000000000000000000000000),
				.INIT_8(256'h0000000000000000000000000000000000000000000000000000000000000000),
				.INIT_9(256'h0000000000000000000000000000000000000000000000000000000000000000),
				.INIT_A(256'h0000000000000000000000000000000000000000000000000000000000000000),
				.INIT_B(256'h0000000000000000000000000000000000000000000000000000000000000000),
				.INIT_C(256'h0000000000000000000000000000000000000000000000000000000000000000),
				.INIT_D(256'h0000000000000000000000000000000000000000000000000000000000000000),
				.INIT_E(256'h0000000000000000000000000000000000000000000000000000000000000000),
				.INIT_F(256'h0000000000000000000000000000000000000000000000000000000000000000),
				.INIT_10(256'h0000000000000000000000000000000000000000000000000000000000000000),
				.INIT_11(256'h0000000000000000000000000000000000000000000000000000000000000000),
				.INIT_12(256'h0000000000000000000000000000000000000000000000000000000000000000),
				.INIT_13(256'h0000000000000000000000000000000000000000000000000000000000000000)
			) EFX_DPRAM_5K_inst (
				.RDATAA(data_out_a[i*2+1:i*2]),		// Read data output A
				.ADDRA({1'b0, addr_a}),				// Address input A
				.CLKA(clk),							// Clock input A
				.CLKEA(en),		    				// Clock-enable input A
				.WEA(we_a),							// Write-enable input A
				.WDATAA(data_in_a[i*2+1:i*2]),		// Write data input A
				.RDATAB({data_out_b[i*2+25:i*2+24],	// Read data output B
						 data_out_b[i*2+17:i*2+16],
						 data_out_b[i*2+9:i*2+8],
						 data_out_b[i*2+1:i*2]}),
				.ADDRB({1'b0, addr_b}),				// Address input B
				.CLKB(clk),							// Clock input B
				.CLKEB(en),	    					// Clock-enable input B
				.WEB(we_b),							// Write-enable input B
				.WDATAB({data_in_b[i*2+25:i*2+24],	// Write data input B
						 data_in_b[i*2+17:i*2+16],
						 data_in_b[i*2+9:i*2+8],
						 data_in_b[i*2+1:i*2]})
			);
		end
	endgenerate

endmodule

トラックバックURL

URL:https://rightxlight.co.jp/technical/efinix-trion-mixed-width-dual-port-memory/trackback/

よく読まれている記事はこちら

ソフトウェアからハードウェアまで、
まずはお気軽にご相談下さい。

お電話はこちら

お電話はこちら 06-6309-7782

受付時間:9:00~18:00(土日祝は除く)

メールフォームからはこちら

お問い合わせお問い合わせ

Copyright (C) Since 2011 RIGHTxLIGHT Co., Ltd. All Rights Reserved.

PAGE TOP