|  | @@ -45,7 +45,8 @@ module sdram
 | 
	
		
			
				|  |  |     //    tRFC	    60 ns       6       10    REFRESH to ACTIVE
 | 
	
		
			
				|  |  |     //    tRP        18 ns       2        3    PRECHARGE to ACTIVE/REFRESH
 | 
	
		
			
				|  |  |     //    tRAS	    42 ns       5        7    ACTIVE to PRECHARGE
 | 
	
		
			
				|  |  | -   //    tRC        60 ns       6       10    ACTIVE to ACTIVE
 | 
	
		
			
				|  |  | +   //    tRC        60 ns       6       10    ACTIVE to ACTIVE (same bank)
 | 
	
		
			
				|  |  | +   //    tRRD       12 ns       2        2    ACTICE to ACTIVE (different bank)
 | 
	
		
			
				|  |  |     //    tWR        12 ns       2        2    Last write data to PRECHARGE
 | 
	
		
			
				|  |  |     //    tMRD                   2	 2    MODE REGISTER to ACTIVE/REFRESH
 | 
	
		
			
				|  |  |     //
 | 
	
	
		
			
				|  | @@ -59,53 +60,54 @@ module sdram
 | 
	
		
			
				|  |  |     t_rp		=  3,
 | 
	
		
			
				|  |  |     t_ras	=  7,
 | 
	
		
			
				|  |  |     t_rc		= 10,
 | 
	
		
			
				|  |  | +   t_rrd        =  2,
 | 
	
		
			
				|  |  |     t_wr		=  2,
 | 
	
		
			
				|  |  |     t_mrd	=  2,
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -   t_refi_lg2	=  9,	// 512 cycles (extra conservative)
 | 
	
		
			
				|  |  | +   t_refi_lg2	= 10,	// 1024 cycles
 | 
	
		
			
				|  |  |     t_p_lg2	= 15,	// 32768 cycles
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -   burst_lg2	=  3	// Burst length on port 1
 | 
	
		
			
				|  |  | +   burst_lg2	=  1	// Burst length on port 1
 | 
	
		
			
				|  |  |  )
 | 
	
		
			
				|  |  |  (
 | 
	
		
			
				|  |  |  	      // Reset and clock
 | 
	
		
			
				|  |  | -	      input		      rst_n,
 | 
	
		
			
				|  |  | -	      input		      clk,
 | 
	
		
			
				|  |  | +	      input			  rst_n,
 | 
	
		
			
				|  |  | +	      input			  clk,
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	      // SDRAM hardware interface
 | 
	
		
			
				|  |  | -	      output		      sr_clk, // SDRAM clock output buffer
 | 
	
		
			
				|  |  | -	      output		      sr_cke, // SDRAM clock enable
 | 
	
		
			
				|  |  | -	      output		      sr_cs_n, // SDRAM CS#
 | 
	
		
			
				|  |  | -	      output		      sr_ras_n, // SDRAM RAS#
 | 
	
		
			
				|  |  | -	      output		      sr_cas_n, // SDRAM CAS#
 | 
	
		
			
				|  |  | -	      output		      sr_we_n, // SDRAM WE#
 | 
	
		
			
				|  |  | -	      output [1:0]	      sr_dqm, // SDRAM DQM (per byte)
 | 
	
		
			
				|  |  | -	      output [1:0]	      sr_ba, // SDRAM bank selects
 | 
	
		
			
				|  |  | -	      output [12:0]	      sr_a, // SDRAM address bus
 | 
	
		
			
				|  |  | -	      inout [15:0]	      sr_dq, // SDRAM data bus
 | 
	
		
			
				|  |  | +	      output			  sr_clk, // SDRAM clock output buffer
 | 
	
		
			
				|  |  | +	      output			  sr_cke, // SDRAM clock enable
 | 
	
		
			
				|  |  | +	      output			  sr_cs_n, // SDRAM CS#
 | 
	
		
			
				|  |  | +	      output			  sr_ras_n, // SDRAM RAS#
 | 
	
		
			
				|  |  | +	      output			  sr_cas_n, // SDRAM CAS#
 | 
	
		
			
				|  |  | +	      output			  sr_we_n, // SDRAM WE#
 | 
	
		
			
				|  |  | +	      output [1:0]		  sr_dqm, // SDRAM DQM (per byte)
 | 
	
		
			
				|  |  | +	      output [1:0]		  sr_ba, // SDRAM bank selects
 | 
	
		
			
				|  |  | +	      output [12:0]		  sr_a, // SDRAM address bus
 | 
	
		
			
				|  |  | +	      inout [15:0]		  sr_dq, // SDRAM data bus
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	      // Port 0: single byte, high priority
 | 
	
		
			
				|  |  | -	      input [24:0]	      a0, // Address, must be stable until ack
 | 
	
		
			
				|  |  | +	      input [24:0]		  a0, // Address, must be stable until ack
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	      output [7:0]	      rd0, // Data from SDRAM
 | 
	
		
			
				|  |  | -	      input		      rrq0, // Read request
 | 
	
		
			
				|  |  | -	      output [t_rcd+t_cl+1:0] rack0, // Read ack
 | 
	
		
			
				|  |  | +	      output reg [7:0]		  rd0, // Data from SDRAM
 | 
	
		
			
				|  |  | +	      input			  rrq0, // Read request
 | 
	
		
			
				|  |  | +	      output reg [t_rcd+t_cl+3:0] rack0, // Read ack
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	      input [7:0]	      wd0, // Data to SDRAM
 | 
	
		
			
				|  |  | -	      input		      wrq0, // Write request
 | 
	
		
			
				|  |  | -	      output [t_rcd:0]	      wack0, // Write ack
 | 
	
		
			
				|  |  | +	      input [7:0]		  wd0, // Data to SDRAM
 | 
	
		
			
				|  |  | +	      input			  wrq0, // Write request
 | 
	
		
			
				|  |  | +	      output reg		  wack0, // Write ack (data latched)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	      // Port 1
 | 
	
		
			
				|  |  | -	      input [24:1]	      a1,
 | 
	
		
			
				|  |  | +	      input [24:2]		  a1,
 | 
	
		
			
				|  |  | +	      input [7:0]		  be1, // Write byte enable
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	      output [15:0]	      rd1,
 | 
	
		
			
				|  |  | -	      input		      rrq1,
 | 
	
		
			
				|  |  | -	      output [t_rcd+t_cl+1:0] rack1,
 | 
	
		
			
				|  |  | +	      output reg [31:0]		  rd1,
 | 
	
		
			
				|  |  | +	      input			  rrq1,
 | 
	
		
			
				|  |  | +	      output reg [t_rcd+t_cl+3:0] rack1,
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	      input [15:0]	      wd1,
 | 
	
		
			
				|  |  | -	      input [1:0]	      wbe1, // Write byte enable
 | 
	
		
			
				|  |  | -	      input		      wrq1,
 | 
	
		
			
				|  |  | -	      output [t_rcd:0]	      wack1
 | 
	
		
			
				|  |  | +	      input [31:0]		  wd1,
 | 
	
		
			
				|  |  | +	      input			  wrq1,
 | 
	
		
			
				|  |  | +	      output reg		  wack1
 | 
	
		
			
				|  |  |  	      );
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |     // Mode register data
 | 
	
	
		
			
				|  | @@ -142,7 +144,7 @@ module sdram
 | 
	
		
			
				|  |  |     localparam	cmd_ref  = 5'b1_0001;  // AUTO REFRESH
 | 
	
		
			
				|  |  |     localparam	cmd_mrd  = 5'b0_0000;  // LOAD MODE REGISTER
 | 
	
		
			
				|  |  |     reg [4:0]	dram_cmd;
 | 
	
		
			
				|  |  | -   wire		is_rfsh = dram_cmd[4];
 | 
	
		
			
				|  |  | +   wire		is_rfsh  = dram_cmd[4];
 | 
	
		
			
				|  |  |     assign	sr_cs_n  = dram_cmd[3];
 | 
	
		
			
				|  |  |     assign	sr_ras_n = dram_cmd[2];
 | 
	
		
			
				|  |  |     assign	sr_cas_n = dram_cmd[1];
 | 
	
	
		
			
				|  | @@ -177,30 +179,21 @@ module sdram
 | 
	
		
			
				|  |  |     reg			    dram_d_en; // Drive data out
 | 
	
		
			
				|  |  |     assign		    sr_dq = dram_d_en ? dram_d : 16'hzzzz;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -   // Input register for SDRAM data; a single register to make it
 | 
	
		
			
				|  |  | -   // possible to put it in the I/O register
 | 
	
		
			
				|  |  | +   // Input register for SDRAM data
 | 
	
		
			
				|  |  |     reg [15:0]		    dram_q;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -   // Port 0 output signals
 | 
	
		
			
				|  |  | -   assign                   rd0 = a0[0] ? dram_q[15:8] : dram_q[7:0];
 | 
	
		
			
				|  |  | -   reg [t_rcd+t_cl+1:0]     rack0_q;
 | 
	
		
			
				|  |  | -   assign                   rack0 = rack0_q;
 | 
	
		
			
				|  |  | -   reg [t_rcd:0]	    wack0_q;
 | 
	
		
			
				|  |  | -   assign                   wack0 = wack0_q;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -   // Port 1 output signals
 | 
	
		
			
				|  |  | -   assign                   rd1 = dram_q;
 | 
	
		
			
				|  |  | -   reg [t_rcd+t_cl+1:0]	    rack1_q;
 | 
	
		
			
				|  |  | -   assign                   rack1 = rack1_q;
 | 
	
		
			
				|  |  | -   reg [t_rcd:0]	    wack1_q;
 | 
	
		
			
				|  |  | -   assign                   wack1 = wack1_q;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |     // State machine and counters
 | 
	
		
			
				|  |  | -   reg [t_refi_lg2:0]	    rfsh_ctr;  // Refresh timer
 | 
	
		
			
				|  |  | -   reg [t_p_lg2:t_refi_lg2] init_ctr;  // Reset to init counter
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -   // XXX: compute the necessary width of this field elsewhere
 | 
	
		
			
				|  |  | -   reg [4:0]	            op_cycle;	// Cycles into the current operation
 | 
	
		
			
				|  |  | +   reg [t_refi_lg2-2:0]	      rfsh_ctr;  // Refresh timer
 | 
	
		
			
				|  |  | +   wire			      rfsh_ctr_msb = rfsh_ctr[t_refi_lg2-2];
 | 
	
		
			
				|  |  | +   reg			      rfsh_ctr_last_msb;
 | 
	
		
			
				|  |  | +   wire			      rfsh_tick = rfsh_ctr_last_msb & ~rfsh_ctr_msb;
 | 
	
		
			
				|  |  | +   reg [t_p_lg2:t_refi_lg2-1] init_ctr;  // Reset to init counter
 | 
	
		
			
				|  |  | +   reg [1:0]		      rfsh_prio; // Refresh priority
 | 
	
		
			
				|  |  | +					 // Bit 0 - refresh if opportune
 | 
	
		
			
				|  |  | +					 // Bit 1 - refresh urgent
 | 
	
		
			
				|  |  | +   reg			      port;	 // Port being serviced
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +   reg [3:0]		      op_cycle;	// Cycles into the current operation
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |     // The actual values are unimportant; the compiler will optimize
 | 
	
		
			
				|  |  |     // the state machine implementation.
 | 
	
	
		
			
				|  | @@ -209,33 +202,60 @@ module sdram
 | 
	
		
			
				|  |  |  	 st_init,		// 1st refresh during initialization
 | 
	
		
			
				|  |  |  	 st_idle,		// Idle state: all banks precharged
 | 
	
		
			
				|  |  |  	 st_rfsh,
 | 
	
		
			
				|  |  | -	 st_p0_rd,
 | 
	
		
			
				|  |  | -	 st_p0_wr,
 | 
	
		
			
				|  |  | -	 st_p1_rd,
 | 
	
		
			
				|  |  | -	 st_p1_wr
 | 
	
		
			
				|  |  | +	 st_rd,
 | 
	
		
			
				|  |  | +	 st_wr
 | 
	
		
			
				|  |  |     } state_t;
 | 
	
		
			
				|  |  |     state_t state = st_reset;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |     always @(posedge clk or negedge rst_n)
 | 
	
		
			
				|  |  |       if (~rst_n)
 | 
	
		
			
				|  |  |         begin
 | 
	
		
			
				|  |  | -	  rfsh_ctr <= 1'b0;
 | 
	
		
			
				|  |  | -	  init_ctr <= 1'b0;
 | 
	
		
			
				|  |  | +	  rfsh_ctr  <= 1'b0;
 | 
	
		
			
				|  |  | +	  init_ctr  <= 1'b0;
 | 
	
		
			
				|  |  | +	  rfsh_prio <= 2'b00;
 | 
	
		
			
				|  |  |         end
 | 
	
		
			
				|  |  |       else
 | 
	
		
			
				|  |  |         begin
 | 
	
		
			
				|  |  | -	  rfsh_ctr <= is_rfsh ? 1'b0 : rfsh_ctr + 1'b1;
 | 
	
		
			
				|  |  | +	  rfsh_ctr          <= rfsh_ctr + 1'b1;
 | 
	
		
			
				|  |  | +	  rfsh_ctr_last_msb <= rfsh_ctr_msb;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	  // Refresh priority management
 | 
	
		
			
				|  |  | +	  if (is_rfsh)
 | 
	
		
			
				|  |  | +	    rfsh_prio <= 2'b00; // This is a refresh cycle
 | 
	
		
			
				|  |  | +	  else if (rfsh_tick)
 | 
	
		
			
				|  |  | +	    rfsh_prio <= { rfsh_prio[0], 1'b1 };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	  // The refresh counter is also used as a prescaler
 | 
	
		
			
				|  |  |  	  // for the initialization counter.
 | 
	
		
			
				|  |  | -	  if (init_ctr[t_refi_lg2] ^ rfsh_ctr[t_refi_lg2])
 | 
	
		
			
				|  |  | +	  // Note that means init_ctr is two cycles "behind"
 | 
	
		
			
				|  |  | +	  // rfsh_ctr; this is totally fine.
 | 
	
		
			
				|  |  | +	  init_ctr <= init_ctr + rfsh_tick;
 | 
	
		
			
				|  |  | +       end // else: !if(~rst_n)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +   // Handle bank wraparound
 | 
	
		
			
				|  |  | +   reg			    last_dword; // This is the last dword in this bank
 | 
	
		
			
				|  |  | +   reg [14:0]		    next_bank;  // Row:bank for the next bank
 | 
	
		
			
				|  |  | +   reg [11:2]		    col_addr;	// Current bank:column
 | 
	
		
			
				|  |  | +   reg			    latch_next_bank;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +   always @(negedge rst_n or posedge clk)
 | 
	
		
			
				|  |  | +     if (~rst_n)
 | 
	
		
			
				|  |  | +       begin
 | 
	
		
			
				|  |  | +	  latch_next_bank <= 1'b0;
 | 
	
		
			
				|  |  | +       end
 | 
	
		
			
				|  |  | +     else
 | 
	
		
			
				|  |  | +       begin
 | 
	
		
			
				|  |  | +	  latch_next_bank <= st_idle;
 | 
	
		
			
				|  |  | +	  if (latch_next_bank)
 | 
	
		
			
				|  |  |  	    begin
 | 
	
		
			
				|  |  | -	       init_ctr[t_p_lg2:t_refi_lg2+1]
 | 
	
		
			
				|  |  | -		 <= init_ctr[t_p_lg2:t_refi_lg2+1] + 1'b1;
 | 
	
		
			
				|  |  | -	       init_ctr[t_refi_lg2] <= rfsh_ctr[t_refi_lg2];
 | 
	
		
			
				|  |  | +	       next_bank <= { dram_a, dram_ba } + 1'b1;
 | 
	
		
			
				|  |  | +	       last_dword <= &col_addr[9:2]; // last dword in bank?
 | 
	
		
			
				|  |  |  	    end
 | 
	
		
			
				|  |  |         end // else: !if(~rst_n)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +   reg [31:0] wdata_q;
 | 
	
		
			
				|  |  | +   reg [ 6:0] be_q;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |     //
 | 
	
		
			
				|  |  |     // Careful with the timing here... there is one cycle between
 | 
	
		
			
				|  |  |     // registers and wires, and the DRAM observes the clock 1/2
 | 
	
	
		
			
				|  | @@ -246,38 +266,38 @@ module sdram
 | 
	
		
			
				|  |  |         begin
 | 
	
		
			
				|  |  |  	  dram_cke      <= 1'b0;
 | 
	
		
			
				|  |  |  	  dram_cmd      <= cmd_desl;
 | 
	
		
			
				|  |  | -	  dram_a        <= 13'h0000;
 | 
	
		
			
				|  |  | -	  dram_ba       <= 2'b00;
 | 
	
		
			
				|  |  | +	  dram_a        <= 13'hxxxx;
 | 
	
		
			
				|  |  | +	  dram_ba       <= 2'bxx;
 | 
	
		
			
				|  |  |  	  dram_dqm      <= 2'b00;
 | 
	
		
			
				|  |  | -	  dram_d        <= 16'h0000;
 | 
	
		
			
				|  |  | +	  dram_d        <= 16'hxxxx;
 | 
	
		
			
				|  |  |  	  dram_d_en     <= 1'b1; // Don't float except during read
 | 
	
		
			
				|  |  |  	  op_cycle      <= 1'b0;
 | 
	
		
			
				|  |  |  	  state         <= st_reset;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	  rack0_q       <= 1'b0;
 | 
	
		
			
				|  |  | -	  wack0_q       <= 1'b0;
 | 
	
		
			
				|  |  | -	  rack1_q       <= 1'b0;
 | 
	
		
			
				|  |  | -	  wack1_q       <= 1'b0;
 | 
	
		
			
				|  |  | +	  rack0       <= 1'b0;
 | 
	
		
			
				|  |  | +	  wack0       <= 1'b0;
 | 
	
		
			
				|  |  | +	  rack1       <= 1'b0;
 | 
	
		
			
				|  |  | +	  wack1       <= 1'b0;
 | 
	
		
			
				|  |  |         end
 | 
	
		
			
				|  |  |       else
 | 
	
		
			
				|  |  |         begin
 | 
	
		
			
				|  |  |  	  dram_cke <= 1'b1;	// Always true once out of reset
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	  // Default values
 | 
	
		
			
				|  |  | -	  dram_a        <= 13'h0000;
 | 
	
		
			
				|  |  | -	  dram_ba       <= 2'b00;
 | 
	
		
			
				|  |  | +	  dram_ba       <= 2'bxx;
 | 
	
		
			
				|  |  |  	  dram_dqm      <= 2'b11;
 | 
	
		
			
				|  |  | -	  dram_d        <= 16'h0000;
 | 
	
		
			
				|  |  | +	  dram_d        <= 16'hxxxx;
 | 
	
		
			
				|  |  | +	  dram_cmd      <= cmd_nop;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	  rack0_q       <= 1'b0;
 | 
	
		
			
				|  |  | -	  wack0_q       <= 1'b0;
 | 
	
		
			
				|  |  | -	  rack1_q       <= 1'b0;
 | 
	
		
			
				|  |  | -	  wack1_q       <= 1'b0;
 | 
	
		
			
				|  |  | +	  rack0		<= rack0 >> 1;
 | 
	
		
			
				|  |  | +	  wack0         <= 1'b0;
 | 
	
		
			
				|  |  | +	  rack1		<= rack1 >> 1;
 | 
	
		
			
				|  |  | +	  wack1         <= 1'b0;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	  dram_d_en     <= 1'b1; // Don't float except during read
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	  if (state == st_reset || state == st_idle)
 | 
	
		
			
				|  |  | -	    op_cycle <= 1'b1;	// == 0 + 1
 | 
	
		
			
				|  |  | +	    op_cycle <= 1'b0;
 | 
	
		
			
				|  |  |  	  else
 | 
	
		
			
				|  |  |  	    op_cycle <= op_cycle + 1'b1;
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -294,16 +314,18 @@ module sdram
 | 
	
		
			
				|  |  |  	      end
 | 
	
		
			
				|  |  |  	    st_init:
 | 
	
		
			
				|  |  |  	      begin
 | 
	
		
			
				|  |  | -		 if ( op_cycle == t_rp || op_cycle == t_rp + t_rfc )
 | 
	
		
			
				|  |  | +		 // Add 3 to the count to account for skew between rfsh_ctr
 | 
	
		
			
				|  |  | +		 // and init_ctr
 | 
	
		
			
				|  |  | +		 if ( rfsh_ctr[4:0] == t_rp+3 || rfsh_ctr[4:0] == t_rp+t_rfc+3 )
 | 
	
		
			
				|  |  |  		   begin
 | 
	
		
			
				|  |  |  		      dram_cmd   <= cmd_ref;
 | 
	
		
			
				|  |  |  		   end
 | 
	
		
			
				|  |  | -		 if ( op_cycle == t_rp + t_rfc*2 )
 | 
	
		
			
				|  |  | +		 if ( rfsh_ctr[4:0] == t_rp+t_rfc*2+3 )
 | 
	
		
			
				|  |  |  		   begin
 | 
	
		
			
				|  |  |  		      dram_cmd   <= cmd_mrd;
 | 
	
		
			
				|  |  |  		      dram_a     <= mrd_val;
 | 
	
		
			
				|  |  |  		   end
 | 
	
		
			
				|  |  | -		 if ( op_cycle >= t_rp + t_rfc*2 + t_mrd - 1 )
 | 
	
		
			
				|  |  | +		 if ( rfsh_ctr[4:0] >= t_rp+t_rfc*2+t_mrd-1+3 )
 | 
	
		
			
				|  |  |  		   state <= st_idle;
 | 
	
		
			
				|  |  |  	      end // case: st_init
 | 
	
		
			
				|  |  |  	    st_idle:
 | 
	
	
		
			
				|  | @@ -315,42 +337,50 @@ module sdram
 | 
	
		
			
				|  |  |  		 // is started opportunistically if nothing is
 | 
	
		
			
				|  |  |  		 // pending and the refresh counter is no less than
 | 
	
		
			
				|  |  |  		 // half expired.
 | 
	
		
			
				|  |  | -		 casez ( {rrq0|wrq0, rrq1|wrq1, rfsh_ctr[t_refi_lg2:t_refi_lg2-1]} )
 | 
	
		
			
				|  |  | -		   4'b1zzz:
 | 
	
		
			
				|  |  | +		 casez ( {rrq0|wrq0, rrq1|wrq1, rfsh_prio} )
 | 
	
		
			
				|  |  | +		   4'b1???:
 | 
	
		
			
				|  |  |  		     begin
 | 
	
		
			
				|  |  |  			// Begin port 0 transaction
 | 
	
		
			
				|  |  |  			dram_cmd    <= cmd_act;
 | 
	
		
			
				|  |  |  			dram_a      <= a0[24:12];
 | 
	
		
			
				|  |  |  			dram_ba     <= a0[11:10];
 | 
	
		
			
				|  |  | +			col_addr    <= a0[11:2];
 | 
	
		
			
				|  |  | +			be_q        <= 1'b1 << a0[1:0];
 | 
	
		
			
				|  |  | +			port        <= 1'b0;
 | 
	
		
			
				|  |  |  			if ( wrq0 )
 | 
	
		
			
				|  |  |  			  begin
 | 
	
		
			
				|  |  | -			     state  <= st_p0_wr;
 | 
	
		
			
				|  |  | -			     wack0_q[t_rcd] <= 1'b1;
 | 
	
		
			
				|  |  | +			     state   <= st_wr;
 | 
	
		
			
				|  |  | +			     wack0   <= 1'b1;
 | 
	
		
			
				|  |  | +			     wdata_q <= {4{wd0}};
 | 
	
		
			
				|  |  |  			  end
 | 
	
		
			
				|  |  |  			else
 | 
	
		
			
				|  |  |  			  begin
 | 
	
		
			
				|  |  | -			     state  <= st_p0_rd;
 | 
	
		
			
				|  |  | -			     rack0_q[t_rcd + t_cl + 1] <= 1'b1;
 | 
	
		
			
				|  |  | +			     state  <= st_rd;
 | 
	
		
			
				|  |  | +			     rack0[t_rcd+t_cl+3] <= 1'b1;
 | 
	
		
			
				|  |  |  			  end
 | 
	
		
			
				|  |  |  		     end
 | 
	
		
			
				|  |  | -		   4'b010z:
 | 
	
		
			
				|  |  | +		   4'b010?:
 | 
	
		
			
				|  |  |  		     begin
 | 
	
		
			
				|  |  |  			// Begin port 1 transaction
 | 
	
		
			
				|  |  |  			dram_cmd    <= cmd_act;
 | 
	
		
			
				|  |  |  			dram_a      <= a1[24:12];
 | 
	
		
			
				|  |  |  			dram_ba     <= a1[11:10];
 | 
	
		
			
				|  |  | +			col_addr    <= a1[11:2];
 | 
	
		
			
				|  |  | +			be_q        <= be1;
 | 
	
		
			
				|  |  | +			port        <= 1'b1;
 | 
	
		
			
				|  |  |  			if ( wrq1 )
 | 
	
		
			
				|  |  |  			  begin
 | 
	
		
			
				|  |  | -			     state  <= st_p1_wr;
 | 
	
		
			
				|  |  | -			     wack1_q[t_rcd] <= 1'b1;
 | 
	
		
			
				|  |  | +			     state   <= st_wr;
 | 
	
		
			
				|  |  | +			     wack1   <= 1'b1;
 | 
	
		
			
				|  |  | +			     wdata_q <= wd1;
 | 
	
		
			
				|  |  |  			  end
 | 
	
		
			
				|  |  |  			else
 | 
	
		
			
				|  |  |  			  begin
 | 
	
		
			
				|  |  | -			     state  <= st_p1_rd;
 | 
	
		
			
				|  |  | -			     rack1_q[t_rcd + t_cl + 1] <= 1'b1;
 | 
	
		
			
				|  |  | +			     state  <= st_rd;
 | 
	
		
			
				|  |  | +			     rack1[t_rcd+t_cl+3] <= 1'b1;
 | 
	
		
			
				|  |  |  			  end
 | 
	
		
			
				|  |  |  		     end
 | 
	
		
			
				|  |  | -		   4'b0z1z, 4'b0001:
 | 
	
		
			
				|  |  | +		   4'b0?1?, 4'b0001:
 | 
	
		
			
				|  |  |  		     begin
 | 
	
		
			
				|  |  |  			// Begin refresh transaction
 | 
	
		
			
				|  |  |  			dram_cmd    <= cmd_ref;
 | 
	
	
		
			
				|  | @@ -365,115 +395,117 @@ module sdram
 | 
	
		
			
				|  |  |  	      end // case: st_idle
 | 
	
		
			
				|  |  |  	    st_rfsh:
 | 
	
		
			
				|  |  |  	      begin
 | 
	
		
			
				|  |  | -		 if (op_cycle >= t_rfc-1)
 | 
	
		
			
				|  |  | +		 if (op_cycle == t_rfc-2)
 | 
	
		
			
				|  |  |  		   state <= st_idle;
 | 
	
		
			
				|  |  |  	      end
 | 
	
		
			
				|  |  | -	    st_p0_rd:
 | 
	
		
			
				|  |  | +	    st_rd:
 | 
	
		
			
				|  |  |  	      begin
 | 
	
		
			
				|  |  |  		 dram_d_en   <= 1'b0;		// Tristate our output
 | 
	
		
			
				|  |  | -		 dram_a[8:0] <= a0[9:1];
 | 
	
		
			
				|  |  | -		 dram_ba     <= a0[11:10];
 | 
	
		
			
				|  |  | -		 dram_a[10]  <= 1'b0;		// No auto precharge
 | 
	
		
			
				|  |  |  		 dram_dqm    <= 2'b00;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -		 if ( op_cycle == t_rcd )
 | 
	
		
			
				|  |  | -		   dram_cmd <= cmd_rd;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		 if ( op_cycle == t_pre_rd_when )
 | 
	
		
			
				|  |  | -		   dram_cmd <= cmd_pre; // Precharge and stop burst
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		 // Latch and ack input data. There is an implicit
 | 
	
		
			
				|  |  | -		 // due to bus turnaround.
 | 
	
		
			
				|  |  | -		 for (int i = 0; i <= t_rcd + t_cl; i++)
 | 
	
		
			
				|  |  | -		   begin
 | 
	
		
			
				|  |  | -		      rack0_q[i] <= (op_cycle == t_rcd + t_cl + 1 - i);
 | 
	
		
			
				|  |  | +		 // Commands
 | 
	
		
			
				|  |  | +		 //
 | 
	
		
			
				|  |  | +		 // This assumes:
 | 
	
		
			
				|  |  | +		 // tRCD = 3
 | 
	
		
			
				|  |  | +		 // rRRD = 2
 | 
	
		
			
				|  |  | +		 // CL   = 3
 | 
	
		
			
				|  |  | +		 // tRC  = 10
 | 
	
		
			
				|  |  | +		 case (op_cycle)
 | 
	
		
			
				|  |  | +		   1: begin
 | 
	
		
			
				|  |  | +		      dram_a   <= next_bank[14:2];
 | 
	
		
			
				|  |  | +		      dram_ba  <= next_bank[1:0];
 | 
	
		
			
				|  |  | +		      dram_cmd <= last_dword ? cmd_act : cmd_nop;
 | 
	
		
			
				|  |  |  		   end
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		 if ( op_cycle == t_rcd + t_cl + 1 )
 | 
	
		
			
				|  |  | -		   begin
 | 
	
		
			
				|  |  | -		      dram_q      <= sr_dq;
 | 
	
		
			
				|  |  | -		      rack0_q     <= 1'b1;
 | 
	
		
			
				|  |  | +		   2, 4: begin
 | 
	
		
			
				|  |  | +		      dram_a[12:9] <= 4'b0000;
 | 
	
		
			
				|  |  | +		      dram_a[8:1]  <= col_addr[9:2];
 | 
	
		
			
				|  |  | +		      dram_a[0]    <= 1'b0;
 | 
	
		
			
				|  |  | +		      dram_cmd     <= cmd_rd;
 | 
	
		
			
				|  |  | +		      col_addr     <= col_addr + 1'b1;
 | 
	
		
			
				|  |  |  		   end
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		 if ( op_cycle >= max(t_rc, t_pre_rd_when + t_rp) - 1 )
 | 
	
		
			
				|  |  | -		   state <= st_idle;
 | 
	
		
			
				|  |  | -	      end // case: st_p0_rd
 | 
	
		
			
				|  |  | -	    st_p0_wr:
 | 
	
		
			
				|  |  | -	      begin
 | 
	
		
			
				|  |  | -		 dram_a[8:0]      <= a0[9:1];
 | 
	
		
			
				|  |  | -		 dram_ba          <= a0[11:10];
 | 
	
		
			
				|  |  | -		 dram_a[10]       <= 1'b0;  // No auto precharge
 | 
	
		
			
				|  |  | -		 dram_d           <= { wd0, wd0 };
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		 // Ack data
 | 
	
		
			
				|  |  | -		 for (int i = 0; i <= t_rcd; i++)
 | 
	
		
			
				|  |  | -		   begin
 | 
	
		
			
				|  |  | -		      wack0_q[i] <= (op_cycle == t_rcd - i);
 | 
	
		
			
				|  |  | +		   8: begin
 | 
	
		
			
				|  |  | +		      // Precharge all banks
 | 
	
		
			
				|  |  | +		      dram_a[12:9] <= 4'b0010;
 | 
	
		
			
				|  |  | +		      dram_cmd     <= cmd_pre;
 | 
	
		
			
				|  |  |  		   end
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		 if ( op_cycle == t_rcd )
 | 
	
		
			
				|  |  | -		   begin
 | 
	
		
			
				|  |  | -		      dram_cmd <= cmd_wr;
 | 
	
		
			
				|  |  | -		      dram_dqm <= { ~a0[0], a0[0] };
 | 
	
		
			
				|  |  | +		   10: begin
 | 
	
		
			
				|  |  | +		      state <= st_idle;
 | 
	
		
			
				|  |  |  		   end
 | 
	
		
			
				|  |  | +		 endcase // case (op_cycle)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -		 if ( op_cycle == t_pre_wr_when )
 | 
	
		
			
				|  |  | +		 // +2 for bus turnaround latencies
 | 
	
		
			
				|  |  | +		 if (op_cycle >= 2+t_cl+2)
 | 
	
		
			
				|  |  |  		   begin
 | 
	
		
			
				|  |  | -		      dram_cmd <= cmd_pre;
 | 
	
		
			
				|  |  | -		   end
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		 if ( op_cycle >= max(t_rc, t_pre_wr_when + t_rp) - 1 )
 | 
	
		
			
				|  |  | -		   state <= st_idle;
 | 
	
		
			
				|  |  | -	      end // case: st_p0_wr
 | 
	
		
			
				|  |  | -	    st_p1_rd:
 | 
	
		
			
				|  |  | +		      if (port == 1'b0)
 | 
	
		
			
				|  |  | +			begin
 | 
	
		
			
				|  |  | +			   if (be_q[0])
 | 
	
		
			
				|  |  | +			     rd0 <= dram_q[7:0];
 | 
	
		
			
				|  |  | +			   if (be_q[1])
 | 
	
		
			
				|  |  | +			     rd0 <= dram_q[15:8];
 | 
	
		
			
				|  |  | +			end
 | 
	
		
			
				|  |  | +		      else if (op_cycle[0] ^ ((2+t_cl+2) & 1'b1))
 | 
	
		
			
				|  |  | +			begin
 | 
	
		
			
				|  |  | +			   // Odd word
 | 
	
		
			
				|  |  | +			   if (be_q[0])
 | 
	
		
			
				|  |  | +			     rd1[23:16] <= dram_q[ 7:0];
 | 
	
		
			
				|  |  | +			   if (be_q[1])
 | 
	
		
			
				|  |  | +			     rd1[31:24] <= dram_q[15:8];
 | 
	
		
			
				|  |  | +			end
 | 
	
		
			
				|  |  | +		      else
 | 
	
		
			
				|  |  | +			begin
 | 
	
		
			
				|  |  | +			   // Even word
 | 
	
		
			
				|  |  | +			   if (be_q[0])
 | 
	
		
			
				|  |  | +			     rd1[ 7:0] <= dram_q[ 7:0];
 | 
	
		
			
				|  |  | +			   if (be_q[1])
 | 
	
		
			
				|  |  | +			     rd1[15:8] <= dram_q[15:8];
 | 
	
		
			
				|  |  | +			end // else: !if(op_cycle[0] ^ ((t_rcd-1+t_cl+2) & 1'b1))
 | 
	
		
			
				|  |  | +		      be_q >>= 2;
 | 
	
		
			
				|  |  | +		   end // if (op_cycle >= 2+t_cl+2)
 | 
	
		
			
				|  |  | +	      end // case: st_rd
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	    st_wr:
 | 
	
		
			
				|  |  |  	      begin
 | 
	
		
			
				|  |  | -		 dram_d_en   <= 1'b0;		// Tristate our output
 | 
	
		
			
				|  |  | -		 dram_a[8:0] <= a1[9:1];
 | 
	
		
			
				|  |  | -		 dram_ba     <= a1[11:10];
 | 
	
		
			
				|  |  | -		 dram_a[10]  <= 1'b1;		// Auto precharge
 | 
	
		
			
				|  |  | -		 dram_dqm    <= 2'b00;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		 if ( op_cycle == t_rcd )
 | 
	
		
			
				|  |  | -		   dram_cmd <= cmd_rd;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		 // Latch and ack input data. There is an implicit +1
 | 
	
		
			
				|  |  | -		 // due to bus turnaround.
 | 
	
		
			
				|  |  | -		 for (int i = 0; i <= t_rcd + t_cl + 1; i++)
 | 
	
		
			
				|  |  | -		   begin
 | 
	
		
			
				|  |  | -		      rack1_q[i] <= (op_cycle > t_rcd + t_cl - i &&
 | 
	
		
			
				|  |  | -				     op_cycle <= t_rcd + t_cl + burst_n - i);
 | 
	
		
			
				|  |  | +		 // Commands
 | 
	
		
			
				|  |  | +		 //
 | 
	
		
			
				|  |  | +		 // This assumes:
 | 
	
		
			
				|  |  | +		 // tRCD = 3
 | 
	
		
			
				|  |  | +		 // tRRD = 2
 | 
	
		
			
				|  |  | +		 // CL   = 3
 | 
	
		
			
				|  |  | +		 // tRC  = 10
 | 
	
		
			
				|  |  | +		 // tWR  = 2
 | 
	
		
			
				|  |  | +		 // tRP =  3
 | 
	
		
			
				|  |  | +		 case (op_cycle)
 | 
	
		
			
				|  |  | +		   1: begin
 | 
	
		
			
				|  |  | +		      dram_a   <= next_bank[14:2];
 | 
	
		
			
				|  |  | +		      dram_ba  <= next_bank[1:0];
 | 
	
		
			
				|  |  | +		      dram_cmd <= last_dword ? cmd_act : cmd_nop;
 | 
	
		
			
				|  |  |  		   end
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		 if ( op_cycle > t_rcd + t_cl &&
 | 
	
		
			
				|  |  | -		      op_cycle <= t_rcd + t_cl + burst_n )
 | 
	
		
			
				|  |  | -		   begin
 | 
	
		
			
				|  |  | -		      dram_q      <= sr_dq;
 | 
	
		
			
				|  |  | +		   2, 4: begin
 | 
	
		
			
				|  |  | +		      dram_a[12:9] <= 4'b0000;
 | 
	
		
			
				|  |  | +		      dram_a[8:1]  <= col_addr[9:2];
 | 
	
		
			
				|  |  | +		      dram_a[0]    <= 1'b0;
 | 
	
		
			
				|  |  | +		      dram_cmd     <= cmd_wr;
 | 
	
		
			
				|  |  | +		      col_addr     <= col_addr + 1'b1;
 | 
	
		
			
				|  |  | +		   end
 | 
	
		
			
				|  |  | +		   7: begin
 | 
	
		
			
				|  |  | +		      // Precharge all banks
 | 
	
		
			
				|  |  | +		      dram_a[12:9] <= 4'b0010;
 | 
	
		
			
				|  |  | +		      dram_cmd     <= cmd_pre;
 | 
	
		
			
				|  |  | +		   end
 | 
	
		
			
				|  |  | +		   10: begin
 | 
	
		
			
				|  |  | +		      state <= st_idle;
 | 
	
		
			
				|  |  |  		   end
 | 
	
		
			
				|  |  | +		 endcase // case (op_cycle)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -		 if ( op_cycle >= max(t_rc - 1, t_rcd + t_cl + burst_n) )
 | 
	
		
			
				|  |  | -		   state <= st_idle;
 | 
	
		
			
				|  |  | -	      end // case: st_p1_rd
 | 
	
		
			
				|  |  | -	    st_p1_wr:
 | 
	
		
			
				|  |  | -	      begin
 | 
	
		
			
				|  |  | -		 dram_a[8:0] <= a1[9:1];
 | 
	
		
			
				|  |  | -		 dram_ba     <= a1[11:10];
 | 
	
		
			
				|  |  | -		 dram_a[10]  <= 1'b1;		// Auto precharge
 | 
	
		
			
				|  |  | -		 dram_dqm    <= ~wbe1;
 | 
	
		
			
				|  |  | -		 dram_d      <= wd1;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		 // Ack data
 | 
	
		
			
				|  |  | -		 for (int i = 0; i <= t_rcd; i++)
 | 
	
		
			
				|  |  | +		 if (op_cycle >= 2)
 | 
	
		
			
				|  |  |  		   begin
 | 
	
		
			
				|  |  | -		      wack1_q[i] <= (op_cycle >= t_rcd - i &&
 | 
	
		
			
				|  |  | -				     op_cycle < t_rcd + burst_n);
 | 
	
		
			
				|  |  | +		      dram_d  <= wdata_q[15:0];
 | 
	
		
			
				|  |  | +		      // Flip data between odd and even words
 | 
	
		
			
				|  |  | +		      wdata_q <= { wdata_q[15:0], wdata_q[31:16] };
 | 
	
		
			
				|  |  | +		      dram_dqm <= ~be_q[1:0];
 | 
	
		
			
				|  |  | +		      be_q >>= 2;
 | 
	
		
			
				|  |  |  		   end
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		 if ( op_cycle == t_rcd )
 | 
	
		
			
				|  |  | -		   dram_cmd <= cmd_wr;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		 if ( op_cycle >= max(t_rcd + burst_n + t_wr + t_rp, t_rc) - 1 )
 | 
	
		
			
				|  |  | -		   state <= st_idle;
 | 
	
		
			
				|  |  | -	      end // case: st_p1_wr
 | 
	
		
			
				|  |  | +	      end // case: st_wr
 | 
	
		
			
				|  |  |  	  endcase // case(state)
 | 
	
		
			
				|  |  |         end // else: !if(~rst_n)
 | 
	
		
			
				|  |  |  endmodule // dram
 |