Subversion Repositories pentevo

Rev

Rev 425 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed | ?url?

  1. // ZX-Evo Base Configuration (c) NedoPC 2008,2009,2010,2011,2012,2013,2014
  2. //
  3. // DRAM controller. performs accesses to DRAM.
  4.  
  5. /*
  6.     This file is part of ZX-Evo Base Configuration firmware.
  7.  
  8.     ZX-Evo Base Configuration firmware is free software:
  9.     you can redistribute it and/or modify it under the terms of
  10.     the GNU General Public License as published by
  11.     the Free Software Foundation, either version 3 of the License, or
  12.     (at your option) any later version.
  13.  
  14.     ZX-Evo Base Configuration firmware is distributed in the hope that
  15.     it will be useful, but WITHOUT ANY WARRANTY; without even
  16.     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  17.     See the GNU General Public License for more details.
  18.  
  19.     You should have received a copy of the GNU General Public License
  20.     along with ZX-Evo Base Configuration firmware.
  21.     If not, see <http://www.gnu.org/licenses/>.
  22. */
  23.  
  24.  
  25. //
  26. //
  27. // state:          | RD1   | RD2   | RD3   | RD4   | WR1   | WR2   | WR3   | WR4   | RFSH1 | RFSH2 | RFSH3 | RFSH4 |
  28. // clk: ___/```\___/```\___/```\___/```\___/```\___/```\___/```\___/```\___/```\___/```\___/```\___/```\___/```\___/```\__
  29. //                 |      READ CYCLE               |      WRITE CYCLE              |      REFRESH CYCLE            |
  30. // ras: ```````````````````\_______________/```````````````\_______________/```````````````````````\_______________/
  31. // cas: ```````````````````````````\_______________/```````````````\_______________/```````\_______________/````````
  32. // ra:                 |  row  | column|               |  row  | column|
  33. // rd:     XXXXXXXXXXXXXXXXXXXXXXXXX<read data read|  write data write data write  |
  34. // rwe:   `````````````````````````````````````````\_______________________________/````````````````````````````````
  35. // req:  __/```````\_______________________/```````\________________________________________________________________
  36. // rnw:  XX/```````\XXXXXXXXXXXXXXXXXXXXXXX\_______/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  37. // cbeg: __________/```````\_______________________/```````\_______________________/```````\_______________________/
  38. // rrdy: __________________________________/```````\________________________________________________________________
  39. // addr: XX< addr  >XXXXXXXXXXXXXXXXXXXXXXX< addr  >XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  40. //wrdata:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX< write >XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  41. //rddata:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX< read  >XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  42. //
  43. // comments:
  44. // rucas_n, rlcas_n, rras0_n, rras1_n, rwe_n could be made 'fast output register'
  45. // ra[] couldn't be such in acex1k, because output registers could be all driven only by
  46. //  single clock polarity (and here they are driven by negative edge, while CAS/RAS by positive)
  47. //
  48. // rst_n is resynced before use and acts as req inhibit. so while in reset, dram regenerates and isn't corrupted
  49.  
  50. `include "../include/tune.v"
  51.  
  52. module dram(
  53.  
  54.         input clk,
  55.         input rst_n, // shut down accesses, remain refresh
  56.  
  57.         output reg [9:0] ra, // to the DRAM pins
  58.         inout     [15:0] rd, // .              .
  59.                              // .              .
  60.         output reg rwe_n,    // .              .
  61.         output reg rucas_n,  // .              .
  62.         output reg rlcas_n,  // .              .
  63.         output reg rras0_n,  // .              .
  64.         output reg rras1_n,  // to the DRAM pins
  65.  
  66.         input [20:0] addr, // access address of 16bit word: addr[0] selects between rras0_n and rras1_n,
  67.                            // addr[10:1] goes to row address, addr[20:11] goes to column address
  68.  
  69.         input req,         // request for read/write cycle
  70.         input rnw,         // READ/nWRITE (=1: read, =0: write)
  71.  
  72.         output reg cbeg,       // cycle begin (any including refresh), can be used for synchronizing
  73.         output reg rrdy,       // Read data ReaDY
  74.  
  75.         output reg [15:0] rddata, // data just read
  76.  
  77.         input  [15:0] wrdata, // data to be written
  78.         input   [1:0] bsel    // positive byte select for write: bsel[0] is for wrdata[7:0], bsel[1] is for wrdata[15:8]
  79.  
  80.  
  81. );
  82.  
  83.         reg [1:0] rst_sync;
  84.         wire reset;
  85.         wire int_req;
  86.  
  87.         reg [20:0] int_addr;
  88.         reg [15:0] int_wrdata;
  89.         reg  [1:0] int_bsel;
  90.  
  91.  
  92.         reg rfsh_alt; // we must alternate chips in refresh cycles to lower total heating
  93.  
  94.  
  95.  
  96.         reg [3:0] state;
  97.         reg [3:0] next_state;
  98.  
  99.         localparam RD1   = 0;
  100.         localparam RD2   = 1;
  101.         localparam RD3   = 2;
  102.         localparam RD4   = 3;
  103.         localparam WR1   = 4;
  104.         localparam WR2   = 5;
  105.         localparam WR3   = 6;
  106.         localparam WR4   = 7;
  107.         localparam RFSH1 = 8;
  108.         localparam RFSH2 = 9;
  109.         localparam RFSH3 = 10;
  110.         localparam RFSH4 = 11;
  111.  
  112.  
  113.  
  114.         initial
  115.         begin
  116.                 state = RFSH1; // for simulation only!
  117.                 rfsh_alt = 1'b0;
  118.         end
  119.  
  120. /*
  121. `ifdef SIMULATE
  122.         always @(posedge clk)
  123.         begin
  124.                 if( req && !rnw && (state==RD4 || state==WR4 || state==RFSH4) )
  125.                 begin
  126.                         $display("written word %x mask %x to address %x",wrdata&{ {8{bsel[1]}}, {8{bsel[0]}} },{ {8{bsel[1]}}, {8{bsel[0]}} },addr);
  127.                 end
  128.         end
  129. `endif
  130. */
  131.  
  132.         always @(posedge clk)
  133.         begin
  134.                 state <= next_state;
  135.         end
  136.  
  137.         always @*
  138.                 case( state )
  139.  
  140.                 RD1:
  141.                         next_state = RD2;
  142.                 RD2:
  143.                         next_state = RD3;
  144.                 RD3:
  145.                         next_state = RD4;
  146.                 RD4:
  147.                         if( !int_req )
  148.                                 next_state = RFSH1;
  149.                         else
  150.                                 next_state = rnw?RD1:WR1;
  151.  
  152.                 WR1:
  153.                         next_state = WR2;
  154.                 WR2:
  155.                         next_state = WR3;
  156.                 WR3:
  157.                         next_state = WR4;
  158.                 WR4:
  159.                         if( !int_req )
  160.                                 next_state = RFSH1;
  161.                         else
  162.                                 next_state = rnw?RD1:WR1;
  163.  
  164.  
  165.                 RFSH1:
  166.                         next_state = RFSH2;
  167.                 RFSH2:
  168.                         next_state = RFSH3;
  169.                 RFSH3:
  170.                         next_state = RFSH4;
  171.                 RFSH4:
  172.                         if( !int_req )
  173.                                 next_state = RFSH1;
  174.                         else
  175.                                 next_state = rnw?RD1:WR1;
  176.  
  177.                 endcase
  178.  
  179.  
  180.         // incoming data latching
  181.         always @(posedge clk)
  182.         begin
  183.                 if( (state==RD4) || (state==WR4) || (state==RFSH4) )
  184.                 begin
  185.                         int_addr   <= addr;
  186.                         int_wrdata <= wrdata;
  187.                         int_bsel   <= bsel;
  188.                 end
  189.         end
  190.  
  191.         // WE control
  192.         always @(posedge clk)
  193.         begin
  194.                 if( (next_state==WR1) || (next_state==WR2) || (next_state==WR3) || (next_state==WR4) )
  195.                         rwe_n <= 1'b0;
  196.                 else
  197.                         rwe_n <= 1'b1;
  198.         end
  199.  
  200.  
  201.         // RAS/CAS sequencing
  202.         always @(posedge clk)
  203.         begin
  204.                 case( state )
  205. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  206. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  207.                 RD1:
  208.                 begin
  209.                         rras0_n <= int_addr[0];
  210.                         rras1_n <= ~int_addr[0];
  211.                 end
  212. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  213.                 RD2:
  214.                 begin
  215.                         rucas_n <= 1'b0;
  216.                         rlcas_n <= 1'b0;
  217.                 end
  218. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  219.                 RD3:
  220.                 begin
  221.                         rras0_n <= 1'b1;
  222.                         rras1_n <= 1'b1;
  223.                 end
  224. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  225.                 RD4:
  226.                 begin
  227.                         rras0_n <= 1'b1;
  228.                         rras1_n <= 1'b1;
  229.                         rucas_n <= 1'b1;
  230.                         rlcas_n <= 1'b1;
  231.                 end
  232. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  233. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  234.                 WR1:
  235.                 begin
  236.                         rras0_n <= int_addr[0];
  237.                         rras1_n <= ~int_addr[0];
  238.                 end
  239. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  240.                 WR2:
  241.                 begin
  242.                         rucas_n <= ~int_bsel[1];
  243.                         rlcas_n <= ~int_bsel[0];
  244.                 end
  245. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  246.                 WR3:
  247.                 begin
  248.                         rras0_n <= 1'b1;
  249.                         rras1_n <= 1'b1;
  250.                 end
  251. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  252.                 WR4:
  253.                 begin
  254.                         rras0_n <= 1'b1;
  255.                         rras1_n <= 1'b1;
  256.                         rucas_n <= 1'b1;
  257.                         rlcas_n <= 1'b1;
  258.                 end
  259. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  260. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  261.                 RFSH1:
  262.                 begin
  263.                         rucas_n <= 1'b0;
  264.                         rlcas_n <= 1'b0;
  265.                 end
  266. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  267.                 RFSH2:
  268.                 begin
  269.                         rras0_n <=  rfsh_alt;
  270.                         rras1_n <= ~rfsh_alt;
  271.  
  272.                         rfsh_alt <= ~rfsh_alt;
  273.                 end
  274. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  275.                 RFSH3:
  276.                 begin
  277.                         rucas_n <= 1'b1;
  278.                         rlcas_n <= 1'b1;
  279.                 end
  280. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  281.                 RFSH4:
  282.                 begin
  283.                         rras0_n <= 1'b1;
  284.                         rras1_n <= 1'b1;
  285.                         rucas_n <= 1'b1;
  286.                         rlcas_n <= 1'b1;
  287.                 end
  288. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  289. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  290.                 endcase
  291.         end
  292.  
  293.  
  294.         // row/column address multiplexing
  295.         always @(negedge clk)
  296.         begin
  297.                 if( (state==RD1) || (state==WR1) )
  298.                         ra <= int_addr[10:1];
  299.                 else
  300.                         ra <= int_addr[20:11];
  301.         end
  302.  
  303.  
  304.         // DRAM data bus control
  305.         assign rd = rwe_n ? 16'hZZZZ : int_wrdata;
  306.  
  307.  
  308.         // read data from DRAM
  309.         always @(posedge clk)
  310.         begin
  311.                 if( state==RD3 )
  312.                         rddata <= rd;
  313.         end
  314.  
  315.  
  316.         // cbeg and rrdy control
  317.         always @(posedge clk)
  318.         begin
  319.                 if( (state==RD4) || (state==WR4) || (state==RFSH4) )
  320.                         cbeg <= 1'b1;
  321.                 else
  322.                         cbeg <= 1'b0;
  323.  
  324.  
  325.             if( state==RD3 )
  326.                 rrdy <= 1'b1;
  327.             else
  328.                 rrdy <= 1'b0;
  329.         end
  330.  
  331.  
  332.         // reset must be synchronous here in order to preserve
  333.         // DRAM state while other modules reset, but we have only
  334.         // asynchronous one globally. so we must re-synchronize it
  335.         // and use it as 'DRAM operation enable'. when in reset,
  336.         // controller ignores req signal and generates only refresh cycles
  337.         always @(posedge clk)
  338.                 rst_sync[1:0] <= { rst_sync[0], ~rst_n };
  339.  
  340.         assign reset = rst_sync[1];
  341.  
  342.         assign int_req = req & (~reset);
  343.  
  344. endmodule
  345.