Browse Source

sdram: remove misaligned handling

Misaligned memory accesses were removed from the CPU, so we can
greatly simplify the memory controller by taking that logic out, too.
H. Peter Anvin 3 years ago
parent
commit
9e0713c926

+ 1 - 1
fpga/max80.qsf

@@ -70,7 +70,7 @@ set_global_assignment -name VHDL_INPUT_VERSION VHDL_2008
 set_global_assignment -name VHDL_SHOW_LMF_MAPPING_MESSAGES OFF
 set_global_assignment -name VERILOG_INPUT_VERSION SYSTEMVERILOG_2005
 set_global_assignment -name VERILOG_SHOW_LMF_MAPPING_MESSAGES OFF
-set_global_assignment -name SAFE_STATE_MACHINE ON
+set_global_assignment -name SAFE_STATE_MACHINE OFF
 set_global_assignment -name REMOVE_REDUNDANT_LOGIC_CELLS ON
 set_global_assignment -name HDL_MESSAGE_LEVEL LEVEL3
 set_global_assignment -name SYNTH_PROTECT_SDC_CONSTRAINT ON

+ 7 - 7
fpga/max80.sv

@@ -197,7 +197,7 @@ module max80 (
    endgenerate
 
    assign hdmi_scl = 1'bz;
-   assign hdmi_sck = 1'bz;
+   assign hdmi_sda = 1'bz;
    assign hdmi_hpd = 1'bz;
 
    //
@@ -322,7 +322,7 @@ module max80 (
 
    wire       abc_rack;
    wire       abc_wack;
-   wire       abc_rvalid;
+   wire       abc_rready;
    wire [7:0] abc_sr_rd;
 
    always @(posedge sdram_clk or negedge rst_n)
@@ -346,7 +346,7 @@ module max80 (
 	  abc_rrq <= abc_xmemrd_q & ~(abc_xmem_done | abc_rack);
 	  abc_wrq <= abc_xmemwr_q & ~(abc_xmem_done | abc_wack);
 
-	  if (abc_rack & abc_rvalid)
+	  if (abc_rack & abc_rready)
 	    abc_do <= abc_sr_rd;
 
 	  // HACK FOR TESTING ONLY
@@ -373,19 +373,18 @@ module max80 (
 		.rd0      ( abc_sr_rd ),
 		.rrq0     ( abc_rrq ),
 		.rack0    ( abc_rack ),
-		.rvalid0  ( abc_rvalid ),
+		.rready0  ( abc_rready ),
 		.wd0      ( abc_d ),
 		.wrq0     ( abc_wrq ),
 		.wack0    ( abc_wack ),
 
 		.a1       ( 24'hxxxxxx ),
-		.be1      ( 8'b0000_0000 ),
 		.rd1      ( ),
 		.rrq1     ( 1'b0 ),
 		.rack1    ( ),
-		.rvalid1  ( ),
+		.rready1  ( ),
 		.wd1      ( 32'hxxxx_xxxx ),
-		.wrq1     ( 1'b0 ),
+		.wstrb1   ( 4'b0000 ),
 		.wack1    ( )
 		);
 
@@ -421,6 +420,7 @@ module max80 (
    wire [31:0]                cpu_mem_addr;
    wire [31:0]                cpu_mem_wdata;
    reg  [31:0]		      cpu_mem_rdata;
+   wire 		      cpu_mem_ready;
 
    wire			      cpu_mem_read = cpu_mem_valid & ~|cpu_mem_wstrb;
 

File diff suppressed because it is too large
+ 461 - 605
fpga/output_files/max80.jam


BIN
fpga/output_files/max80.jbc


BIN
fpga/output_files/max80.jic


+ 1 - 1
fpga/output_files/max80.map

@@ -10,7 +10,7 @@ Quad-Serial configuration device dummy clock cycle: 8
 
 Notes:
 
-- Data checksum for this conversion is 0xF783E86E
+- Data checksum for this conversion is 0xF76F5268
 
 - All the addresses in this file are byte addresses
 

BIN
fpga/output_files/max80.pof


BIN
fpga/output_files/max80.sof


+ 72 - 153
fpga/sdram.sv

@@ -18,13 +18,12 @@
 //
 //  Two ports are provided: port 0 is single byte per transaction,
 //  and has highest priority; it is intended for transactions from the
-//  ABC-bus. Port 1 does 4-byte accesses with arbitrary alignment and
-//  byte enables.
+//  ABC-bus. Port 1 does aligned 4-byte accesses with byte enables.
 //
 //  All signals are in the sdram clock domain.
 //
 //  [rw]ack is asserted at the beginning of a read- or write cycle and
-//  deasserted afterwards; rvalid is asserted once all data is read and
+//  deasserted afterwards; rready is asserted once all data is read and
 //  the read data (rdX port) is valid; it remains asserted after the
 //  transaction is complete and rack is deasserted.
 //
@@ -63,7 +62,7 @@ module sdram
    t_refi_lg2	= 10,	// 1024 cycles
    t_p_lg2	= 15,	// 32768 cycles
 
-   burst_lg2	=  1	// Burst length on port 1
+   burst_lg2	=  1	// log2(burst length)
 )
 (
 	      // Reset and clock
@@ -88,7 +87,7 @@ module sdram
 	      output reg [7:0]	rd0, // Data from SDRAM
 	      input		rrq0, // Read request
 	      output reg	rack0, // Read ack (transaction started)
-	      output reg	rvalid0, // Read data valid
+	      output reg	rready0, // Read data valid
 
 	      input [7:0]	wd0, // Data to SDRAM
 	      input		wrq0, // Write request
@@ -96,20 +95,21 @@ module sdram
 
 	      // Port 1
 	      input [24:2]	a1,
-	      input [7:0]	be1, // Write byte enable
 
 	      output reg [31:0] rd1,
 	      input		rrq1,
 	      output reg	rack1,
-	      output reg	rvalid1,
+	      output reg	rready1,
 
 	      input [31:0]	wd1,
-	      input		wrq1,
+	      input [3:0]	wstrb1,
 	      output reg	wack1
 	      );
 
 `include "functions.sv"		// For modelsim
 
+   wire 			wrq1 = |wstrb1;
+   
    // Mode register data
    wire			    mrd_wburst = 1'b1;     // Write bursts enabled
    wire [2:0]		    mrd_cl     = t_cl;
@@ -203,7 +203,8 @@ module sdram
 	 st_idle,		// Idle state: all banks precharged
 	 st_rfsh,
 	 st_rd,
-	 st_wr
+	 st_wr,
+	 st_pre_idle
    } state_t;
    state_t state = st_reset;
 
@@ -236,22 +237,9 @@ module sdram
    reg 	     op_zero;		// op_cycle wrap around
    reg [1:0] init_op_ctr;	// op_cycle extension for init states
    
-   // 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
-
-   always @(posedge clk)
-     begin
-	if (op_cycle == 0)
-	    begin
-	       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 [ 7:0] be_q;
+   reg [ 3:0] be_q;
+   reg [ 9:0] col_addr;
 
    //
    // Careful with the timing here... there is one cycle between
@@ -275,32 +263,36 @@ module sdram
 	  state         <= st_reset;
 
 	  rack0         <= 1'b0;
-	  rvalid0       <= 1'b0;
+	  rready0       <= 1'b0;
 	  wack0         <= 1'b0;
 
 	  rack1         <= 1'b0;
-	  rvalid1       <= 1'b0;
+	  rready1       <= 1'b0;
 	  wack1         <= 1'b0;
 
 	  wdata_q       <= 32'hxxxx_xxxx;
-	  be_q          <= 8'hxx;
+	  be_q          <= 4'bxxxx;
        end
      else
        begin
 	  dram_cke <= 1'b1;	// Always true once out of reset
 
 	  // Default values
-	  dram_ba       <= 2'bxx;
+	  // Note: dram_ba are preserved
+	  dram_a        <= 13'hxxxx;
 	  dram_dqm      <= 2'b00;
 	  dram_d        <= 16'hxxxx;
 	  dram_cmd      <= cmd_nop;
 
 	  dram_d_en     <= 1'b1; // Don't float except during read
 
-	  rack0       <= 1'b0;
-	  wack0       <= 1'b0;
-	  rack1       <= 1'b0;
-	  wack1       <= 1'b0;
+	  if (state != st_rd && state != st_wr)
+	    begin
+	       rack0 <= 1'b0;
+	       wack0 <= 1'b0;
+	       rack1 <= 1'b0;
+	       wack1 <= 1'b0;
+	    end
 
 	  if (state == st_reset || state == st_idle)
 	    op_cycle <= 1'b0;
@@ -318,6 +310,7 @@ module sdram
 		 if (init_ctr[t_p_lg2])
 		      state      <= st_init_rfsh;
 	      end
+
 	    st_init_rfsh:
 	      begin
 		 dram_a[10] <= 1'b1; // Refresh all banks
@@ -330,6 +323,7 @@ module sdram
 			state <= st_init_mrd;
 		   end
 	      end
+
 	    st_init_mrd:			       
 	      begin
 		 dram_a <= mrd_val;
@@ -339,6 +333,7 @@ module sdram
 		   else
 		     dram_cmd <= cmd_mrd;
 	      end
+
 	    st_idle:
 	      begin
 		 // A data transaction starts with ACTIVE command;
@@ -355,19 +350,20 @@ module sdram
 			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];
+			col_addr     <= a0[9:0];
 			if ( wrq0 )
 			  begin
 			     state   <= st_wr;
 			     wack0   <= 1'b1;
-			     wdata_q <= {4{wd0}};
+			     wdata_q <= {16'hxxxx, wd0, wd0};
+			     be_q    <= {2'b00, a0[0], ~a0[0]};
 			  end
 			else
 			  begin
 			     state   <= st_rd;
 			     rack0   <= 1'b1;
-			     rvalid0 <= 1'b0;
+			     rready0 <= 1'b0;
+			     be_q    <= 4'b1111;
 			  end
 		     end
 		   4'b010?:
@@ -376,19 +372,20 @@ module sdram
 			dram_cmd     <= cmd_act;
 			dram_a       <= a1[24:12];
 			dram_ba      <= a1[11:10];
-			col_addr     <= a1[11:2];
-			be_q         <= be1;
+			col_addr     <= { a1[9:2], 2'b00 };
 			if ( wrq1 )
 			  begin
 			     state   <= st_wr;
 			     wack1   <= 1'b1;
 			     wdata_q <= wd1;
+			     be_q    <= wstrb1;
 			  end
 			else
 			  begin
 			     state   <= st_rd;
 			     rack1   <= 1'b1;
-			     rvalid1 <= 1'b0;
+			     rready1 <= 1'b0;
+			     be_q    <= 4'b1111;
 			  end
 		     end
 		   4'b0?1?, 4'b0001:
@@ -402,19 +399,18 @@ module sdram
 			dram_cmd    <= cmd_desl;
 			state       <= st_idle;
 		     end
-		 endcase // casez ( {rrq0|wrq0, rrq1|wrq1, rfsh_ctr[t_ref:t_ref-1]} )
+		 endcase // casez ( {rrq0|wrq0, rrq1|wrq1, rfsh_prio} )
 	      end // case: st_idle
+
 	    st_rfsh:
 	      begin
 		 if (op_cycle == t_rfc-2)
 		   state <= st_idle;
 	      end
-	    st_rd:
-	      begin
-		 rack0       <= rack0;
-		 rack1       <= rack1;
 
-		 dram_d_en   <= 1'b0;		// Tristate data bus
+	    st_rd, st_wr:
+	      begin
+		 dram_d_en <= (state == st_wr);
 
 		 // Commands
 		 //
@@ -423,123 +419,46 @@ module sdram
 		 // 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
-		   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
-		   8: begin
-		      // Precharge all banks
-		      dram_a[12:9] <= 4'b0010;
-		      dram_cmd     <= cmd_pre;
-		   end
-		   10: begin
-		      state <= st_idle;
-		      rack0 <= 1'b0;
-		      rack1 <= 1'b0;
-		   end
-		 endcase // case (op_cycle)
-
-		 // +2 for bus turnaround latencies
-		 // Assert rvalid in the same cycle the last requested
-		 // data byte (as given by byte enables) is latched.
-
-		 if (op_cycle >= 2+t_cl+2)
-		   begin
-		      if (rack0)
-			begin
-			   rvalid0 <= ~|be_q[7:2];
-
-			   if (be_q[0])
-			     rd0 <= dram_q[7:0];
-			   if (be_q[1])
-			     rd0 <= dram_q[15:8];
-			end
-		      if (rack1)
-			begin
-			   rvalid1 <= ~|be_q[7:2];
-
-			   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))
-			end // if (rack1)
-
-		      be_q <= be_q >> 2;
-		   end // if (op_cycle >= 2+t_cl+2)
-	      end // case: st_rd
-
-	    st_wr:
-	      begin
-		 wack0 <= wack0;
-		 wack1 <= wack1;
-
-		 dram_dqm <= 2'b11; // Mask data bytes unless we mean it
-
-		 // 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;
+		   2: begin
+		      dram_a[10]   <= 1'b1; // Auto precharge
+		      dram_a[8:0]  <= col_addr[9:1];
+		      dram_cmd     <= (state == st_wr) ? cmd_wr : cmd_rd;
+		      dram_d       <= wdata_q[15:0];
+		      wdata_q      <= { 16'hxxxx, wdata_q[31:16] };
+		      dram_dqm     <= ~be_q[1:0];
+		      be_q         <= { 2'bxx, be_q[3:2] };
 		   end
-		   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;
+		   3: begin
+		      dram_d       <= wdata_q[15:0];
+		      dram_dqm     <= ~be_q[1:0];
+		      wdata_q      <= 32'hxxxx_xxxx;
+		      be_q         <= 4'bxxxx;
 		   end
+		   // CL+2 cycles after the read command
 		   7: begin
-		      // Precharge all banks
-		      dram_a[12:9] <= 4'b0010;
-		      dram_cmd     <= cmd_pre;
+		      if (rack0)
+			rd0 <= col_addr[0] ? dram_q[15:8] : dram_q[7:0];
+		      rready0 <= rready0 | rack0;
+		      if (rack1)
+			rd1[15:0] <= dram_q;
 		   end
-		   10: begin
-		      state <= st_idle;
-		      wack0 <= 1'b0;
-		      wack1 <= 1'b0;
+		   8: begin
+		      if (rack1)
+			rd1[31:16] <= dram_q;
+		      rready1 <= rready1 | rack1;
+		      // Last cycle before tRC is a separate state
+		      // so that rack/wack will be cleared
+		      state <= st_pre_idle;
 		   end
 		 endcase // case (op_cycle)
+	      end // case: st_rd, st_wr
 
-		 if (op_cycle >= 2)
-		   begin
-		      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 <= be_q >> 2;
-		   end
-	      end // case: st_wr
+	    st_pre_idle:
+	      begin
+		 state <= st_idle;
+	      end
 	  endcase // case(state)
        end // else: !if(~rst_n)
 endmodule // dram

Some files were not shown because too many files changed in this diff