?? fft_ctrl.v
字號:
// FFT controll
// point=512
//`define THE_LAST_STAGE 4'b1000 // 9-1=8
//`define THE_LAST_BFLY 8'hFF // 512/2-1=255
//point = 2048
//`define THE_LAST_STAGE 4'b1010; // point=2048
//`define THE_LAST_BFLY 10'h3FF; // 2048/2-1=1023
module fft_ctrl (
rst,
clk,
frame_in_dav,
frame_in_enb,
frame_in_sop,
frame_out_dav,
frame_out_enb,
frame_out_sop,
frame_out_eop,
ram_up_wen,
ram_up_ren,
ram_up_waddr,
ram_up_raddr,
ram_dn_wen,
ram_dn_ren,
ram_dn_waddr,
ram_dn_raddr,
rom_ren,
rom_raddr,
ram_up_wsel,
ram_up_rsel,
frame_input_on, // to input multiplexer
ram_rdata_valid,
wr_stage_cmplt,
bfly_finish
);
input rst, clk;
input frame_in_dav, frame_out_dav;
output frame_in_enb,frame_out_enb;
input frame_in_sop;
output frame_out_sop, frame_out_eop;
output ram_up_wen, ram_up_ren;
output [9:0] ram_up_waddr, ram_up_raddr;
output ram_dn_wen, ram_dn_ren;
output [9:0] ram_dn_waddr, ram_dn_raddr;
output rom_ren;
output [9:0] rom_raddr;
output ram_up_wsel;
output ram_up_rsel;
output frame_input_on;
output ram_rdata_valid;
output wr_stage_cmplt, bfly_finish;
reg frame_in_enb, frame_out_enb;
reg frame_out_sop, frame_out_eop;
wire ram_up_wsel;
reg ram_up_rsel;
wire frame_input_on;
reg ram_rdata_valid;
wire wr_stage_cmplt;
wire bfly_finish;
//=================================================
// Input control
//=================================================
reg ram_full;
reg [10:0] frame_in_cnt; //2^11= 2048
reg frame_in_cnt_enb;
wire frame_in_eop;
always @(posedge rst or posedge clk) begin
if(rst)
ram_full <= 1'b0;
else if(frame_in_eop)
ram_full <= 1'b1;
else if(frame_out_eop)
ram_full <= 1'b0;
end
always @(posedge rst or posedge clk) begin
if(rst)
frame_in_enb <= 1'b0;
else if(frame_in_eop)
frame_in_enb <= 1'b0;
else if(frame_in_dav && !ram_full)
frame_in_enb <= 1'b1;
end
always @(posedge rst or posedge clk) begin
if(rst)
frame_in_cnt_enb <= 1'b0;
else if(frame_in_eop)
frame_in_cnt_enb <= 1'b0;
else if(frame_in_enb && frame_in_sop)
frame_in_cnt_enb <= 1'b1;
end
// input switch control
assign frame_input_on = frame_in_sop | frame_in_cnt_enb;
// fram_in_cnt
always @(posedge rst or posedge clk) begin
if(rst)
frame_in_cnt <= 11'h0; // point=2048
else if(frame_in_enb && frame_input_on)
frame_in_cnt <= frame_in_cnt + 1'b1;
end
assign frame_in_eop = (frame_in_cnt==11'h7FF); // 2^11=2048
// input writing address
wire [10:0] ram_input_addr;
assign ram_input_addr = { frame_in_cnt[0],
frame_in_cnt[1],
frame_in_cnt[2],
frame_in_cnt[3],
frame_in_cnt[4],
frame_in_cnt[5],
frame_in_cnt[6],
frame_in_cnt[7],
frame_in_cnt[8],
frame_in_cnt[9],
frame_in_cnt[10]
};
//=================================================
// RAM read control in butterfly
//=================================================
reg [13:0] rd_cnt;
reg rd_cnt_enb;
wire [3:0] rd_stage;
wire [9:0] rd_index;
wire rd_index_eop;
wire rd_stage_eop;
reg [2:0] stage_end_delay;
reg rd_cnt_wait;
always @(posedge rst or posedge clk) begin
if(rst)
rd_cnt <= 14'h0;
else if(frame_in_eop)
rd_cnt <= 14'h0;
else if(rd_cnt_enb && !rd_cnt_wait )
rd_cnt <= rd_cnt + 1'b1;
end
assign rd_stage = rd_cnt[13:10];
assign rd_index = rd_cnt[9:0];
assign rd_index_eop = (rd_index==10'b11_1111_1111) && rd_cnt_enb; // the last butterfly in the stage
assign rd_stage_eop = (rd_stage==4'b1010) && rd_index_eop; // the last stage 11-1=10
always @(posedge rst or posedge clk) begin
if(rst)
stage_end_delay <= 3'b111;
else if(rd_index_eop)
stage_end_delay <= 3'b000;
else if(stage_end_delay!=3'b111)
stage_end_delay <= stage_end_delay + 1'b1;
end
always @(posedge rst or posedge clk) begin
if(rst)
rd_cnt_wait <= 1'b0;
else if(rd_index_eop)
rd_cnt_wait <= 1'b1;
else if(stage_end_delay==3'b101) // end of writing delay 6clk(0~5)
rd_cnt_wait <= 1'b0;
end
always @(posedge rst or posedge clk) begin
if(rst)
rd_cnt_enb <= 1'b0;
else if(frame_in_eop)
rd_cnt_enb <= 1'b1;
else if(rd_stage_eop )
rd_cnt_enb <= 1'b0;
end
//-------------------------------------------------
// map the RAM read address
reg [9:0] raddr_up; //1024
wire [9:0] raddr_dn;
wire ren_up;
wire ren_dn;
assign ren_up = rd_cnt_enb & ~rd_cnt_wait;
// circle left shift
always @(rd_stage or rd_index) begin
case(rd_stage)
4'b0000,
4'b1010: raddr_up <= rd_index[9:0];
4'b0001: raddr_up <= {rd_index[8:0],rd_index[9]};
4'b0010: raddr_up <= {rd_index[7:0],rd_index[9:8]};
4'b0011: raddr_up <= {rd_index[6:0],rd_index[9:7]};
4'b0100: raddr_up <= {rd_index[5:0],rd_index[9:6]};
4'b0101: raddr_up <= {rd_index[4:0],rd_index[9:5]};
4'b0110: raddr_up <= {rd_index[3:0],rd_index[9:4]};
4'b0111: raddr_up <= {rd_index[2:0],rd_index[9:3]};
4'b1000: raddr_up <= {rd_index[1:0],rd_index[9:2]};
4'b1001: raddr_up <= {rd_index[0],rd_index[9:1]};
default: raddr_up <= 10'b00_0000_0000;
endcase
end
assign ren_dn = ren_up;
assign raddr_dn = raddr_up;
//=================================================
// RAM write control in butterfly
//=================================================
reg [13:0] wr_cnt;
reg wr_cnt_enb;
wire [3:0] wr_stage;
wire [9:0] wr_index;
wire wr_index_sop;
wire wr_index_eop;
wire wr_stage_eop;
reg [2:0] stage_start_delay;
reg wr_cnt_wait;
wire wen_up;
reg wen_dn;
always @(posedge rst or posedge clk) begin
if(rst)
wr_cnt <= 14'h0;
else if(frame_in_eop) // cleared by input finish
wr_cnt <= 14'h0;
else if(wr_cnt_enb && !wr_cnt_wait )
wr_cnt <= wr_cnt + 1'b1;
end
assign wr_stage = wr_cnt[13:10];
assign wr_index = wr_cnt[9:0];
assign wr_index_sop = ((stage_end_delay==3'b101) && wr_cnt_enb) || frame_in_eop; // the last butterfly in the stage
assign wr_index_eop = (wr_index==10'b11_1111_1111) && wr_cnt_enb;
assign wr_stage_eop = (wr_stage==4'b1010) && wr_index_eop; // 11-1=10
always @(posedge rst or posedge clk) begin
if(rst)
stage_start_delay <= 3'b111;
//else if(wr_index_sop || frame_in_eop) // the start of each write stage or the end of frame_in
else if(wr_index_sop) // the start of each write stage or the end of frame_in
stage_start_delay <= 3'b000;
else if(stage_start_delay!=3'b111)
stage_start_delay <= stage_start_delay + 1'b1;
end
always @(posedge rst or posedge clk) begin
if(rst)
wr_cnt_wait <= 1'b0;
else if(wr_index_eop || frame_in_eop)
wr_cnt_wait <= 1'b1;
else if(stage_start_delay==3'b100) // end of writing delay 5clk(0~4)
wr_cnt_wait <= 1'b0;
end
always @(posedge rst or posedge clk) begin
if(rst)
wr_cnt_enb <= 1'b0;
else if(frame_in_eop)
wr_cnt_enb <= 1'b1;
else if(wr_stage_eop ) // the last writing stage
wr_cnt_enb <= 1'b0;
end
assign wen_up = wr_cnt_enb & ~wr_cnt_wait;
always @(posedge rst or posedge clk) begin
if(rst)
wen_dn <= 1'b0;
else
wen_dn <= wen_up; // 1clk dealy
end
//assign ram_up_wsel = ~wr_cnt[0] & wen_up;
//assign ram_up_wsel = ~wr_cnt[0] & wen_up & ~wr_index_eop; // avoid glach at the end of every stage
assign ram_up_wsel = ~wr_cnt[0] & (wen_up | wen_dn);
//-------------------------------------------------
// map the RAM write address
reg [9:0] waddr1, waddr2;
always @(wr_stage or wr_index) begin
case(wr_stage)
4'b0000,4'b1010: begin
waddr1 <= {wr_index[9:1],1'b0};
waddr2 <= {wr_index[9:1],1'b1};
end
4'b0001: begin
waddr1 <= {wr_index[8:1],1'b0,wr_index[9]};
waddr2 <= {wr_index[8:1],1'b1,wr_index[9]};
end
4'b0010: begin
waddr1 <= {wr_index[7:1],1'b0,wr_index[9:8]};
waddr2 <= {wr_index[7:1],1'b1,wr_index[9:8]};
end
4'b0011: begin
waddr1 <= {wr_index[6:1],1'b0,wr_index[9:7]};
waddr2 <= {wr_index[6:1],1'b1,wr_index[9:7]};
end
4'b0100: begin
waddr1 <= {wr_index[5:1],1'b0,wr_index[9:6]};
waddr2 <= {wr_index[5:1],1'b1,wr_index[9:6]};
end
4'b0101: begin
waddr1 <= {wr_index[4:1],1'b0,wr_index[9:5]};
waddr2 <= {wr_index[4:1],1'b1,wr_index[9:5]};
end
4'b0110: begin
waddr1 <= {wr_index[3:1],1'b0,wr_index[9:4]};
waddr2 <= {wr_index[3:1],1'b1,wr_index[9:4]};
end
4'b0111: begin
waddr1 <= {wr_index[2:1],1'b0,wr_index[9:3]};
waddr2 <= {wr_index[2:1],1'b1,wr_index[9:3]};
end
4'b1000: begin
waddr1 <= {wr_index[1],1'b0,wr_index[9:2]};
waddr2 <= {wr_index[1],1'b1,wr_index[9:2]};
end
4'b1001: begin
waddr1 <= {1'b0,wr_index[9:1]};
waddr2 <= {1'b1,wr_index[9:1]};
end
default: begin
waddr1 <= 10'b00_0000_0000;
waddr2 <= 10'b00_0000_0000;
end
endcase
end
// waddr2 buffer
reg [9:0] waddr2_d1t_up, waddr2_d1t_dn;
always @(posedge rst or posedge clk) begin
if(rst)
waddr2_d1t_up = 10'h0;
else if(!wr_cnt[0] && wr_cnt_enb)
waddr2_d1t_up = waddr2; // write after 1 clk delay
end
always @(posedge rst or posedge clk) begin
if(rst)
waddr2_d1t_dn = 10'h0;
else if(wr_cnt[0] && wr_cnt_enb)
waddr2_d1t_dn = waddr2; // write after 1 clk delay
end
//=================================================
// output control
//=================================================
reg bfly_finish_flg;
reg [10:0] frame_out_cnt; //2^11=2048
reg frame_out_cnt_enb;
wire frame_out_cnt_sop;
wire frame_out_cnt_eop;
//assign bfly_finish = (wr_stage==4'b1000) && (waddr2_d1t_dn==8'b1111_1111);
assign bfly_finish = (wr_stage==4'b1010) && (waddr2==10'b11_1111_1111);
always @(posedge rst or posedge clk) begin
if(rst)
bfly_finish_flg <= 1'b0;
else if(bfly_finish)
bfly_finish_flg <= 1'b1;
else if(frame_out_dav)
bfly_finish_flg <= 1'b0;
end
always @(posedge rst or posedge clk) begin
if(rst)
frame_out_cnt_enb <= 1'b0;
else if(frame_out_dav && bfly_finish_flg)
frame_out_cnt_enb <= 1'b1;
else if(frame_out_cnt_eop)
frame_out_cnt_enb <= 1'b0;
end
assign frame_out_cnt_sop = (frame_out_cnt==11'h000) && frame_out_cnt_enb;
assign frame_out_cnt_eop = (frame_out_cnt==11'h7FF) && frame_out_cnt_enb;
always @(posedge rst or posedge clk) begin
if(rst)
frame_out_cnt <= 11'h0;
else if(frame_out_cnt_eop)
frame_out_cnt <= 11'h0;
else if(frame_out_cnt_enb)
frame_out_cnt <= frame_out_cnt + 1'b1;
end
// delay 2clk output
reg frame_out_cnt_enb_d1t;
reg frame_out_cnt_sop_d1t;
reg frame_out_cnt_eop_d1t;
always @(posedge rst or posedge clk) begin
if(rst) begin
frame_out_cnt_enb_d1t <= 1'b0;
frame_out_cnt_sop_d1t <= 1'b0;
frame_out_cnt_eop_d1t <= 1'b0;
frame_out_enb <= 1'b0;
frame_out_sop <= 1'b0;
frame_out_eop <= 1'b0;
end
else begin
frame_out_cnt_enb_d1t <= frame_out_cnt_enb;
frame_out_cnt_sop_d1t <= frame_out_cnt_sop;
frame_out_cnt_eop_d1t <= frame_out_cnt_eop;
frame_out_enb <= frame_out_cnt_enb_d1t;
frame_out_sop <= frame_out_cnt_sop_d1t;
frame_out_eop <= frame_out_cnt_eop_d1t;
end
end
//=================================================
// RAM control output
//=================================================
assign ram_up_ren = ren_up | (frame_out_cnt_enb & ~frame_out_cnt[0]);
assign ram_dn_ren = ren_dn | (frame_out_cnt_enb & frame_out_cnt[0]);
assign ram_up_raddr = (frame_out_cnt_enb) ? {frame_out_cnt[9:1],frame_out_cnt[10]} :
raddr_up;
assign ram_dn_raddr = (frame_out_cnt_enb) ? {frame_out_cnt[9:1],frame_out_cnt[10]} :
raddr_dn;
assign ram_up_wen = (~ram_input_addr[0] & frame_input_on) | wen_up ;
assign ram_dn_wen = ( ram_input_addr[0] & frame_input_on) | wen_dn ;
assign ram_up_waddr = (frame_input_on) ? ram_input_addr[10:1] :
(wr_cnt[0]) ? waddr2_d1t_up : waddr1;
assign ram_dn_waddr = (frame_input_on) ? ram_input_addr[10:1] :
(wr_cnt[0]) ? waddr1 : waddr2_d1t_dn;
//=================================================
// map the ROM read address
//=================================================
reg rom_ren;
reg [10:0] right_shift;
reg [9:0] rom_raddr;
wire [9:0] rom_offset;
reg [9:0] tw_cnt;
wire [9:0] field_num;
always @(posedge rst or posedge clk) begin
if(rst)
rom_ren <= 1'b0;
else if(stage_start_delay==3'b000) // 1clk delay with ram_ren
rom_ren <= 1'b1;
else if(stage_end_delay==3'b000)
rom_ren <= 1'b0;
end
always @(posedge rst or posedge clk) begin
if(rst)
right_shift <= 11'b000_0000_0000;
else if(frame_in_eop)
right_shift <= 11'b100_0000_0000;
//else if(rd_index_eop)
else if(stage_end_delay==3'b001)
right_shift <= {1'b0,right_shift[10:1]};
end
assign rom_offset = right_shift[9:0];
assign field_num = rom_offset - 1'b1;
always @(posedge rst or posedge clk) begin
if(rst) begin
tw_cnt <= 9'h0;
end
else begin
if( (tw_cnt == field_num) && rom_ren )
tw_cnt <= 9'h0;
else if (rom_ren)
tw_cnt <= tw_cnt + 1'b1;
end
end
always @(posedge rst or posedge clk) begin
if(rst)
rom_raddr <= 10'b00_0000_0000;
else if(frame_in_eop)
rom_raddr <= 10'b00_0000_0000;
else if(rom_ren && (tw_cnt == field_num) )
rom_raddr <= rom_raddr + rom_offset;
end
//=================================================
// internal control out
//=================================================
reg frame_out_ram_up;
always @(posedge rst or posedge clk) begin
if(rst)
ram_rdata_valid <= 1'b0;
else if(stage_start_delay==3'b001) // 2clk delay after ram_ren
ram_rdata_valid <= 1'b1;
else if(stage_end_delay==3'b001)
ram_rdata_valid <= 1'b0;
end
assign wr_stage_cmplt = wr_index_eop;
always @(posedge rst or posedge clk) begin
if(rst) begin
frame_out_ram_up <= 1'b0;
ram_up_rsel <= 1'b0;
end
else begin
frame_out_ram_up <= frame_out_cnt_enb & ~frame_out_cnt[0];
ram_up_rsel <= frame_out_ram_up;
end
end
endmodule
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -