Top secrets sources NedoPC pentevo

Rev

Blame | Last modification | View Log | Download | RSS feed | ?url?

// PentEvo project (c) NedoPC 2008-2009
//
// state:          | RD1   | RD2   | RD3   | RD4   | WR1   | WR2   | WR3   | WR4   | RFSH1 | RFSH2 | RFSH3 | RFSH4 |
// clk: ___/```\___/```\___/```\___/```\___/```\___/```\___/```\___/```\___/```\___/```\___/```\___/```\___/```\___/```\__
//                 |      READ CYCLE               |      WRITE CYCLE              |      REFRESH CYCLE            |
// ras: ```````````````````\_______________/```````````````\_______________/```````````````````````\_______________/
// cas: ```````````````````````````\_______________/```````````````\_______________/```````\_______________/````````
// ra:                 |  row  | column|               |  row  | column|
// rd:     XXXXXXXXXXXXXXXXXXXXXXXXX<read data read|  write data write data write  |
// rwe:   `````````````````````````````````````````\_______________________________/````````````````````````````````
// req:  __/```````\_______________________/```````\________________________________________________________________
// rnw:  XX/```````\XXXXXXXXXXXXXXXXXXXXXXX\_______/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
// cbeg: __________/```````\_______________________/```````\_______________________/```````\_______________________/
// rrdy: __________________________________/```````\________________________________________________________________
// addr: XX< addr  >XXXXXXXXXXXXXXXXXXXXXXX< addr  >XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
//wrdata:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX< write >XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
//rddata:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX< read  >XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
//
// comments:
// rucas_n, rlcas_n, rras0_n, rras1_n, rwe_n could be made 'fast output register'
// ra[] couldn't be such in acex1k, because output registers could be all driven only by
//  single clock polarity (and here they are driven by negative edge, while CAS/RAS by positive)
//
// rst_n is resynced before use and acts as req inhibit. so while in reset, dram regenerates and isn't corrupted

module dram(

        input clk,
        input rst_n, // shut down accesses, remain refresh

        output reg [9:0] ra, // to the DRAM pins
        inout     [15:0] rd, // .              .
                             // .              .
        output reg rwe_n,    // .              .
        output reg rucas_n,  // .              .
        output reg rlcas_n,  // .              .
        output reg rras0_n,  // .              .
        output reg rras1_n,  // to the DRAM pins

        input [20:0] addr, // access address of 16bit word: addr[0] selects between rras0_n and rras1_n,
                           // addr[10:1] goes to row address, addr[20:11] goes to column address

        input req,         // request for read/write cycle
        input rnw,         // READ/nWRITE (=1: read, =0: write)

        output reg cbeg,       // cycle begin (any including refresh), can be used for synchronizing
        output reg rrdy,       // Read data ReaDY

        output reg [15:0] rddata, // data just read

        input  [15:0] wrdata, // data to be written
        input   [1:0] bsel    // positive byte select for write: bsel[0] is for wrdata[7:0], bsel[1] is for wrdata[15:8]


);

        reg [1:0] rst_sync;
        wire reset;
        wire int_req;

        reg [20:0] int_addr;
        reg [15:0] int_wrdata;
        reg  [1:0] int_bsel;



        reg [3:0] state;
        reg [3:0] next_state;

        localparam RD1   = 0;
        localparam RD2   = 1;
        localparam RD3   = 2;
        localparam RD4   = 3;
        localparam WR1   = 4;
        localparam WR2   = 5;
        localparam WR3   = 6;
        localparam WR4   = 7;
        localparam RFSH1 = 8;
        localparam RFSH2 = 9;
        localparam RFSH3 = 10;
        localparam RFSH4 = 11;


        always @(posedge clk)
        begin
                state <= next_state;
        end

        always @*
                case( state )

                RD1:
                        next_state = RD2;
                RD2:
                        next_state = RD3;
                RD3:
                        next_state = RD4;
                RD4:
                        if( !int_req )
                                next_state = RFSH1;
                        else
                                next_state = rnw?RD1:WR1;

                WR1:
                        next_state = WR2;
                WR2:
                        next_state = WR3;
                WR3:
                        next_state = WR4;
                WR4:
                        if( !int_req )
                                next_state = RFSH1;
                        else
                                next_state = rnw?RD1:WR1;


                RFSH1:
                        next_state = RFSH2;
                RFSH2:
                        next_state = RFSH3;
                RFSH3:
                        next_state = RFSH4;
                RFSH4:
                        if( !int_req )
                                next_state = RFSH1;
                        else
                                next_state = rnw?RD1:WR1;

                endcase


        // incoming data latching
        always @(posedge clk)
        begin
                if( (state==RD4) || (state==WR4) || (state==RFSH4) )
                begin
                        int_addr   <= addr;
                        int_wrdata <= wrdata;
                        int_bsel   <= bsel;
                end
        end

        // WE control
        always @(posedge clk)
        begin
                if( (next_state==WR1) || (next_state==WR2) || (next_state==WR3) || (next_state==WR4) )
                        rwe_n <= 1'b0;
                else
                        rwe_n <= 1'b1;
        end


        // RAS/CAS sequencing
        always @(posedge clk)
        begin
                case( state )
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                RD1:
                begin
                        rras0_n <= int_addr[0];
                        rras1_n <= ~int_addr[0];
                end
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                RD2:
                begin
                        rucas_n <= 1'b0;
                        rlcas_n <= 1'b0;
                end
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                RD3:
                begin
                        rras0_n <= 1'b1;
                        rras1_n <= 1'b1;
                end
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                RD4:
                begin
                        rras0_n <= 1'b1;
                        rras1_n <= 1'b1;
                        rucas_n <= 1'b1;
                        rlcas_n <= 1'b1;
                end
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                WR1:
                begin
                        rras0_n <= int_addr[0];
                        rras1_n <= ~int_addr[0];
                end
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                WR2:
                begin
                        rucas_n <= ~int_bsel[1];
                        rlcas_n <= ~int_bsel[0];
                end
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                WR3:
                begin
                        rras0_n <= 1'b1;
                        rras1_n <= 1'b1;
                end
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                WR4:
                begin
                        rras0_n <= 1'b1;
                        rras1_n <= 1'b1;
                        rucas_n <= 1'b1;
                        rlcas_n <= 1'b1;
                end
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                RFSH1:
                begin
                        rucas_n <= 1'b0;
                        rlcas_n <= 1'b0;
                end
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                RFSH2:
                begin
                        rras0_n <= 1'b0;
                        rras1_n <= 1'b0;
                end
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                RFSH3:
                begin
                        rucas_n <= 1'b1;
                        rlcas_n <= 1'b1;
                end
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                RFSH4:
                begin
                        rras0_n <= 1'b1;
                        rras1_n <= 1'b1;
                        rucas_n <= 1'b1;
                        rlcas_n <= 1'b1;
                end
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                endcase
        end


        // row/column address multiplexing
        always @(negedge clk)
        begin
                if( (state==RD1) || (state==WR1) )
                        ra <= int_addr[10:1];
                else
                        ra <= int_addr[20:11];
        end


        // DRAM data bus control
        assign rd = rwe_n ? 16'hZZZZ : int_wrdata;


        // read data from DRAM
        always @(posedge clk)
        begin
                if( state==RD3 )
                        rddata <= rd;
        end


        // cbeg and rrdy control
        always @(posedge clk)
        begin
                if( (state==RD4) || (state==WR4) || (state==RFSH4) )
                        cbeg <= 1'b1;
                else
                        cbeg <= 1'b0;


            if( state==RD3 )
                rrdy <= 1'b1;
            else
                rrdy <= 1'b0;
        end


        // reset must be synchronous here in order to preserve
        // DRAM state while other modules reset, but we have only
        // asynchronous one globally. so we must re-synchronize it
        // and use it as 'DRAM operation enable'. when in reset,
        // controller ignores req signal and generates only refresh cycles
        always @(posedge clk)
                rst_sync[1:0] <= { rst_sync[0], ~rst_n };

        assign reset = rst_sync[1];

        assign int_req = req & (~reset);

endmodule