FPGA SDR(13)自作NCO


2018/07/22 追記:メモリ節約のため、2ポートROMを使ってCOSテーブルを省略しました。
2018/07/21 追記:出力ビット数を指定できるパラメータを追加。

 

IP CatalogにあるNCOは評価版なのでダウンロードケーブルを接続した状態でのみ使うことができます。CICフィルタに続いてNCOを自作してみました。入出力はIP CatalogにあるNCOに合わせています。

CICフィルタと同様に、MegaWizardのNCOの生成が途中で止まってしまうEP2C5T144でもこの自作NCOなら使用できます。

`timescale 1ns/1ns


module MyNCO
 #(
	parameter OUT_WIDTH = 10
 )
(
	input  wire clk,
	input  wire clken,
	input  wire [31:0] phi_inc_i,
	output wire [OUT_WIDTH-1:0] fsin_o,
	output wire [OUT_WIDTH-1:0] fcos_o,
	output wire out_valid,
	input  wire reset_n
);


	wire [17:0] cos;
	wire [17:0] sin;
	reg [31:0] addr;
	wire [31:0] cos_addr;


	assign out_valid = 1'b1;

	always @(posedge clk)
	begin
		if (~reset_n)
		begin
			addr <= 0;
		end else if (clken) begin
			addr <= addr + phi_inc_i;
		end
	end
	assign cos_addr = addr + 32'h40000000;
		
	rom2sin	rom2sin_inst (
		.address_a ( addr[31 -: 12] ),
		.address_b ( cos_addr[31 -: 12] ),
		.clock ( clk ),
		.q_a ( sin ),
		.q_b ( cos )
	);

	assign fcos_o = cos[17 -: OUT_WIDTH];
	assign fsin_o = sin[17 -: OUT_WIDTH];


endmodule

SINテーブルはIP Catalogの「ROM: 2-PORT」を18ビット X 4096ワードのサイズで作ります。COSテーブルはSINテーブルを90°分進んだアドレスで読み出すことで省略します。ROMの中身はMIFファイルを用意します。4096ワードでSIN1周期のデータを、-131071(0x20001)から131071(0x1ffff)の範囲で作ります。

SINテーブル

WIDTH=18;
DEPTH=4096;

ADDRESS_RADIX=HEX;
DATA_RADIX=HEX;

CONTENT BEGIN
	0000 : 00000;
	0001 : 000c9;
	0002 : 00192;
	...
	03ff : 1fffe;
	0400 : 1ffff;
	0401 : 1fffe;
	...
	07ff : 000c9;
	0800 : 00000;
	0801 : 3ff37;
	...
	0bff : 20002;
	0c00 : 20001;
	0c01 : 20002;
	...
	0ffd : 3fda5;
	0ffe : 3fe6e;
	0fff : 3ff37;
END;