/*
 
  read sequence
 
 
 
clk   ``\____/````\____/` ..... _/````\____/````\____/` ..... _/````\____/````\____/`
 
             |         |         |         |         |         |         |
 
start XXXX```````````\__ ....... ____________________________________________________
 
             |         |         |         |         |         |         |
 
rnw   XXXXXX```XXXXXXXXX ....... XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 
             |         | some    |         |         |         |         |
 
ready XXXXXXX\__________ clocks __/``````````````````  ....... ```````````\__________
 
                         before                                |         |
 
rdat  ------------------ ready  -< cell 0  | cell 1  | ....... |last cell>-----------
 
             |         |         |         |         |         |         |
 
stop  XXXXXXX\__________ ....... _____________________ ....... ___________/``````````
 
                                                                            ^all operations stopped until next start strobe
 
 
 
 
 
 
 
  write sequence
 
 
 
clk   ``\____/````\____/` ..... _/````\____/````\____/````\____/````\____/````\____/````\____/````\____/
 
             |         | some    |         | some    |         |         |         |         |         |
 
start XXXX```````````\__ ....... _____________ .... ______________ .... ________________________________
 
             |         | clocks  |         | clocks  |         |         |         |         |         |
 
rnw   XXXXXX___XXXXXXXXX ....... XXXXXXXXXXXXX .... XXXXXXXXXXXXXX .... XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 
             |         | before  |         | before  |         |         |         |         |         |
 
ready XXXXXXX\__________ ....... _/`````````\_ .... __/`````````\_ .... __/`````````\___________________
 
             |         | first   |         | next    |         |         |         |         |         |
 
wdat  XXXXXXXXXXXXXXXXXXXXXXXXXXXX< cell 0  >X .... XX< cell 1  >X .... XX<last cell>XXXXXXXXXXXXXXXXXXX
 
             |         | ready   |         | ready   |         |         |         |         |         |
 
stop  XXXXXXX\__________ ....... _____________ .... ______________ .... ____________/```````````````````
 
             |         | strobe  |         | strobe  |         |         |         |         |         |
 
 
 
 
 
 
 
 
 
clk   ``\____/````\____/````\____/````\____/````\____/````\____/````\____/````\____/````\____/````\____/````\____/````\____/``
 
             |         |         |         |         |         |         |         |         |         |         |         |
 
ready __________________/`````````\___________________/`````````\___________________/`````````\___________________/`````````\_
 
             |         |         |         |         |         |         |         |         |         |         |         |
 
wdat           cell 0             | cell 1                      | cell 2                      | cell 3                      |
 
             |         |         |         |         |         |         |         |         |         |         |         |
 
sram_adr XXXXXXXXXXXXXXXXXXXXXXXXX| 0                           | 1                           | 2                           |
 
             |         |         |         |         |         |         |         |         |         |         |         |
 
sram_dat XXXXXXXXXXXXXXXXXXXXXXXXX| cell 0                      | cell 1                      | cell 2                      |
 
             |         |         |         |         |         |         |         |         |         |         |         |
 
sram_we_n```````````````````````````````````\_________/```````````````````\_________/```````````````````\_________/``````````
 
             | BEG     | PRE1    | PRE2    |         |         |         |         |         |         |         |         |
 
             |         |         | CYC1    | CYC2    | CYC3    | CYC1    | CYC2    | CYC3    | CYC1    | CYC2    | CYC3    |
 
 
 
 
 
 
 
 
 
 
 
 
 
*/
 
 
 
 
 
module sram_control(
 
 
 
        clk,
 
        clk2, //latching of SRAM data out
 
 
 
        start, // initializing input, address=0
 
 
 
        stop, // when all addresses are done, nothing will happen after stop is set, need another start signal
 
 
 
        rnw, // 1 - read, 0 - write sequence (latched when start=1)
 
 
 
        ready, // strobe. when writing, one mean that data from wdat written to the memory (2^SRAM_ADDR_SIZE strobes total)
 
               // when reading, one mean that data read from memory is on rdat output (2^SRAM_ADDR_SIZE strobes total)
 
 
 
 
 
        wdat, // input, data to be written to memory
 
        rdat, // output, data last read from memory
 
 
 
 
 
 
 
        SRAM_DQ,   // sram inout databus
 
 
 
        SRAM_ADDR, // sram address bus
 
 
 
        SRAM_UB_N, // sram control signals
 
        SRAM_LB_N, //
 
        SRAM_WE_N, //
 
        SRAM_CE_N, //
 
        SRAM_OE_N  //
 
);
 
 
 
parameter SRAM_DATA_SIZE = 16;
 
parameter SRAM_ADDR_SIZE = 18;
 
 
 
 
 
        input clk;
 
        input clk2;
 
 
 
        input start,rnw;
 
 
 
        output stop;
 
        reg    stop;
 
 
 
        output ready;
 
        reg    ready;
 
 
 
        input [SRAM_DATA_SIZE-1:0] wdat;
 
 
 
        output [SRAM_DATA_SIZE-1:0] rdat;
 
        reg    [SRAM_DATA_SIZE-1:0] rdat;
 
 
 
 
 
        inout [SRAM_DATA_SIZE-1:0] SRAM_DQ;
 
        reg   [SRAM_DATA_SIZE-1:0] SRAM_DQ;
 
 
 
        output [SRAM_ADDR_SIZE-1:0] SRAM_ADDR;
 
        wire   [SRAM_ADDR_SIZE-1:0] SRAM_ADDR;
 
 
 
        output SRAM_UB_N,SRAM_LB_N,SRAM_WE_N,SRAM_CE_N,SRAM_OE_N;
 
        reg    SRAM_UB_N,SRAM_LB_N,SRAM_WE_N,SRAM_CE_N,SRAM_OE_N;
 
 
 
 
 
        reg [SRAM_DATA_SIZE-1:0] wdat2;
 
        reg dbin; //data bus direction control
 
 
 
        reg  [SRAM_ADDR_SIZE:0] sram_addr_ctr; // one bit bigger to have stop flag
 
        wire [SRAM_ADDR_SIZE:0] sram_addr_nxt; // next sram address
 
 
 
 
 
        reg [SRAM_DATA_SIZE-1:0] rdat2;
 
 
 
        assign SRAM_ADDR = sram_addr_ctr[SRAM_ADDR_SIZE-1:0];
 
 
 
        assign sram_addr_nxt = sram_addr_ctr + 1;
 
 
 
 
 
        // data bus control
 
        always @*
 
        begin
 
                if( dbin )
 
                        SRAM_DQ <= 'hZ;
 
                else // !dbin
 
                        SRAM_DQ <= wdat2;
 
        end
 
 
 
        always @(posedge clk2) // clk2!!!! late latching
 
        begin
 
                rdat2 <= SRAM_DQ;
 
        end
 
 
 
        always @(posedge clk)
 
        begin
 
                rdat <= rdat2;
 
        end
 
 
 
 
 
        always @(posedge clk)
 
        begin
 
                if( ready ) wdat2 <= wdat;
 
        end
 
 
 
 
 
 
 
 
 
 
 
        reg [3:0] curr_state,next_state;
 
 
 
        parameter START_STATE = 4'd00; // reset state
 
 
 
        parameter INIT_STATE  = 4'd01; // initialization state
 
 
 
        parameter READ_BEG    = 4'd02; // read branch: prepare signals
 
        parameter READ_PRE    = 4'd13;
 
        parameter READ_CYCLE  = 4'd03; // read in progress: increment address, set ready, out data, do so until all addresses done
 
        parameter READ_POST   = 4'd14;
 
        parameter READ_END    = 4'd04; // read end: deassert some signals, go to stop state
 
 
 
        parameter WRITE_BEG   = 4'd05; // prepare signals
 
        parameter WRITE_PRE1  = 4'd06; // assert ready
 
        parameter WRITE_PRE2  = 4'd07; // capture wdat, negate ready, NO INCREMENT address, next state is WRITE_CYC2
 
        parameter WRITE_CYC1  = 4'd08; // capture wdat, negate ready, increment address
 
        parameter WRITE_CYC2  = 4'd09; // assert SRAM_WE_N, go to WRITE_END if sram_addr_nxt is out of memory region
 
        parameter WRITE_CYC3  = 4'd10; // negate SRAM_WE_N, assert ready (wdat will be captured in WRITE_CYC1)
 
        parameter WRITE_END   = 4'd11; // deassert sram control signals, go to STOP_STATE
 
 
 
 
 
        parameter STOP_STATE  = 4'd12; // full stop state
 
 
 
 
 
 
 
        // FSM states
 
        always @*
 
        begin
 
                case( curr_state )
 
 
 
////////////////////////////////////////////////////////////////////////
 
                START_STATE:
 
                        next_state = INIT_STATE;
 
 
 
 
 
////////////////////////////////////////////////////////////////////////
 
                INIT_STATE:
 
                begin
 
                        if( rnw ) // read
 
                                next_state = READ_BEG;
 
                        else // !rnw - write
 
                                next_state = WRITE_BEG;
 
                end
 
 
 
 
 
 
 
 
 
////////////////////////////////////////////////////////////////////////
 
                READ_BEG:
 
                        next_state = READ_PRE;
 
 
 
                READ_PRE:
 
                        next_state = READ_CYCLE;
 
 
 
                READ_CYCLE:
 
                        if( !sram_addr_ctr[SRAM_ADDR_SIZE] )
 
                                next_state = READ_CYCLE;
 
                        else
 
                                next_state = READ_POST;
 
 
 
                READ_POST:
 
                        next_state = READ_END;
 
 
 
                READ_END:
 
                        next_state = STOP_STATE;
 
 
 
 
 
 
 
////////////////////////////////////////////////////////////////////////
 
                WRITE_BEG:
 
                        next_state = WRITE_PRE1;
 
 
 
                WRITE_PRE1:
 
                        next_state = WRITE_PRE2;
 
 
 
                WRITE_PRE2:
 
                        next_state = WRITE_CYC2;
 
 
 
 
 
                WRITE_CYC1:
 
                        next_state = WRITE_CYC2;
 
 
 
                WRITE_CYC2:
 
                        if( !sram_addr_nxt[SRAM_ADDR_SIZE] )
 
                                next_state = WRITE_CYC3;
 
                        else
 
                                next_state = WRITE_END;
 
 
 
                WRITE_CYC3:
 
                        next_state = WRITE_CYC1;
 
 
 
                WRITE_END:
 
                        next_state = STOP_STATE;
 
 
 
 
 
 
 
////////////////////////////////////////////////////////////////////////
 
                STOP_STATE:
 
                        next_state = STOP_STATE;
 
 
 
 
 
 
 
 
 
////////////////////////////////////////////////////////////////////////
 
                default:
 
                        next_state = STOP_STATE;
 
 
 
                endcase
 
 
 
        end
 
 
 
 
 
 
 
        // FSM flip-flops
 
        always @(posedge clk)
 
        begin
 
                if( start )
 
                        curr_state <= START_STATE;
 
                else
 
                        curr_state <= next_state;
 
        end
 
 
 
 
 
        // FSM outputs
 
        always @(posedge clk)
 
        begin
 
                case( next_state )
 
 
 
////////////////////////////////////////////////////////////////////////
 
                INIT_STATE:
 
                begin
 
                        stop <= 1'b0;
 
 
 
                        SRAM_UB_N <= 1'b1;
 
                        SRAM_LB_N <= 1'b1;
 
                        SRAM_CE_N <= 1'b1;
 
                        SRAM_OE_N <= 1'b1;
 
                        SRAM_WE_N <= 1'b1;
 
 
 
                        dbin <= 1'b1;
 
 
 
                        sram_addr_ctr <= 0;
 
 
 
                        ready <= 1'b0;
 
                end
 
 
 
 
 
 
 
////////////////////////////////////////////////////////////////////////
 
                READ_BEG:
 
                begin
 
                        SRAM_UB_N <= 1'b0;
 
                        SRAM_LB_N <= 1'b0;
 
                        SRAM_CE_N <= 1'b0;
 
                        SRAM_OE_N <= 1'b0;
 
                end
 
 
 
                READ_PRE:
 
                begin
 
                  sram_addr_ctr <= sram_addr_nxt;
 
                end
 
 
 
                READ_CYCLE:
 
                begin
 
                        ready <= 1'b1;
 
 
 
                  sram_addr_ctr <= sram_addr_nxt;
 
                end
 
 
 
                READ_POST:
 
                begin
 
                        ready <= 1'b0; // in read sequence, ready and data are 2 cycles past the actual read.
 
                end
 
 
 
                READ_END:
 
                begin
 
                        SRAM_UB_N <= 1'b1;
 
                        SRAM_LB_N <= 1'b1;
 
                        SRAM_CE_N <= 1'b1;
 
                        SRAM_OE_N <= 1'b1;
 
 
 
                        ready <= 1'b0;
 
                end
 
 
 
 
 
 
 
 
 
////////////////////////////////////////////////////////////////////////
 
                WRITE_BEG:
 
                begin
 
                        SRAM_UB_N <= 1'b0;
 
                        SRAM_LB_N <= 1'b0;
 
                        SRAM_CE_N <= 1'b0;
 
 
 
                        dbin <= 1'b0;
 
                end
 
 
 
                WRITE_PRE1:
 
                begin
 
                        ready <= 1'b1;
 
                end
 
 
 
                WRITE_PRE2:
 
                begin
 
                        ready <= 1'b0;
 
                end
 
 
 
 
 
                WRITE_CYC1:
 
                begin
 
                        ready <= 1'b0;
 
 
 
                        sram_addr_ctr <= sram_addr_nxt;
 
                end
 
 
 
                WRITE_CYC2:
 
                begin
 
                        SRAM_WE_N <= 1'b0;
 
                end
 
 
 
                WRITE_CYC3:
 
                begin
 
                        SRAM_WE_N <= 1'b1;
 
 
 
                        ready <= 1'b1;
 
                end
 
 
 
                WRITE_END:
 
                begin
 
                        ready <= 1'b0;
 
 
 
                        SRAM_WE_N <= 1'b1;
 
                        SRAM_UB_N <= 1'b1;
 
                        SRAM_LB_N <= 1'b1;
 
                        SRAM_CE_N <= 1'b1;
 
                end
 
 
 
 
 
////////////////////////////////////////////////////////////////////////
 
                STOP_STATE:
 
                begin
 
                        stop <= 1'b1;
 
                end
 
 
 
                endcase
 
        end
 
 
 
 
 
endmodule