FFT8.0

ISE 

例化:

FFT_ip your_instance_name (
  .aclk(aclk), // input aclk
  .s_axis_config_tdata(s_axis_config_tdata), // input [7 : 0] s_axis_config_tdata
  .s_axis_config_tvalid(s_axis_config_tvalid), // input s_axis_config_tvalid
  .s_axis_config_tready(s_axis_config_tready), // output s_axis_config_tready
  .s_axis_data_tdata(s_axis_data_tdata), // input [31 : 0] s_axis_data_tdata
  .s_axis_data_tvalid(s_axis_data_tvalid), // input s_axis_data_tvalid
  .s_axis_data_tready(s_axis_data_tready), // output s_axis_data_tready
  .s_axis_data_tlast(s_axis_data_tlast), // input s_axis_data_tlast
  .m_axis_data_tdata(m_axis_data_tdata), // output [31 : 0] m_axis_data_tdata
  .m_axis_data_tuser(m_axis_data_tuser), // output [7 : 0] m_axis_data_tuser
  .m_axis_data_tvalid(m_axis_data_tvalid), // output m_axis_data_tvalid
  .m_axis_data_tready(m_axis_data_tready), // input m_axis_data_tready
  .m_axis_data_tlast(m_axis_data_tlast), // output m_axis_data_tlast
  .m_axis_status_tdata(m_axis_status_tdata), // output [7 : 0] m_axis_status_tdata
  .m_axis_status_tvalid(m_axis_status_tvalid), // output m_axis_status_tvalid
  .m_axis_status_tready(m_axis_status_tready), // input m_axis_status_tready
  .event_frame_started(event_frame_started), // output event_frame_started
  .event_tlast_unexpected(event_tlast_unexpected), // output event_tlast_unexpected
  .event_tlast_missing(event_tlast_missing), // output event_tlast_missing
  .event_status_channel_halt(event_status_channel_halt), // output event_status_channel_halt
  .event_data_in_channel_halt(event_data_in_channel_halt), // output event_data_in_channel_halt
  .event_data_out_channel_halt(event_data_out_channel_halt) // output event_data_out_channel_halt
);


端口说明:
input aclk,输入数据的采样频率;
input [7 : 0] s_axis_config_tdata ,一般写8'd1,最低位1表示fft,0表示ifft;如果scaling设置自动,该端口8位宽,若scaling设置不是自动,会是16位宽;
input s_axis_config_tvalid,当configure数据有效时,置1后模块会采集configure数据;如果在采样时刻该位为0,那么模块会跳过该次采样,只有当采样时刻该位为1是,模块才会采数;
output s_axis_config_tready,模块准备好接受configure数据的标志;
input [31 : 0] s_axis_data_tdata,输入数据,高16位位虚部,低16位为实部;
input s_axis_data_tvalid,当输入数据有效时,置1后模块会采集数据;
output s_axis_data_tready,模块准备好接受数据的标志;
input s_axis_data_tlast,输入数据流是该次转换的最后一个数据时,置1,告诉模块一帧数据结束;
output [31 : 0] m_axis_data_tdata,输出数据,高16位位虚部,低16位为实部;
output [7 : 0] m_axis_data_tuser,设置为自动scaling时,该端口表示该次转换的截位(压缩倍数);如果scaling不是自动,那么不会有该信号;该信号在一帧数据的整个时间段内都有效;
output m_axis_data_tvalid,输出数据有效标志(指示);
input m_axis_data_tready,告诉模块准备好接受数据了,模块可以输出转换结果了,该信号由从机(下一个模块)产生,一般应该一直保持高电平,即从机不应该影响主机的性能,如果该信号为0了,可能会导致模块吐不出数,最终导致模块不吃数(只是一种可能,没试过,突然产生的想法)
output m_axis_data_tlast,输出一帧数据的最后一位指示;
output [7 : 0] m_axis_status_tdata,和m_axis_data_tuser内容一样,只不过只在一帧数据的开始位置保持一个时钟;
output m_axis_status_tvalid,status数据有效标志;
input m_axis_status_tready,类似于m_axis_data_tready的作用;
output event_frame_started,输入数据的一帧数据的开始标志,模块告诉数据输入端一帧数据开始采集;
output event_tlast_unexpected,
output event_tlast_missing,若果输入数据流的last信号不对(最常见的就是错位),这两个信号会给出警告指示;
output event_status_channel_halt
output event_data_in_channel_halt
output event_data_out_channel_halt,这三个信号都为0,说明一般不会出错
代码:

(1)TOP 模块

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date:    10:30:06 08/07/2018 
// Design Name: 
// Module Name:    FFT_top 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//
module FFT_top #(
	parameter integer width_data_y_in = 16,
	parameter integer width_addr_y_in = 9 
	)(
	clk,
	rst_n,
	en_bram_y_in,
	wea_bram_y_in,
	data_y_in,
	data_imag,
	data_real
	
    );
input clk;
input rst_n;
input en_bram_y_in;
input [width_data_y_in/8:1]wea_bram_y_in;

output [width_data_y_in:1]data_y_in;
output [width_data_y_in:1]data_imag,data_real;

//FFT端口:
wire s_axis_config_tready;
wire [8:1]s_axis_config_tdata;

wire s_axis_data_tvalid,s_axis_data_tready,s_axis_data_tlast;
wire [width_data_y_in*2:1] s_axis_data_tdata;

wire [width_data_y_in*2:1] m_axis_data_tdata;
wire [7 : 0]	m_axis_data_tuser;
wire 				m_axis_data_tvalid;
wire 				m_axis_data_tlast;
wire [7 : 0] 	m_axis_status_tdata;
wire  			m_axis_status_tvalid;

wire event_frame_started;
wire event_tlast_unexpected;
wire event_tlast_missing;
wire event_status_channel_halt;
wire event_data_in_channel_halt;
wire event_data_out_channel_halt;

//PLL端口:
wire CLK_OUT_250M,LOCKED;

//所有的模块都准备好了
wire ready_top;
assign ready_top = (rst_n) & (LOCKED) ;

//原始数据:
wire [width_addr_y_in:1] addr_bram_y_in;
Bram_ctrl #(
		.width_addr(width_addr_y_in)
	)U_Bram_ctrl_bram1(
		.clk		(CLK_OUT_250M),
		.rst_n	(ready_top),
		.ena		(en_bram_y_in & s_axis_data_tready),
		.addr		(addr_bram_y_in)
    );
Bram_y_in U_Bram_y_in (
  .clka(CLK_OUT_250M), // input clka
  .ena(en_bram_y_in), // input ena
  .wea(wea_bram_y_in), // input [1 : 0] wea
  .addra(addr_bram_y_in), // input [6 : 0] addra
  .dina(16'd0), // input [15 : 0] dina
  .douta(data_y_in) // output [15 : 0] douta
);

//FFT:
reg [7:0] reg_s_axis_config_tdata;
reg reg_s_axis_config_tvalid;
always@(posedge CLK_OUT_250M or negedge rst_n)
	begin
		if(~rst_n)
			begin
				reg_s_axis_config_tdata <= 0;
				reg_s_axis_config_tvalid <= 0;
			end
		else
			begin
				reg_s_axis_config_tdata <= 8'd1;
				reg_s_axis_config_tvalid <= 1;
			end
	end

assign s_axis_config_tdata = reg_s_axis_config_tdata;
assign s_axis_config_tvalid = reg_s_axis_config_tvalid;

assign s_axis_data_tvalid = ready_top & en_bram_y_in;
assign s_axis_data_tdata[width_data_y_in*2:width_data_y_in+1] = 16'd0;
assign s_axis_data_tdata[width_data_y_in:1] = data_y_in;
assign s_axis_data_tlast = (addr_bram_y_in == 8'd255) ? 1'b1:1'b0;//255是单次FFT的点数;

assign 	data_imag = m_axis_data_tdata[32:17];
assign	data_real = m_axis_data_tdata[16:1];

FFT_ip U_FFT_ip (
  .aclk(CLK_OUT_250M), // input aclk
  .s_axis_config_tdata(s_axis_config_tdata), // input [7 : 0] s_axis_config_tdata
  .s_axis_config_tvalid(s_axis_config_tvalid), // input s_axis_config_tvalid
  .s_axis_config_tready(s_axis_config_tready), // output s_axis_config_tready

  .s_axis_data_tdata(s_axis_data_tdata), // input [31 : 0] s_axis_data_tdata
  .s_axis_data_tvalid(s_axis_data_tvalid), // input s_axis_data_tvalid
  .s_axis_data_tready(s_axis_data_tready), // output s_axis_data_tready
  .s_axis_data_tlast(s_axis_data_tlast), // input s_axis_data_tlast

  .m_axis_data_tdata(m_axis_data_tdata), // output [31 : 0] m_axis_data_tdata
  .m_axis_data_tuser(m_axis_data_tuser), // output [7 : 0] m_axis_data_tuser
  .m_axis_data_tvalid(m_axis_data_tvalid), // output m_axis_data_tvalid
  .m_axis_data_tready(1'b1), // input m_axis_data_tready
  .m_axis_data_tlast(m_axis_data_tlast), // output m_axis_data_tlast
  .m_axis_status_tdata(m_axis_status_tdata), // output [7 : 0] m_axis_status_tdata
  .m_axis_status_tvalid(m_axis_status_tvalid), // output m_axis_status_tvalid
  .m_axis_status_tready(1'b1), // input m_axis_status_tready

  .event_frame_started(event_frame_started), // output event_frame_started
  .event_tlast_unexpected(event_tlast_unexpected), // output event_tlast_unexpected
  .event_tlast_missing(event_tlast_missing), // output event_tlast_missing
  .event_status_channel_halt(event_status_channel_halt), // output event_status_channel_halt
  .event_data_in_channel_halt(event_data_in_channel_halt), // output event_data_in_channel_halt
  .event_data_out_channel_halt(event_data_out_channel_halt) // output event_data_out_channel_halt
);

PLL U_PLL
   (// Clock in ports
    .CLK_IN_100M(clk),      // IN
    // Clock out ports
    .CLK_OUT_250M(CLK_OUT_250M),     // OUT
    // Status and control signals
    .RESET(~rst_n),// IN
    .LOCKED(LOCKED));      // OUT


endmodule

(2)Bram_Ctrl模块

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date:    07:36:19 08/01/2018 
// Design Name: 
// Module Name:    bram_ctrl 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//一个clk吐一个数;ena为使能信号;所有的数吐完为止;
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//
module Bram_ctrl #(
	parameter integer width_addr = 1
	)(
	clk,
	rst_n,
	ena,
	addr	
    );
	// pwm_cs <= {{(CHANNEL-1){1'b0}},1'b1};
input clk;
input rst_n;
input ena;
output [width_addr:1]addr;

wire [width_addr:1]addr_max;
assign addr_max = {(width_addr){32'hffff}};
//ena延迟一个时钟,(时序要求)
reg reg_ena;
always@(posedge clk or negedge rst_n)
	begin
		if(~rst_n)
			begin
				reg_ena <= 0;
			end
		else
			begin
				reg_ena <= ena;
			end
	end

//地址信号:
reg [width_addr:1]reg_addr;
always@(posedge clk or negedge rst_n)
	begin
		if(~rst_n)
			begin
				reg_addr <= 0;
			end
		else
			begin
				if(reg_ena)
					begin
						if(reg_addr==addr_max)//
							begin
							//	reg_addr <= reg_addr ;//只输出一遍
								reg_addr <= reg_addr + 1;//循环输出
							end
						else
							begin
								reg_addr <= reg_addr + 1;
							end
					end
				else 
					begin
						reg_addr <= reg_addr;
					end
			end
	end

assign addr = reg_addr;

endmodule

(3)Bram模块

16*512;单口ram;有ena信号;read first;有wea信号(bytesize=8);

(4)PLL模块

产生250M的时钟,其实输入时钟50M直接驱动也是可以的;

 

说点题外话:

另外当一个模块内有比较复杂的时钟系统(多个PLL)时,一定要注意BUFG等的使用(PLL的输出端口可以选择BUFG)

 

 

 

 

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值