OpenCores
URL https://opencores.org/ocsvn/fft2_size/fft2_size/trunk

Subversion Repositories fft2_size

[/] [fft2_size/] [fft_int/] [cascade_n.sv] - Rev 12

Go to most recent revision | Compare with Previous | Blame | View Log

`ifndef _cascade_n_
`define _cascade_n_
`include "butterfly.sv"
`include "yx_addr.sv"
`include "delay_line.sv"

module cascade_n #(parameter
        ADDR_WIDTH = 9,
        DATA_WIDTH = 32,
//      RES_WIDTH = DATA_WIDTH + 1,
        POW = 3 // 1...ADDR_WIDTH/2
)(
        input aclr, clk, sink_ready,
        output [ADDR_WIDTH-1:0] sink_rdaddr,
        input signed [DATA_WIDTH-1:0] sink_Re, sink_Im,
        output reg sink_rdack,
        input [ADDR_WIDTH-1:0] source_rdaddr,
        output reg signed [DATA_WIDTH:0] source_Re, source_Im,
        output reg source_ready,
        input source_rdack
);
        localparam DELAY = (POW == 1 || POW == 2) ? 3 : 4;
        
        reg wr_buf = 1'b0, rd_buf = 1'b0;
        reg signed [DATA_WIDTH:0] mem_Re[2][2**ADDR_WIDTH];
        reg signed [DATA_WIDTH:0] mem_Im[2][2**ADDR_WIDTH];
        
        reg [ADDR_WIDTH-1:0] cnt, cnt_dly;
        reg sop = 1'b0;
        wire [ADDR_WIDTH-1:0] wraddr;
        wire wrvalid;
        wire [DATA_WIDTH:0] bf_Re, bf_Im;       
        
        always @(posedge clk, posedge aclr)
                if (aclr)
                        cnt <= '0;
                else if (!sink_ready || sink_rdack)
                        cnt <= '0;
                else
                        cnt <= cnt + 1'b1;
        
        yx_addr #(.WIDTH(ADDR_WIDTH), .POW(POW)) yx0(.cnt, .yx_cnt(sink_rdaddr));
        
        always_ff @(posedge clk) begin
                sink_rdack <= cnt == 2**ADDR_WIDTH - 2; // at last addr
                sop <= cnt == 'h0;
        end
        
        butterfly #(.DATA_WIDTH(DATA_WIDTH), .POW(POW)) bf( // 3,4 clocks delay
                .clk, .sync(sop), .sink_Re, .sink_Im, // y, x
                .source_Re(bf_Re), .source_Im(bf_Im) // y, x
        );
        
        // Delay line. Butterfly (3 or 4) + memory read (1)
        delay_lines_reg #(.DELAY(DELAY + 1), .WIDTH(ADDR_WIDTH)) dly0(
                .aclr(1'b0), .sclr(1'b0), .clock(clk), .clock_ena(1'b1),
                .sig_in(cnt), .sig_out(cnt_dly)
        );
        
        delay_line_reg #(.DELAY(DELAY + 1)) dly1(
                .aclr, .sclr(1'b0), .clock(clk), .clock_ena(1'b1),
                .sig_in(sink_ready), .sig_out(wrvalid)
        );
        
        yx_addr #(.WIDTH(ADDR_WIDTH), .POW(POW)) yx1(.cnt(cnt_dly), .yx_cnt(wraddr));
        
        always_ff @(posedge clk)
                if (wrvalid)
                        begin
                                mem_Re[wr_buf][wraddr] <= bf_Re;
                                mem_Im[wr_buf][wraddr] <= bf_Im;
                        end
        
        always_ff @(posedge clk) begin
                source_Re <= mem_Re[rd_buf][source_rdaddr];
                source_Im <= mem_Im[rd_buf][source_rdaddr];
        end
        
        generate
                if (POW == ADDR_WIDTH)
                        begin
                                always_ff @(posedge clk, posedge aclr)
                                        if (aclr)
                                                source_ready <= 1'b0;
                                        else if (wrvalid && cnt_dly == 2**(POW-1))
                                                source_ready <= 1'b1;
                                        else if (source_rdack) // end
                                                source_ready <= 1'b0;
                        end
                else
                        begin
                                always_ff @(posedge clk, posedge aclr)
                                        if (aclr)
                                                source_ready <= 1'b0;
                                        else if (wrvalid && wraddr == 2**POW)
                                                source_ready <= 1'b1;
                                        else if (source_rdack) // end
                                                source_ready <= 1'b0;
                        end
        endgenerate
        
        always_ff @(posedge clk, posedge aclr)
                if (aclr)
                        wr_buf <= 1'b0;
                else if (wrvalid && cnt_dly == {ADDR_WIDTH{1'b1}})
                        wr_buf <= !wr_buf;
                        
        always_ff @(posedge clk, posedge aclr)
                if (aclr)
                        rd_buf <= 1'b0;
                else if (source_ready && source_rdack)
                        rd_buf <= !rd_buf;
        
endmodule :cascade_n

`endif

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.