cmd_encod_linear_wr.v 14.9 KB
Newer Older
1 2 3 4 5 6 7
/*!
 * <b>Module:</b>cmd_encod_linear_wr
 * @file cmd_encod_linear_wr.v
 * @date 2015-01-23  
 * @author Andrey Filippov     
 *
 * @brief Command sequencer generator for writing a sequential  up to 1KB page
8 9
 * single page access, bank and row will not be changed
 *
10 11 12 13
 * @copyright Copyright (c) 2015 Elphel, Inc.
 *
 * <b>License:</b>
 *
14 15 16 17 18 19 20 21 22 23 24 25
 * cmd_encod_linear_wr.v is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 *  cmd_encod_linear_wr.v is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/> .
26 27 28 29 30 31
 *
 * Additional permission under GNU GPL version 3 section 7:
 * If you modify this Program, or any covered work, by linking or combining it
 * with independent modules provided by the FPGA vendor only (this permission
 * does not extend to any 3-rd party modules, "soft cores" or macros) under
 * different license terms solely for the purpose of generating binary "bitstream"
32
 * files and/or simulating the code, the copyright holders of this Program give
33 34
 * you the right to distribute the covered work without those independent modules
 * as long as the source code for them is available from the FPGA vendor free of
Andrey Filippov's avatar
Andrey Filippov committed
35
 * charge, and there is no dependence on any encrypted modules for simulating of
36 37 38
 * the combined code. This permission applies to you if the distributed code
 * contains all the components and scripts required to completely simulate it
 * with at least one of the Free Software programs.
39
 */
40 41 42
`timescale 1ns/1ps

module  cmd_encod_linear_wr #(
Andrey Filippov's avatar
Andrey Filippov committed
43 44
    parameter ADDRESS_NUMBER=       15,
    parameter COLADDR_NUMBER=       10,
45
    parameter NUM_XFER_BITS=         6,    // number of bits to specify transfer length
46
    parameter CMD_PAUSE_BITS=       10,
47 48
    parameter CMD_DONE_BIT=         10, // VDT BUG: CMD_DONE_BIT is used in a function call parameter!
    parameter WSEL=                 1'b0
49
) (
Andrey Filippov's avatar
Andrey Filippov committed
50
    input                        mrst,
51 52 53 54
    input                        clk,
// programming interface
    input                  [2:0] bank_in,     // bank address
    input   [ADDRESS_NUMBER-1:0] row_in,      // memory row
Andrey Filippov's avatar
Andrey Filippov committed
55
    input   [COLADDR_NUMBER-4:0] start_col,   // start memory column (3 LSBs should be 0?)
56
    input    [NUM_XFER_BITS-1:0] num128_in,   // number of 128-bit words to transfer (8*16 bits) - full burst of 8 (0 - full 64)
57
    input                        skip_next_page_in, // do not reset external buffer (continue)    
58
    input                        start,       // start generating commands
59
    output reg            [31:0] enc_cmd,     // encoded command SuppressThisWarning VivadoSynthesis  [Synth 8-3332] Sequential element cmd_encod_linear_wr.enc_cmd_reg[9,6,4:3] is unused and will be removed from module cmd_encod_linear_wr.
60 61 62
    output reg                   enc_wr,      // write encoded command
    output reg                   enc_done     // encoding finished
);
63
    localparam ROM_WIDTH=12;
64 65
    localparam ROM_DEPTH=4;
    
66 67 68 69 70 71 72 73 74 75
    localparam ENC_NOP=         0;
    localparam ENC_BUF_RD=      1;
    localparam ENC_DQS_TOGGLE=  2;
    localparam ENC_DQ_DQS_EN=   3;
    localparam ENC_SEL=         4;
    localparam ENC_ODT=         5;
    localparam ENC_CMD_SHIFT=   6; // [7:6] - command: 0 -= NOP, 1 - WRITE, 2 - PRECHARGE, 3 - ACTIVATE
    localparam ENC_PAUSE_SHIFT= 8; // [9:8] - 2- bit pause (for NOP commandes)
    localparam ENC_PRE_DONE=   10;
    localparam ENC_BUF_PGNEXT= 11;
76 77 78 79 80
    
    localparam ENC_CMD_NOP=      0; // 2-bit locally encoded commands
    localparam ENC_CMD_WRITE=    1;
    localparam ENC_CMD_PRECHARGE=2;
    localparam ENC_CMD_ACTIVATE= 3;
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
    
// read buffer is always at addr 0 and 1,    
    localparam REPEAT_ADDR=        5; // loop here (2-cycle command write)
    localparam PRELAST_WRITE_ADDR='h6; // jump here (from 4) if only 2 writes are needed (are fall from 4 wnen 1 write is left 
    localparam LAST_WRITE_ADDR=   'h8; // jump here (from 4) if only 2 writes are needed (are fall from 4 wnen 1 write is left 
    localparam NO_WRITE_ADDR=     'ha; // jump here (from 4) if only 1 write is needed
    localparam WRITE_ADDR1=     3;
    localparam WRITE_ADDR2=     5;
//    localparam WRITE_ADDR3=     6;
//    localparam WRITE_ADDR4=     8;
    localparam CUT_SINGLE_ADDR= 2; // cut read buffer after this address if only one burst is needed
    localparam CUT_DUAL_ADDR=   4; // cut read buffer after this address if two bursts are needed
    
    
    
96 97 98 99 100 101 102
    
    localparam CMD_NOP=      0; // 3-bit normal memory RCW commands (positive logic)
    localparam CMD_WRITE=    3;
    localparam CMD_PRECHARGE=5;
    localparam CMD_ACTIVATE= 4;
    
    reg   [ADDRESS_NUMBER-1:0] row;     // memory row
Andrey Filippov's avatar
Andrey Filippov committed
103
    reg   [COLADDR_NUMBER-4:0] col;     // start memory column (3 LSBs should be 0?) // VDT BUG: col is used as a function call parameter!
104
    reg                  [2:0] bank;    // memory bank;
105 106
    reg      [NUM_XFER_BITS:0] num128;  // number of 128-bit words to transfer
    reg                        skip_next_page;
107 108
    
    reg                        gen_run;
109
//    reg                        gen_run_d;
110 111
    reg        [ROM_DEPTH-1:0] gen_addr; // will overrun as stop comes from ROM
    
112
    reg        [ROM_WIDTH-1:0] rom_r; // SuppressThisWarning VivadoSynthesis: [Synth 8-3332] Sequential element cmd_encod_linear_wr.rom_r_reg[8] is unused and will be removed from module cmd_encod_linear_wr.
113 114 115 116
    wire                       pre_done;
    wire                 [1:0] rom_cmd;
    wire                 [1:0] rom_skip;
    wire                 [2:0] full_cmd;
117
//    reg                        done;
118
    reg                        start_d;
119
    wire                      next_zero_w= single_write?((gen_addr==CUT_SINGLE_ADDR)?1:0):(dual_write?(gen_addr==CUT_DUAL_ADDR):0);
120
    reg                       cut_buf_rd;
121 122 123 124
    reg                       single_write; // only one burst has to be written
    reg                       dual_write;   // Two bursts have to be written
    reg                       few_write;    //write 1,2 or 3 bursts
    wire                      write_addr_w;   // gen_addr that generates write commands
125
    reg       [ROM_DEPTH-1:0] jump_gen_addr; // will overrun as stop comes from ROM SuppressThisWarning VivadoSynthesis: [Synth 8-3332] Sequential element cmd_encod_linear_wr.jump_gen_addr_reg[0] is unused and will be removed from module cmd_encod_linear_wr.
126 127 128 129 130

    assign     pre_done=rom_r[ENC_PRE_DONE] && gen_run;
    assign     rom_cmd=  rom_r[ENC_CMD_SHIFT+:2];
    assign     rom_skip= rom_r[ENC_PAUSE_SHIFT+:2];
    assign     full_cmd= rom_cmd[1]?(rom_cmd[0]?CMD_ACTIVATE:CMD_PRECHARGE):(rom_cmd[0]?CMD_WRITE:CMD_NOP);
131
// prepare jump address? and bufrd during 2,3 
132
    assign     write_addr_w= (gen_addr==WRITE_ADDR1) || (gen_addr==WRITE_ADDR2); // do not need to update after WRITE_ADDR2
133 134 135 136 137
// make num128 7-bits to accommodate 64!
    always @ (posedge clk) begin
        start_d <= start;
        cut_buf_rd <= rom_r[ENC_BUF_RD] && (cut_buf_rd || next_zero_w);
    end    
Andrey Filippov's avatar
Andrey Filippov committed
138
    always @ (posedge clk) begin
139

Andrey Filippov's avatar
Andrey Filippov committed
140
        if      (mrst)     gen_run <= 0;
141 142 143
        else if (start)    gen_run<= 1;
        else if (pre_done) gen_run<= 0;
        
Andrey Filippov's avatar
Andrey Filippov committed
144
        if      (mrst)                                                     gen_addr <= 0;
145 146
        else if (!start && !gen_run)                                       gen_addr <= 0;
        else if ((gen_addr==(REPEAT_ADDR-1)) && few_write)                 gen_addr <= jump_gen_addr;
Andrey Filippov's avatar
Andrey Filippov committed
147
        else if ((gen_addr !=REPEAT_ADDR) || (num128[NUM_XFER_BITS:2]==0)) gen_addr <= gen_addr+1; // not in a loop
Andrey Filippov's avatar
Andrey Filippov committed
148 149

//counting loops        
Andrey Filippov's avatar
Andrey Filippov committed
150
        if      (mrst)         num128 <= 0;
151 152 153 154
        else if (start)        num128 <= {(num128_in==0)?1'b1:1'b0,num128_in};
        else if (!gen_run)     num128 <= 0; //
        else if (write_addr_w) num128 <= num128 -1;
        
Andrey Filippov's avatar
Andrey Filippov committed
155
        if      (mrst)        single_write <= 0;
156 157
        else if (start_d)    single_write <= (num128[NUM_XFER_BITS:1]==0); // could not be 0
        
Andrey Filippov's avatar
Andrey Filippov committed
158
        if      (mrst)        dual_write <= 0;
159 160
        else if (start_d)    dual_write <= (num128==2);

Andrey Filippov's avatar
Andrey Filippov committed
161
        if      (mrst)        few_write <= 0;
162 163
        else if (start_d)    few_write <=(num128[NUM_XFER_BITS:2]==0); // (0,)1,2 or3
        
Andrey Filippov's avatar
Andrey Filippov committed
164 165
        if (mrst) jump_gen_addr <= 0;
        else      jump_gen_addr <= single_write ? NO_WRITE_ADDR : (dual_write ? LAST_WRITE_ADDR : PRELAST_WRITE_ADDR);
166
        
167 168 169 170 171
    end
    
    always @ (posedge clk) if (start) begin
        row<=row_in;
        bank <= bank_in;
172
        skip_next_page <= skip_next_page_in;
173
    end
Andrey Filippov's avatar
Andrey Filippov committed
174 175 176 177 178

    always @ (posedge clk) begin
        if (start) col <= start_col;
        else if (rom_cmd==ENC_CMD_WRITE) col <= col+1;
    end
179 180
    
    // ROM-based (registered output) encoded sequence
181
    // TODO: Remove last ENC_BUF_RD
Andrey Filippov's avatar
Andrey Filippov committed
182 183
    always @ (posedge clk) begin
        if (mrst)          rom_r <= 0;
184
        else case (gen_addr)
185 186 187
            4'h0: rom_r <= (ENC_CMD_ACTIVATE <<  ENC_CMD_SHIFT) | (1 << ENC_BUF_RD);// | (1 << ENC_NOP); 
            4'h1: rom_r <= (ENC_CMD_NOP <<       ENC_CMD_SHIFT) | (1 << ENC_BUF_RD);
            4'h2: rom_r <= (ENC_CMD_NOP <<       ENC_CMD_SHIFT) | (1 << ENC_BUF_RD);
188 189 190
            4'h3: rom_r <= (ENC_CMD_WRITE <<     ENC_CMD_SHIFT) | (1 << ENC_BUF_RD) | (WSEL << ENC_SEL)         | (1 << ENC_ODT);   // single cycle
//          4'h4: rom_r <= (ENC_CMD_NOP <<       ENC_CMD_SHIFT) | (1 << ENC_BUF_RD) | (1 << ENC_DQ_DQS_EN)   | (1 << ENC_ODT);  // single cycle
            4'h4: rom_r <= (ENC_CMD_NOP <<       ENC_CMD_SHIFT) | (1 << ENC_BUF_RD)                  | (1 << ENC_ODT);  // single cycle
191
// next may loop            
192 193 194 195
            4'h5: rom_r <= (ENC_CMD_WRITE <<     ENC_CMD_SHIFT) | (1 << ENC_NOP) | (1 << ENC_BUF_RD) | (1 << ENC_DQS_TOGGLE) | (1 << ENC_DQ_DQS_EN) | (WSEL << ENC_SEL) | (1 << ENC_ODT);  // dual cycle 
            4'h6: rom_r <= (ENC_CMD_WRITE <<     ENC_CMD_SHIFT)                  | (1 << ENC_BUF_RD) | (1 << ENC_DQS_TOGGLE) | (1 << ENC_DQ_DQS_EN) | (WSEL << ENC_SEL) | (1 << ENC_ODT);  // dual cycle 
            4'h7: rom_r <= (ENC_CMD_NOP <<       ENC_CMD_SHIFT)                                      | (1 << ENC_DQS_TOGGLE) | (1 << ENC_DQ_DQS_EN) | (WSEL << ENC_SEL) | (1 << ENC_ODT);
            4'h8: rom_r <= (ENC_CMD_WRITE <<     ENC_CMD_SHIFT)                                      | (1 << ENC_DQS_TOGGLE) | (1 << ENC_DQ_DQS_EN) | (WSEL << ENC_SEL) | (1 << ENC_ODT);  // dual cycle 
196 197 198 199 200 201
            4'h9: rom_r <= (ENC_CMD_NOP <<       ENC_CMD_SHIFT)                                      | (1 << ENC_DQS_TOGGLE) | (1 << ENC_DQ_DQS_EN) | (1 << ENC_ODT);
            4'ha: rom_r <= (ENC_CMD_NOP <<       ENC_CMD_SHIFT) | (2 << ENC_PAUSE_SHIFT)             | (1 << ENC_DQS_TOGGLE) | (1 << ENC_DQ_DQS_EN) | (1 << ENC_ODT);
            4'hb: rom_r <= (ENC_CMD_NOP <<       ENC_CMD_SHIFT) | (2 << ENC_PAUSE_SHIFT);
            4'hc: rom_r <= (ENC_CMD_PRECHARGE << ENC_CMD_SHIFT) |      (1 << ENC_BUF_PGNEXT);
            4'hd: rom_r <= (ENC_CMD_NOP <<       ENC_CMD_SHIFT) | (2 << ENC_PAUSE_SHIFT);
            4'he: rom_r <= (ENC_CMD_NOP <<       ENC_CMD_SHIFT) | (1 << ENC_PRE_DONE);
202
            default:rom_r <= 0;
203 204
       endcase
    end
Andrey Filippov's avatar
Andrey Filippov committed
205
    always @ (posedge clk) begin
206
        
Andrey Filippov's avatar
Andrey Filippov committed
207
        if (mrst)          enc_wr <= 0;
208
        else               enc_wr <= gen_run; // || gen_run_d;
209
        
Andrey Filippov's avatar
Andrey Filippov committed
210 211 212
        if (mrst)           enc_done <= 0;
//        else              enc_done <= enc_wr || !gen_run_d;
        else                enc_done <= enc_wr && !gen_run; // !gen_run_d;
213
        
Andrey Filippov's avatar
Andrey Filippov committed
214
        if (mrst)         enc_cmd <= 0;
215 216
        else if (gen_run) begin
          if (rom_cmd==0) enc_cmd <= func_encode_skip ( // encode pause
217
            {{CMD_PAUSE_BITS-2{1'b0}},rom_skip[1:0]}, // skip;   // number of extra cycles to skip (and keep all the other outputs)
218
            pre_done, // done,                                     // end of sequence 
219 220 221 222 223 224 225 226 227
            bank[2:0],                                // bank (here OK to be any)
            rom_r[ENC_ODT],          //   odt_en;     // enable ODT
            1'b0,                    //   cke;        // disable CKE
            rom_r[ENC_SEL],          //   sel;        // first/second half-cycle, other will be nop (cke+odt applicable to both)
            rom_r[ENC_DQ_DQS_EN],    //   dq_en;      // enable (not tristate) DQ  lines (internal timing sequencer for 0->1 and 1->0)
            rom_r[ENC_DQ_DQS_EN],    //   dqs_en;     // enable (not tristate) DQS lines (internal timing sequencer for 0->1 and 1->0)
            rom_r[ENC_DQS_TOGGLE],   //   dqs_toggle; // enable toggle DQS according to the pattern
            1'b0,                    //   dci;        // DCI disable, both DQ and DQS lines (internal logic and timing sequencer for 0->1 and 1->0)
            1'b0,                    //   buf_wr;     // connect to external buffer (but only if not paused)
228
            rom_r[ENC_BUF_RD] && !cut_buf_rd, //buf_rd;// connect to external buffer (but only if not paused)
229
            rom_r[ENC_BUF_PGNEXT] && !skip_next_page);     //   buf_rst;    // connect to external buffer (but only if not paused)
230
          else  enc_cmd <= func_encode_cmd ( // encode non-NOP command
231 232
            rom_cmd[1]?
                    row:
233
                    {{ADDRESS_NUMBER-COLADDR_NUMBER{1'b0}},col[COLADDR_NUMBER-4:0],3'b0}, //  [14:0] addr;       // 15-bit row/column address
234 235 236 237 238 239 240 241 242 243
            bank[2:0],                                // bank (here OK to be any)
            full_cmd[2:0],           //   rcw;        // RAS/CAS/WE, positive logic
            rom_r[ENC_ODT],          //   odt_en;     // enable ODT
            1'b0,                    //   cke;        // disable CKE
            rom_r[ENC_SEL],          //   sel;        // first/second half-cycle, other will be nop (cke+odt applicable to both)
            rom_r[ENC_DQ_DQS_EN],    //   dq_en;      // enable (not tristate) DQ  lines (internal timing sequencer for 0->1 and 1->0)
            rom_r[ENC_DQ_DQS_EN],    //   dqs_en;     // enable (not tristate) DQS lines (internal timing sequencer for 0->1 and 1->0)
            rom_r[ENC_DQS_TOGGLE],   //   dqs_toggle; // enable toggle DQS according to the pattern
            1'b0,                    //   dci;        // DCI disable, both DQ and DQS lines (internal logic and timing sequencer for 0->1 and 1->0)
            1'b0,                    //   buf_wr;     // connect to external buffer (but only if not paused)
244
            rom_r[ENC_BUF_RD] && !cut_buf_rd, //buf_rd;// connect to external buffer (but only if not paused)     
245
            rom_r[ENC_NOP],          //   nop;        // add NOP after the current command, keep other data
246
            rom_r[ENC_BUF_PGNEXT] && !skip_next_page);     //   buf_rst;    // connect to external buffer (but only if not paused)
247
        end
248 249 250 251
    end    
    

// move to include?
252
`include "includes/x393_mcontr_encode_cmd.vh" 
253 254
endmodule