Improved access speed to SDRAM.

This commit is contained in:
kitune-san
2022-08-15 13:07:19 +09:00
parent c4a22e57b4
commit eaba318d41
4 changed files with 95 additions and 183 deletions

View File

@@ -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 }]

View File

@@ -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),

View File

@@ -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

View File

@@ -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;