mirror of
https://github.com/MiSTer-devel/PCXT_MiSTer.git
synced 2026-04-26 03:04:30 +00:00
Improved access speed to SDRAM.
This commit is contained in:
2
PCXT.sdc
2
PCXT.sdc
@@ -47,7 +47,7 @@ set_max_delay -to [get_registers {emu:emu|CHIPSET:u_CHIPSET|PERIPHERALS:u_PERI
|
||||
emu:emu|CHIPSET:u_CHIPSET|PERIPHERALS:u_PERIPHERALS|CGA_CRTC_OE_1}] 10
|
||||
|
||||
# SDRAM
|
||||
set_input_delay -clock { SDRAM_CLK } -max 6 [get_ports { SDRAM_DQ[*] }]
|
||||
set_input_delay -clock { SDRAM_CLK } -max 5 [get_ports { SDRAM_DQ[*] }]
|
||||
set_input_delay -clock { SDRAM_CLK } -min 3 [get_ports { SDRAM_DQ[*] }]
|
||||
set_output_delay -clock { SDRAM_CLK } -max 2 [get_ports { SDRAM_DQ[*] SDRAM_DQM* SDRAM_A[*] SDRAM_n* SDRAM_BA[*] SDRAM_CKE }]
|
||||
set_output_delay -clock { SDRAM_CLK } -min 1.5 [get_ports { SDRAM_DQ[*] SDRAM_DQM* SDRAM_A[*] SDRAM_n* SDRAM_BA[*] SDRAM_CKE }]
|
||||
|
||||
@@ -305,10 +305,8 @@ module CHIPSET (
|
||||
);
|
||||
|
||||
RAM u_RAM (
|
||||
.clock (clock),
|
||||
.sdram_clock (sdram_clock),
|
||||
.reset (reset),
|
||||
.sdram_reset (sdram_reset),
|
||||
.clock (sdram_clock),
|
||||
.reset (sdram_reset),
|
||||
.enable_sdram (enable_sdram),
|
||||
.address (address),
|
||||
.internal_data_bus (internal_data_bus),
|
||||
|
||||
@@ -5,19 +5,17 @@
|
||||
// Written by kitune-san
|
||||
//
|
||||
module KFSDRAM #(
|
||||
// IS42S16320F-7TL (32Mx16)
|
||||
parameter sdram_col_width = 9,
|
||||
parameter sdram_row_width = 13,
|
||||
parameter sdram_bank_width = 2,
|
||||
parameter sdram_data_width = 16,
|
||||
parameter sdram_no_refresh = 1'b0,
|
||||
parameter sdram_trc = 16'd5-16'd1,
|
||||
parameter sdram_tras = 16'd8-16'd1,
|
||||
parameter sdram_trp = 16'd1-16'd1,
|
||||
parameter sdram_tmrd = 16'd2-16'd1,
|
||||
parameter sdram_trcd = 16'd1-16'd1,
|
||||
parameter sdram_tdpl = 16'd2-16'd1,
|
||||
parameter cas_latency = 3'b011,
|
||||
parameter cas_latency = 3'b010,
|
||||
parameter sdram_init_wait = 16'd10000,
|
||||
parameter sdram_refresh_cycle = 16'd00100
|
||||
) (
|
||||
@@ -57,7 +55,7 @@ module KFSDRAM #(
|
||||
`define BANK_ADDRESS_TOP (sdram_col_width + sdram_row_width + sdram_bank_width - 1)
|
||||
`define BANK_ADDRESS_BOTTOM (sdram_col_width + sdram_row_width)
|
||||
|
||||
typedef enum { INIT, PALL, INIT_CBR_1, INIT_CBR_2, MRS, REFRESH_PALL, REFRESH, IDLE, WRITE_ACT, WRITE, PRECHARGE_WAIT, READ_ACT, READ, PRECHARGE } state_t;
|
||||
typedef enum { INIT, PALL, INIT_CBR_1, INIT_CBR_2, MRS, REFRESH_PALL, REFRESH, IDLE, WRITE, PRECHARGE_WAIT, READ, PRECHARGE } state_t;
|
||||
|
||||
state_t state;
|
||||
state_t next_state;
|
||||
@@ -67,7 +65,6 @@ module KFSDRAM #(
|
||||
logic [sdram_col_width-1:0] read_counter;
|
||||
logic send_cmd_timing;
|
||||
logic end_read_cmd;
|
||||
logic read_flag_tmp;
|
||||
|
||||
//
|
||||
// State Machine
|
||||
@@ -106,16 +103,12 @@ module KFSDRAM #(
|
||||
end
|
||||
IDLE: begin
|
||||
if (write_request)
|
||||
next_state = WRITE_ACT;
|
||||
next_state = WRITE;
|
||||
else if (read_request)
|
||||
next_state = READ_ACT;
|
||||
next_state = READ;
|
||||
else if ((~sdram_no_refresh) && (enable_refresh) && (refresh_counter == sdram_refresh_cycle))
|
||||
next_state = REFRESH_PALL;
|
||||
end
|
||||
WRITE_ACT: begin
|
||||
if (state_counter == sdram_trcd)
|
||||
next_state = WRITE;
|
||||
end
|
||||
WRITE: begin
|
||||
if (access_counter == (access_num - 1))
|
||||
next_state = PRECHARGE_WAIT;
|
||||
@@ -124,10 +117,6 @@ module KFSDRAM #(
|
||||
if (state_counter == sdram_tdpl)
|
||||
next_state = PRECHARGE;
|
||||
end
|
||||
READ_ACT: begin
|
||||
if (state_counter == sdram_trcd)
|
||||
next_state = READ;
|
||||
end
|
||||
READ: begin
|
||||
if ((end_read_cmd) && (read_counter == access_num))
|
||||
next_state = PRECHARGE;
|
||||
@@ -315,26 +304,39 @@ module KFSDRAM #(
|
||||
sdram_dq_io <= 1'b1;
|
||||
end
|
||||
IDLE : begin
|
||||
sdram_address <= 0;
|
||||
sdram_cke <= 1'b1;
|
||||
sdram_cs <= 1'b0;
|
||||
sdram_ras <= 1'b1;
|
||||
sdram_cas <= 1'b1;
|
||||
sdram_we <= 1'b1;
|
||||
sdram_ba <= 0;
|
||||
sdram_dq_out <= 0;
|
||||
sdram_dq_io <= 1'b1;
|
||||
end
|
||||
WRITE_ACT: begin
|
||||
sdram_address <= (send_cmd_timing) ? address[`ROW_ADDRESS_TOP:`ROW_ADDRESS_BOTTOM] : 0;
|
||||
sdram_cke <= 1'b1;
|
||||
sdram_cs <= 1'b0;
|
||||
sdram_ras <= (send_cmd_timing) ? 1'b0 : 1'b1;
|
||||
sdram_cas <= 1'b1;
|
||||
sdram_we <= 1'b1;
|
||||
sdram_ba <= (send_cmd_timing) ? address[`BANK_ADDRESS_TOP:`BANK_ADDRESS_BOTTOM] : 0;
|
||||
sdram_dq_out <= 0;
|
||||
sdram_dq_io <= 1'b1;
|
||||
if (next_state == WRITE) begin
|
||||
sdram_address <= address[`ROW_ADDRESS_TOP:`ROW_ADDRESS_BOTTOM];
|
||||
sdram_cke <= 1'b1;
|
||||
sdram_cs <= 1'b0;
|
||||
sdram_ras <= 1'b0;
|
||||
sdram_cas <= 1'b1;
|
||||
sdram_we <= 1'b1;
|
||||
sdram_ba <= address[`BANK_ADDRESS_TOP:`BANK_ADDRESS_BOTTOM];
|
||||
sdram_dq_out <= 0;
|
||||
sdram_dq_io <= 1'b1;
|
||||
end
|
||||
else if (next_state == READ) begin
|
||||
sdram_address <= address[`ROW_ADDRESS_TOP:`ROW_ADDRESS_BOTTOM];
|
||||
sdram_cke <= 1'b1;
|
||||
sdram_cs <= 1'b0;
|
||||
sdram_ras <= 1'b0;
|
||||
sdram_cas <= 1'b1;
|
||||
sdram_we <= 1'b1;
|
||||
sdram_ba <= address[`BANK_ADDRESS_TOP:`BANK_ADDRESS_BOTTOM];
|
||||
sdram_dq_out <= 0;
|
||||
sdram_dq_io <= 1'b1;
|
||||
end
|
||||
else begin
|
||||
sdram_address <= 0;
|
||||
sdram_cke <= 1'b1;
|
||||
sdram_cs <= 1'b0;
|
||||
sdram_ras <= 1'b1;
|
||||
sdram_cas <= 1'b1;
|
||||
sdram_we <= 1'b1;
|
||||
sdram_ba <= 0;
|
||||
sdram_dq_out <= 0;
|
||||
sdram_dq_io <= 1'b1;
|
||||
end
|
||||
end
|
||||
WRITE: begin
|
||||
sdram_address[sdram_col_width-1:0] <= address[sdram_col_width-1:0] + access_counter;
|
||||
@@ -359,17 +361,6 @@ module KFSDRAM #(
|
||||
sdram_dq_out <= 0;
|
||||
sdram_dq_io <= 1'b1;
|
||||
end
|
||||
READ_ACT: begin
|
||||
sdram_address <= (send_cmd_timing) ? address[`ROW_ADDRESS_TOP:`ROW_ADDRESS_BOTTOM] : 0;
|
||||
sdram_cke <= 1'b1;
|
||||
sdram_cs <= 1'b0;
|
||||
sdram_ras <= (send_cmd_timing) ? 1'b0 : 1'b1;
|
||||
sdram_cas <= 1'b1;
|
||||
sdram_we <= 1'b1;
|
||||
sdram_ba <= (send_cmd_timing) ? address[`BANK_ADDRESS_TOP:`BANK_ADDRESS_BOTTOM] : 0;
|
||||
sdram_dq_out <= 0;
|
||||
sdram_dq_io <= 1'b1;
|
||||
end
|
||||
READ: begin
|
||||
sdram_address[sdram_col_width-1:0] <= (~end_read_cmd) ? address[sdram_col_width-1:0] + access_counter : 0;
|
||||
sdram_address[sdram_row_width-1:sdram_col_width] <= 0;
|
||||
@@ -414,12 +405,7 @@ module KFSDRAM #(
|
||||
//
|
||||
// Input Data
|
||||
//
|
||||
always_ff @(posedge sdram_clock, posedge sdram_reset) begin
|
||||
if (sdram_reset)
|
||||
data_out <= 0;
|
||||
else
|
||||
data_out <= sdram_dq_in;
|
||||
end
|
||||
assign data_out = sdram_dq_in;
|
||||
|
||||
|
||||
//
|
||||
@@ -428,13 +414,6 @@ module KFSDRAM #(
|
||||
assign idle = (state == IDLE);
|
||||
assign refresh_mode = (state == REFRESH_PALL) || (state == REFRESH);
|
||||
assign write_flag = (state == WRITE);
|
||||
assign read_flag_tmp = (state == READ) && (next_state == READ) && (state_counter > cas_latency);
|
||||
|
||||
always_ff @(posedge sdram_clock, posedge sdram_reset) begin
|
||||
if (sdram_reset)
|
||||
read_flag <= 1'b0;
|
||||
else
|
||||
read_flag <= read_flag_tmp;
|
||||
end
|
||||
assign read_flag = (state == READ) && (next_state == READ) && (state_counter > cas_latency);
|
||||
|
||||
endmodule
|
||||
|
||||
@@ -4,9 +4,7 @@
|
||||
//
|
||||
module RAM (
|
||||
input logic clock,
|
||||
input logic sdram_clock,
|
||||
input logic reset,
|
||||
input logic sdram_reset,
|
||||
input logic enable_sdram,
|
||||
// I/O Ports
|
||||
input logic [19:0] address,
|
||||
@@ -17,8 +15,6 @@ module RAM (
|
||||
input logic no_command_state,
|
||||
output logic memory_access_ready,
|
||||
output logic ram_address_select_n,
|
||||
// VRAM FIFO
|
||||
// TODO:
|
||||
// SDRAM
|
||||
output logic [12:0] sdram_address,
|
||||
output logic sdram_cke,
|
||||
@@ -32,131 +28,79 @@ module RAM (
|
||||
output logic sdram_dq_io,
|
||||
output logic sdram_ldqm,
|
||||
output logic sdram_udqm,
|
||||
// EMS
|
||||
input logic [6:0] map_ems[0:3],
|
||||
input logic ems_b1,
|
||||
input logic ems_b2,
|
||||
input logic ems_b3,
|
||||
input logic ems_b4
|
||||
|
||||
// EMS
|
||||
input logic [6:0] map_ems[0:3],
|
||||
input logic ems_b1,
|
||||
input logic ems_b2,
|
||||
input logic ems_b3,
|
||||
input logic ems_b4
|
||||
|
||||
);
|
||||
|
||||
typedef enum {IDLE, RAM_WRITE_1, RAM_WRITE_2, RAM_READ_1, RAM_READ_2, COMPLETE_RAM_RW, WAIT} state_t;
|
||||
|
||||
state_t state;
|
||||
state_t next_state;
|
||||
logic [21:0] latch_address_ff;
|
||||
logic [21:0] latch_address;
|
||||
logic [7:0] latch_data_ff;
|
||||
logic [7:0] latch_data;
|
||||
logic write_command_ff_1;
|
||||
logic write_command_ff_2;
|
||||
logic write_command;
|
||||
logic read_command_ff_1;
|
||||
logic read_command_ff_2;
|
||||
logic read_command;
|
||||
logic no_command_state_ff_1;
|
||||
logic no_command_state_ff_2;
|
||||
logic no_command_state_ff_3;
|
||||
logic prev_no_command_state;
|
||||
logic enable_refresh;
|
||||
|
||||
logic access_ready;
|
||||
|
||||
//
|
||||
// RAM Address Select (0x00000-0xAFFFF and 0xC0000-0xEBFFF)
|
||||
//
|
||||
assign ram_address_select_n = ~(enable_sdram &&
|
||||
~(address[19:16] == 4'b1111) && // B0000h reserved for VRAM
|
||||
~(address[19:16] == 4'b1011) && // F0000h reserved for BIOS
|
||||
~(address[19:14] == 6'b111011)); // EC000h reserved for XTIDE
|
||||
|
||||
//
|
||||
assign ram_address_select_n = ~(enable_sdram &&
|
||||
~(address[19:16] == 4'b1111) && // B0000h reserved for VRAM
|
||||
~(address[19:16] == 4'b1011) && // F0000h reserved for BIOS
|
||||
~(address[19:14] == 6'b111011)); // EC000h reserved for XTIDE
|
||||
|
||||
|
||||
//
|
||||
// Latch I/O Ports
|
||||
// I/O Ports
|
||||
//
|
||||
// Address
|
||||
always_ff @(posedge sdram_clock, posedge sdram_reset) begin
|
||||
if (sdram_reset)
|
||||
latch_address_ff <= 0;
|
||||
else begin
|
||||
|
||||
if (ems_b1)
|
||||
latch_address_ff <= {1'b1, map_ems[0], address[13:0]};
|
||||
else if (ems_b2)
|
||||
latch_address_ff <= {1'b1, map_ems[1], address[13:0]};
|
||||
else if (ems_b3)
|
||||
latch_address_ff <= {1'b1, map_ems[2], address[13:0]};
|
||||
else if (ems_b4)
|
||||
latch_address_ff <= {1'b1, map_ems[3], address[13:0]};
|
||||
else
|
||||
latch_address_ff <= {2'b00, address};
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
always_ff @(posedge sdram_clock, posedge sdram_reset) begin
|
||||
if (sdram_reset)
|
||||
latch_address <= 0;
|
||||
always_comb begin
|
||||
if (ems_b1)
|
||||
latch_address = {1'b1, map_ems[0], address[13:0]};
|
||||
else if (ems_b2)
|
||||
latch_address = {1'b1, map_ems[1], address[13:0]};
|
||||
else if (ems_b3)
|
||||
latch_address = {1'b1, map_ems[2], address[13:0]};
|
||||
else if (ems_b4)
|
||||
latch_address = {1'b1, map_ems[3], address[13:0]};
|
||||
else
|
||||
latch_address <= latch_address_ff;
|
||||
latch_address = {2'b00, address};
|
||||
end
|
||||
|
||||
// Data Bus
|
||||
always_ff @(posedge sdram_clock, posedge sdram_reset) begin
|
||||
if (sdram_reset) begin
|
||||
latch_data_ff <= 0;
|
||||
// Data
|
||||
always_ff @(posedge clock, posedge reset) begin
|
||||
if (reset)
|
||||
latch_data <= 0;
|
||||
end
|
||||
else begin
|
||||
latch_data_ff <= internal_data_bus;
|
||||
latch_data <= latch_data_ff;
|
||||
end
|
||||
else
|
||||
latch_data <= internal_data_bus;
|
||||
end
|
||||
|
||||
// Write Command
|
||||
always_ff @(posedge sdram_clock, posedge sdram_reset) begin
|
||||
if (sdram_reset) begin
|
||||
write_command_ff_1 <= 1'b0;
|
||||
write_command_ff_2 <= 1'b0;
|
||||
write_command <= 1'b0;
|
||||
end
|
||||
else begin
|
||||
write_command_ff_1 <= ~ram_address_select_n & ~memory_write_n;
|
||||
write_command_ff_2 <= write_command_ff_1;
|
||||
write_command <= write_command_ff_2;
|
||||
end
|
||||
end
|
||||
assign write_command = ~ram_address_select_n & ~memory_write_n;
|
||||
|
||||
// Read Command
|
||||
always_ff @(posedge sdram_clock, posedge sdram_reset) begin
|
||||
if (sdram_reset) begin
|
||||
read_command_ff_1 <= 1'b0;
|
||||
read_command_ff_2 <= 1'b0;
|
||||
read_command <= 1'b0;
|
||||
end
|
||||
else begin
|
||||
read_command_ff_1 <= ~ram_address_select_n & ~memory_read_n;
|
||||
read_command_ff_2 <= read_command_ff_1;
|
||||
read_command <= read_command_ff_2;
|
||||
end
|
||||
end
|
||||
assign read_command = ~ram_address_select_n & ~memory_read_n;
|
||||
|
||||
// Generate refresh timing
|
||||
always_ff @(posedge sdram_clock, posedge sdram_reset) begin
|
||||
if (sdram_reset) begin
|
||||
no_command_state_ff_1 <= 1'b0;
|
||||
no_command_state_ff_2 <= 1'b0;
|
||||
no_command_state_ff_3 <= 1'b0;
|
||||
always_ff @(posedge clock, posedge reset) begin
|
||||
if (reset) begin
|
||||
prev_no_command_state <= 1'b0;
|
||||
end
|
||||
else begin
|
||||
no_command_state_ff_1 <= no_command_state;
|
||||
no_command_state_ff_2 <= no_command_state_ff_1;
|
||||
no_command_state_ff_3 <= no_command_state_ff_2;
|
||||
prev_no_command_state <= no_command_state;
|
||||
end
|
||||
end
|
||||
|
||||
assign enable_refresh = no_command_state_ff_2 & ~no_command_state_ff_3;
|
||||
assign enable_refresh = no_command_state & ~prev_no_command_state;
|
||||
|
||||
|
||||
//
|
||||
@@ -174,8 +118,8 @@ module RAM (
|
||||
logic refresh_mode;
|
||||
|
||||
KFSDRAM u_KFSDRAM (
|
||||
.sdram_clock (sdram_clock),
|
||||
.sdram_reset (sdram_reset),
|
||||
.sdram_clock (clock),
|
||||
.sdram_reset (reset),
|
||||
.address (access_address),
|
||||
.access_num (access_num),
|
||||
.data_in (access_data_in),
|
||||
@@ -247,8 +191,8 @@ module RAM (
|
||||
endcase
|
||||
end
|
||||
|
||||
always_ff @(posedge sdram_clock, posedge sdram_reset) begin
|
||||
if (sdram_reset)
|
||||
always_ff @(posedge clock, posedge reset) begin
|
||||
if (reset)
|
||||
state = IDLE;
|
||||
else
|
||||
state = next_state;
|
||||
@@ -261,11 +205,11 @@ module RAM (
|
||||
always_comb begin
|
||||
casez (state)
|
||||
IDLE: begin
|
||||
access_address = 25'h0000000;
|
||||
access_num = 10'h000;
|
||||
access_data_in = 16'h0000;
|
||||
write_request = 1'b0;
|
||||
read_request = 1'b0;
|
||||
access_address = {7'h00, latch_address};
|
||||
access_num = 10'h001;
|
||||
access_data_in = {8'h00, latch_data};
|
||||
write_request = write_command ? 1'b1 : 1'b0;
|
||||
read_request = read_command ? 1'b1 : 1'b0;
|
||||
sdram_ldqm = 1'b0;
|
||||
sdram_udqm = 1'b0;
|
||||
end
|
||||
@@ -330,32 +274,23 @@ module RAM (
|
||||
//
|
||||
// Databus Out
|
||||
//
|
||||
logic [15:0] data_out_tmp;
|
||||
|
||||
always_ff @(posedge sdram_clock, posedge sdram_reset) begin
|
||||
if (sdram_reset)
|
||||
data_out_tmp <= 0;
|
||||
else if (read_flag)
|
||||
data_out_tmp <= access_data_out;
|
||||
else if (read_command)
|
||||
data_out_tmp <= data_out_tmp;
|
||||
else
|
||||
data_out_tmp <= 0;
|
||||
end
|
||||
|
||||
always_ff @(posedge clock, posedge reset) begin
|
||||
if (reset)
|
||||
data_bus_out <= 0;
|
||||
else if (read_flag)
|
||||
data_bus_out <= access_data_out[7:0];
|
||||
else if (read_command)
|
||||
data_bus_out <= data_bus_out;
|
||||
else
|
||||
data_bus_out <= data_out_tmp[7:0];
|
||||
data_bus_out <= 0;
|
||||
end
|
||||
|
||||
|
||||
//
|
||||
// Ready/Wait Signal
|
||||
//
|
||||
always_ff @(posedge sdram_clock, posedge sdram_reset) begin
|
||||
if (sdram_reset)
|
||||
always_ff @(posedge clock, posedge reset) begin
|
||||
if (reset)
|
||||
access_ready <= 1'b0;
|
||||
else if (state == COMPLETE_RAM_RW)
|
||||
access_ready <= 1'b1;
|
||||
|
||||
Reference in New Issue
Block a user