2
0
Эх сурвалжийг харах

fpga: make the SDRAM work!

H. Peter Anvin 3 жил өмнө
parent
commit
16e9576297

+ 11 - 0
fpga/max80.sdc

@@ -23,6 +23,17 @@ set_clock_groups -asynchronous \
     -group $main_clocks \
     -group [get_clocks rst_n]
 
+set sdram_clk [get_clocks pll|*|clk\[0\]]
+set cpu_clk   [get_clocks pll|*|clk\[1\]]
+set vid_clk   [get_clocks pll|*|clk\[2\]]
+
+# The SDRAM ack signal is delayed by a minimum of 1 SDRAM plus one CPU
+# cycle by the sdram_mem_ready logic, so make it a multicycle path.
+#set_multicycle_path -from [get_registers sdram:sdram|rd1*] \
+#    -to [get_registers picorv32:cpu|*] -start -setup 3
+#set_multicycle_path -from [get_registers sdram:sdram|rd1*] \
+#    -to [get_registers picorv32:cpu|*] -start -hold 2
+
 # Anything that feeds into a synchronizer is by definition
 # asynchronous, but encode it as allowing multicycle of one
 # clock, to limit the possible skew (but it is of course not possible

+ 78 - 37
fpga/max80.sv

@@ -354,8 +354,45 @@ module max80 (
 	    abc_mempg <= { abc_a[1:0], abc_di };
        end // else: !if(~rst_n)
 
+   //
+   // Internal CPU bus
+   //
+   wire			      cpu_mem_valid;
+   wire			      cpu_mem_instr;
+   wire [ 3:0]		      cpu_mem_wstrb;
+   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;
+
+   wire                       cpu_la_read;
+   wire                       cpu_la_write;
+   wire [31:0]                cpu_la_addr;
+   wire [31:0]		      cpu_la_wdata;
+   wire [ 3:0]		      cpu_la_wstrb;
+
+   // cpu_mem_valid by address quadrant
+   wire [ 3:0] cpu_mem_quad = cpu_mem_valid << cpu_mem_addr[31:30];
+
+   // Decode for small devices; use address space within range of
+   // negative offsets from the zero register [-1K,0)
+   wire [15:0] iodev = cpu_mem_quad[3] << cpu_mem_addr[9:6];
+
+   wire [31:0] sdram_rd;
+   wire        sdram_rack;
+   wire        sdram_rready;
+   wire        sdram_wack;
+   reg	       sdram_acked;
+
+   always @(posedge sdram_clk)
+     sdram_acked <= cpu_mem_quad[1] & (sdram_acked | sdram_rack | sdram_wack);
+
+   wire        sdram_req = cpu_mem_quad[1] & ~sdram_acked;
+
    sdram sdram (
-		.rst_n    ( rst_n ),
+		.rst_n    ( rst_n & ~iodev[12] ),
 		.clk      ( sdram_clk ), // Input clock
 
 		.sr_clk   ( sr_clk ),    // Output clock buffer
@@ -378,14 +415,14 @@ module max80 (
 		.wrq0     ( abc_wrq ),
 		.wack0    ( abc_wack ),
 
-		.a1       ( 24'hxxxxxx ),
-		.rd1      ( ),
-		.rrq1     ( 1'b0 ),
-		.rack1    ( ),
-		.rready1  ( ),
-		.wd1      ( 32'hxxxx_xxxx ),
-		.wstrb1   ( 4'b0000 ),
-		.wack1    ( )
+		.a1       ( cpu_mem_addr[24:2] ),
+		.rd1      ( sdram_rd ),
+		.rrq1     ( sdram_req & ~|cpu_mem_wstrb ),
+		.rack1    ( sdram_rack ),
+		.rready1  ( sdram_rready ),
+		.wd1      ( cpu_mem_wdata ),
+		.wstrb1   ( {4{sdram_req}} & cpu_mem_wstrb ),
+		.wack1    ( sdram_wack )
 		);
 
    // SD card
@@ -413,23 +450,6 @@ module max80 (
 
    // Embedded RISC-V CPU
    parameter cpu_fast_mem_bits = 11; /* 2^[this] * 4 bytes */
-
-   wire			      cpu_mem_valid;
-   wire			      cpu_mem_instr;
-   wire [ 3:0]		      cpu_mem_wstrb;
-   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;
-
-   wire                       cpu_la_read;
-   wire                       cpu_la_write;
-   wire [31:0]                cpu_la_addr;
-   wire [31:0]		      cpu_la_wdata;
-   wire [ 3:0]		      cpu_la_wstrb;
-
    picorv32 #(
 	      .ENABLE_COUNTERS ( 1 ),
 	      .ENABLE_COUNTERS64 ( 1 ),
@@ -473,11 +493,33 @@ module max80 (
 	.eoi ( )
 	);
 
-   // cpu_mem_ready is always true for fast memory
-   assign cpu_mem_ready = cpu_mem_valid;
+   // cpu_mem_ready is always true for fast memory; for SDRAM we have to
+   // wait either for a write ack or a low-high transition on the
+   // read ready signal.
+   reg sdram_rready_q;
+   reg sdram_mem_ready;
+   reg [31:0] sdram_rdata;
+   always @(posedge sys_clk)
+     begin
+	sdram_rready_q <= sdram_rready;
+	if (cpu_mem_quad[1])
+	  sdram_mem_ready <= sdram_mem_ready | sdram_wack |
+			     (sdram_rready & ~sdram_rready_q);
+	else
+	  sdram_mem_ready <= 1'b0;
+
+	sdram_rdata <= sdram_rd;
+     end
 
-   // Memory valid flag by quadrant
-   wire [3:0]		      mem_quad = cpu_mem_valid << cpu_mem_addr[31:30];
+   always @(*)
+     case ( cpu_mem_quad )
+       4'b0000: cpu_mem_ready = 1'b0;
+       4'b0001: cpu_mem_ready = 1'b1;
+       4'b0010: cpu_mem_ready = sdram_mem_ready;
+       4'b0100: cpu_mem_ready = 1'b1;
+       4'b1000: cpu_mem_ready = 1'b1;
+       default: cpu_mem_ready = 1'bx;
+     endcase // case ( mem_quad )
 
    //
    // Fast memory. This runs on the SDRAM clock, i.e. 2x the speed
@@ -498,15 +540,14 @@ module max80 (
 	    .rdata ( fast_mem_rdata )
 	    );
 
+   // Input data MUX
    always @(*)
-     case (cpu_mem_addr[31:30])
-       2'b00: cpu_mem_rdata = fast_mem_rdata;
+     case ( cpu_mem_quad )
+       4'b0001: cpu_mem_rdata = fast_mem_rdata;
+       4'b0010: cpu_mem_rdata = sdram_rdata;
+       4'b1000: cpu_mem_rdata = 32'hffff_ffff;
        default: cpu_mem_rdata = 32'hxxxx_xxxx;
-     endcase // case (cpu_mem_addr[31:30])
-
-   // Decode for small devices; use address space within range of
-   // negative offsets from the zero register [-1K,0)
-   wire [15:0] iodev = mem_quad[3] << cpu_mem_addr[9:6];
+     endcase
 
    // LED indication from the CPU
    reg [2:0]   led_q;

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 2927 - 2675
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 0xF76F5268
+- Data checksum for this conversion is 0xF76CC710
 
 - All the addresses in this file are byte addresses
 

BIN
fpga/output_files/max80.pof


BIN
fpga/output_files/max80.sof


+ 15 - 7
fpga/sdram.sv

@@ -244,7 +244,10 @@ module sdram
    //
    // Careful with the timing here... there is one cycle between
    // registers and wires, and the DRAM observes the clock 1/2
-   // cycle from the internal logic.
+   // cycle from the internal logic. This affects read timing.
+   //
+   // Note that rready starts out as 1. This allows a 0->1 detection
+   // on the rready line to be used as cycle termination signal.
    //
    always @(posedge clk or negedge rst_n)
      if (~rst_n)
@@ -263,11 +266,11 @@ module sdram
 	  state         <= st_reset;
 
 	  rack0         <= 1'b0;
-	  rready0       <= 1'b0;
+	  rready0       <= 1'b1;
 	  wack0         <= 1'b0;
 
 	  rack1         <= 1'b0;
-	  rready1       <= 1'b0;
+	  rready1       <= 1'b1;
 	  wack1         <= 1'b0;
 
 	  wdata_q       <= 32'hxxxx_xxxx;
@@ -306,15 +309,18 @@ module sdram
 	  case (state)
 	    st_reset:
 	      begin
-		 dram_cmd  <= cmd_desl;
+		 dram_a[10] <= 1'b1; // Precharge all banks
+
+		 dram_cmd  <= cmd_nop;
 		 if (init_ctr[t_p_lg2])
-		      state      <= st_init_rfsh;
+		   begin
+		      dram_cmd <= cmd_pre;
+		      state    <= st_init_rfsh;
+		   end
 	      end
 
 	    st_init_rfsh:
 	      begin
-		 dram_a[10] <= 1'b1; // Refresh all banks
-
 		 if (op_zero)
 		   begin
 		      dram_cmd <= cmd_ref;
@@ -327,6 +333,8 @@ module sdram
 	    st_init_mrd:			       
 	      begin
 		 dram_a <= mrd_val;
+		 dram_ba <= 2'b00;
+
 		 if (op_zero)
 		   if (init_op_ctr[0])
 		     state <= st_idle;

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно