verilog实现czt变换
Posted 者乎之类的
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了verilog实现czt变换相关的知识,希望对你有一定的参考价值。
没太有心思写具体过程了,仅记录设计(编代码)过程中的几个版本
原理及实现步骤
版本一
刚开始写不太会写,考虑数据流方式进行fft,ifft等操作,数据延迟搞不清,就将数据全部进行加载,类似于将串行数据流并行读入并使用,这样使用时就不用考虑延迟对不准数据使用错误了。
即:
//数据
wire signed [15:0]inputdata_r;
gen_inputdata u_gen_inputdata(
.clka(clk_in),
.addra(inputdata_addr),
.douta(inputdata_r)
);
reg signed [15:0]input_data[0:N-1];
//装载din和wn
always@(posedge clk_in or negedge rst_n)begin
if(!rst_n)begin
wndata_addr<=0;
inputdata_addr<=0;
end
else begin
wndata_addr<=wndata_addr+1'b1;
inputdata_addr<=inputdata_addr+1'b1;
end
end
wire en_din[0:M-1];
genvar i;
wire [8:0] en_din_o;
assign en_din_o=inputdata_addr-1;
generate for (i=0;i<=M-1;i=i+1)begin:ram_loop
assign en_din[i]=(en_din_o==i);
always@(posedge clk_in or negedge rst_n)begin
if(!rst_n)begin
input_data[i]<=0;
input_dataimg[i]<=0;
wndatareal[i]<=0;
wndataimg[i]<=0;
end
else if(en_din[i])begin
input_data[i]<=inputdata_r;
input_dataimg[i]<=inputdataimg_r;
wndatareal[i]<=wndatareal_r;
wndataimg[i]<=wndataimg_r;
end
else begin
input_data[i]<=input_data[i];
input_dataimg[i]<=input_dataimg[i];
wndatareal[i]<=wndatareal[i];
wndataimg[i]<=wndataimg[i];
end
end
end
endgenerate
整体代码:
module czt(
input clk_in,
input rst_n,
//input signed [15:0]inputdatareal_r,
//input signed [15:0]inputdataimg_r,
output [41:0]czt_datareal,
output [41:0]czt_dataimg,
output [42:0]czt_data
);
//常数定义
parameter N = 10'd512;
parameter M = 10'd512;
parameter L = 11'd1024;
状态机
//reg [4:0] state=0; //状态机
//reg [4:0] state_wn=0; //装载wn
//reg [4:0] state_din=1; //装载din
//reg [4:0] state_g=2; //din*wn
//reg [4:0] state_h=3; //装载h
//reg [4:0] state_fft4g=3; //gfft运算
//地址
reg [8:0] wndata_addr;
reg [9:0] hdata_addr;
reg [8:0]inputdata_addr; //输入数据查表地址
//数据
wire signed [15:0]inputdata_r;
wire signed [15:0]inputdataimg_r;
wire signed [31:0]wndatareal_r;
wire signed [31:0]wndataimg_r;
wire signed [31:0]hdatareal_r;
wire signed [31:0]hdataimg_r;
reg signed [15:0]input_data[0:N-1];
reg signed [15:0]input_dataimg[0:N-1];
reg signed [31:0]wndatareal[0:N-1];
reg signed [31:0]wndataimg[0:N-1];
reg signed [31:0]hdatareal[0:L-1];
reg signed [31:0]hdataimg[0:L-1];
reg signed [48:0]data_g_real[0:L-1];
reg signed [48:0]data_g_img[0:L-1];
//装载din和wn
always@(posedge clk_in or negedge rst_n)begin
if(!rst_n)begin
wndata_addr<=0;
inputdata_addr<=0;
end
else begin
wndata_addr<=wndata_addr+1'b1;
inputdata_addr<=inputdata_addr+1'b1;
end
end
wire en_din[0:M-1];
genvar i;
wire [8:0] en_din_o;
assign en_din_o=inputdata_addr-1;
generate for (i=0;i<=M-1;i=i+1)begin:ram_loop
assign en_din[i]=(en_din_o==i);
always@(posedge clk_in or negedge rst_n)begin
if(!rst_n)begin
input_data[i]<=0;
input_dataimg[i]<=0;
wndatareal[i]<=0;
wndataimg[i]<=0;
end
else if(en_din[i])begin
input_data[i]<=inputdata_r;
input_dataimg[i]<=inputdataimg_r;
wndatareal[i]<=wndatareal_r;
wndataimg[i]<=wndataimg_r;
end
else begin
input_data[i]<=input_data[i];
input_dataimg[i]<=input_dataimg[i];
wndatareal[i]<=wndatareal[i];
wndataimg[i]<=wndataimg[i];
end
end
end
endgenerate
//装载h
always@(posedge clk_in or negedge rst_n)begin
if(!rst_n)begin
hdata_addr<=0;
end
else begin
hdata_addr<=hdata_addr+1'b1;
end
end
wire en_h[0:L-1];
wire [9:0] en_h_o;
assign en_h_o=hdata_addr-1;
generate for (i=0;i<=L-1;i=i+1)begin:ram_loop_h
assign en_h[i]=(en_h_o==i);
always@(posedge clk_in or negedge rst_n)begin
if(!rst_n)begin
hdatareal[i]<=0;
hdataimg[i]<=0;
end
else if(en_h[i])begin
hdatareal[i]<=hdatareal_r;
hdataimg[i]<=hdataimg_r;
end
else begin
hdatareal[i]<=hdatareal[i];
hdataimg[i]<=hdataimg[i];
end
end
end
endgenerate
//计算din*wn
generate for (i=0;i<=M-1;i=i+1)begin:loop_din_wn
always@(posedge clk_in or negedge rst_n)begin
if(!rst_n)begin
data_g_real[i]<=0;
data_g_img[i]<=0;
end
else begin
data_g_real[i]<=input_data[i]*wndatareal[i]-input_dataimg[i]*wndataimg[i];
data_g_img[i]<=input_data[i]*wndataimg[i]+input_dataimg[i]*wndatareal[i];
end
end
end
endgenerate
generate for (i=M;i<=L-1;i=i+1)begin:loop_din_wn1
always@(posedge clk_in or negedge rst_n)begin
if(!rst_n)begin
data_g_real[i]<=0;
data_g_img[i]<=0;
end
else begin
data_g_real[i]<=0;
data_g_img[i]<=0;
end
end
end
endgenerate
//准备fft1信号
reg start1,start1_r;
wire start;
assign start=start1 && !start1_r;
reg [9:0]fft_cnt;
always@(posedge clk_in or negedge rst_n)begin
if(!rst_n)begin
fft_cnt<=0;
end
else begin
fft_cnt<=fft_cnt+1'b1;
end
end
always@(posedge clk_in or negedge rst_n)begin
if(!rst_n)begin
start1<=0;
end
else if(fft_cnt==10'd1023)begin
start1<=1;
end
else begin
start1<=start1;
end
end
always@(posedge clk_in or negedge rst_n)begin
if(!rst_n)begin
start1_r<=0;
end
else begin
start1_r<=start1;
end
end
wire fwd_inv,fwd_inv_we,fwd_inv_ifft;
reg fwd_inv_we1,fwd_inv_we1_r;
assign fwd_inv=1;
assign fwd_inv_ifft=0;
assign fwd_inv_we=(fwd_inv_we1 && !fwd_inv_we1_r);
always@(posedge clk_in or negedge rst_n)begin
if(!rst_n)begin
fwd_inv_we1<=1'b0;
fwd_inv_we1_r<=1'b0;
end
else begin
fwd_inv_we1<=1'b1;
fwd_inv_we1_r<=fwd_inv_we1;
end
end
reg signed[31:0]xn_re,xn_im;
always@(posedge clk_in or negedge rst_n)begin
if(!rst_n)begin
xn_re<=32'b0;
xn_im<=32'b0;
end
else begin
xn_re<=data_g_real[fft_cnt][48:17];
xn_im<=data_g_img[fft_cnt][48:17];
end
end
wire rfd;
wire busy;
wire edone;
wire done;
wire dv;
wire [9:0] xn_index;
wire [9:0] xk_index;
wire signed[42:0] xk_re;
wire signed[42:0] xk_im;
// Instantiate the Unit Under Test (UUT)
fft1 fft4mul (
.clk(clk_in),
.start(start),
.fwd_inv(fwd_inv),
.fwd_inv_we(fwd_inv_we),
.rfd(rfd),
.busy(busy),
.edone(edone),
.done(done),
.dv(dv),
.xn_re(xn_re),
.xn_im(xn_im),
.xn_index(xn_index),
.xk_index(xk_index),
.xk_re(xk_re),
.xk_im(xk_im)
);
//hfft
wire rfd1;
wire busy1;
wire edone1;
wire done1;
wire dv1;
wire [9:0] xn_index1;
wire [9:0] xk_index1;
wire signed[42:0] xk_re1;
wire signed[42:0] xk_im1;
reg signed[31:0]xn_re1,xn_im1;
always@(posedge clk_in or negedge rst_n)begin
if(!rst_n)begin
xn_re1<=32'b0;
xn_im1<=32'b0;
end
else begin
xn_re1<=hdatareal[fft_cnt];
xn_im1<=hdatareal[fft_cnt];
end
end
fft1 fft4h (
.clk(clk_in),
.start(start),
.fwd_inv(fwd_inv),
.fwd_inv_we(fwd_inv_we),
.rfd(rfd1),
.busy(busy1),
.edone(edone1),
.done(done1),
.dv(dv1),
.xn_re(xn_re1),
.xn_im(xn_im1),
.xn_index(xn_index1),
.xk_index(xk_index1),
.xk_re(xk_re1),
.xk_im(xk_im1)
);
/
//两fft后相乘
reg signed [35:0]q_re_j,q_im_j;
wire signed[16:0] xk_re_j,xk_re1_j,xk_im_j,xk_im1_j;
assign xk_re_j=xk_re[34:18];
assign xk_re1_j=xk_re1[38:22];
assign xk_im_j=xk_im[34:18];
assign xk_im1_j=xk_im1[38:22];
always@(posedge clk_in or negedge rst_n)begin
if(!rst_n)begin
q_re_j<=32'b0;
q_im_j<=32'b0;
end
else begin
q_re_j<=xk_re_j*xk_re1_j-xk_im_j*xk_im1_j;
q_im_j<=xk_re_j*xk_im1_j+xk_re1_j*xk_im_j;
end
end
wire signed [31:0]q_re,q_im;
assign q_re=q_re_j[32:1];
assign q_im=q_im_j[32:1];
/
//ifft
wire rfd2;
wire busy2;
wire edone2;
wire done2;
wire dv2;
wire [9:0] xn_index2;
wire [9:0] xk_index2;
wire signed[42:0] xk_re2;
wire signed[42:0] xk_im2;
fft1 ifft (
.clk(clk_in),
.start(edone1),
.fwd_inv(fwd_inv_ifft),
.fwd_inv_we(fwd_inv_we),
.rfd(rfd2),
.busy(busy2),
.edone(edone2),
.done(done2),
.dv(dv2),
.xn_re(q_re),
.xn_im(q_im),
.xn_index(xn_index2),
.xk_index(xk_index2),
.xk_re(xk_re2),
.xk_im(xk_im2)
);
assign czt_datareal=xk_re2[42]?(~xk_re2+1):xk_re2;
assign czt_dataimg=xk_im2[42]?(~xk_im2+1):xk_im2;
assign czt_data=czt_datareal+czt_dataimg;
gen_inputdata u_gen_inputdata(
.clka(clk_in),
.addra(inputdata_addr),
.douta(inputdata_r)
);
gen_inputdata_img u_gen_inputdata_img(
.clka(clk_in),
.addra(inputdata_addr),
.douta(inputdataimg_r)
);
gen_wn gen_wn_real(
.clka(clk_in),
.addra(wndata_addr),
.douta(wndatareal_r)
);
gen_wn_img gen_wn_imag(
.clka(clk_in),
.addra(wndata_addr),
.douta(wndataimg_r)
);
gen_h gen_h_real(
.clka(clk_in),
.addra(hdata_addr),
.douta(hdatareal_r)
);
gen_h_img gen_h_imag(
.clka(clk_in),
.addra(hdata_addr),
.Notepad++编辑器——Verilog代码片段直接编译
FPGA小波变换基于FPGA的图像9/7整数小波变换verilog实现