Drive RAM and Autoconfig cycles with Z3 State machine

Previously ram_cycle would latch at FCSn asserted and not be cleared until another FCSn assertion happened

This caused issues because FCS_n_sync would lead ram_cycle_sync by 1 clock and this caused false memory cycles to start because ram_cycle_sync would still be true when it shouldn't be.
This commit is contained in:
Matt Harlum 2022-06-13 14:01:00 +00:00
parent 1fc7c53392
commit 0a770dc2d6
5 changed files with 1255 additions and 1251 deletions

File diff suppressed because it is too large Load Diff

View File

@ -10,26 +10,24 @@ work. If not, see <http://creativecommons.org/licenses/by-sa/4.0/>.
*/
module Autoconfig (
input match,
output reg [3:0] addr_match,
input autoconfig_cycle,
input [6:0] ADDRL,
input FCS_n,
input CLK,
input READ,
input DS_n,
input CFGIN_n,
input [3:0] DIN,
input RESET_n,
input SENSEZ3,
input [2:0] FC,
input [1:0] z3_state,
output reg [3:0] addr_match,
output reg CFGOUT_n,
output ram_cycle,
output autoconfig_cycle,
output reg dtack,
output reg configured,
output reg shutup,
output reg [3:0] DOUT
);
`include "globalparams.vh"
`ifndef makedefines
`define SERIAL 32'd421
`define PRODID 8'h72
@ -39,63 +37,6 @@ localparam [15:0] mfg_id = 16'h07DB;
localparam [7:0] prod_id = `PRODID;
localparam [31:0] serial = `SERIAL;
reg shutup = 0;
reg [1:0] z3_state;
wire validspace = FC[1] ^ FC[0]; // 1 when FC indicates user/supervisor data/program space
reg [1:0] vs;
always @(posedge CLK) begin
vs[1:0] <= {vs[0],validspace};
end
localparam Z3_IDLE = 2'd0,
Z3_START = 2'd1,
Z3_DATA = 2'd2,
Z3_END = 2'd3;
assign autoconfig_cycle = match && !CFGIN_n && CFGOUT_n && vs[1];
always @(posedge CLK or negedge RESET_n)
begin
if (!RESET_n) begin
z3_state <= Z3_IDLE;
end else begin
case (z3_state)
Z3_IDLE:
begin
dtack <= 0;
if (!FCS_n && autoconfig_cycle)
z3_state <= Z3_START;
else
z3_state <= Z3_IDLE;
end
Z3_START:
begin
if (FCS_n) begin
z3_state <= Z3_IDLE;
end else if (!DS_n) begin
z3_state <= Z3_DATA;
end else begin
z3_state <= Z3_START;
end
end
Z3_DATA:
begin
z3_state <= Z3_END;
dtack <= 1;
end
Z3_END:
begin
if (FCS_n)
z3_state <= Z3_IDLE;
else
z3_state <= Z3_END;
end
endcase
end
end
// Register Config in/out at end of bus cycle
always @(posedge FCS_n or negedge RESET_n)
begin
@ -111,9 +52,11 @@ begin
if (!RESET_n) begin
DOUT[3:0] <= 4'b0;
configured <= 1'b0;
dtack <= 1'b0;
shutup <= 1'b0;
addr_match[3:0] <= 4'b1111;
end else if (z3_state == Z3_DATA) begin
end else if (z3_state == Z3_DATA && autoconfig_cycle == 1) begin
dtack <= 1;
if (READ) begin
case ({ADDRL[5:0],ADDRL[6]})
7'h00: DOUT[3:0] <= 4'b1010; // Type: Zorro III Memory
@ -148,8 +91,9 @@ begin
configured <= 1;
end
end
end else begin
dtack <= 0;
end
end
assign ram_cycle = (match && !CFGOUT_n && !shutup && vs[1]);
endmodule

4
RTL/globalparams.vh Normal file
View File

@ -0,0 +1,4 @@
localparam Z3_IDLE = 2'd0,
Z3_START = 2'd1,
Z3_DATA = 2'd2,
Z3_END = 2'd3;

View File

@ -13,15 +13,13 @@ work. If not, see <http://creativecommons.org/licenses/by-sa/4.0/>.
module SDRAM(
input [27:2] ADDR,
input [3:0] DS_n,
input DOE,
input FCS_n,
input ram_cycle,
input RESET_n,
input RW,
input CLK,
input ECLK,
input configured,
input MTCR_n,
input [1:0] z3_state,
output [1:0] BA,
output [12:0] MADDR,
output CAS_n,
@ -30,11 +28,13 @@ module SDRAM(
output WE_n,
output reg CKE,
output reg [3:0] DQM_n,
output DTACK_EN
output reg dtack
);
localparam tRP = 1;
localparam tRCD = 1;
`include "globalparams.vh"
localparam tRP = 2;
localparam tRCD = 2;
localparam tRFC = 4;
localparam CAS_LATENCY = 3'd2;
@ -178,13 +178,6 @@ always @(posedge CLK or negedge RESET_n) begin
end
end
reg [1:0] ram_cycle_sync;
reg dtack;
always @(posedge CLK) begin
ram_cycle_sync[1:0] <= {ram_cycle_sync[0], ram_cycle};
end
always @(posedge CLK or negedge RESET_n)
begin
if (!RESET_n) begin
@ -215,10 +208,10 @@ begin
cs_r_n[1:0] <= 2'b00; // Refresh all modules
refreshing <= 1'b1;
// If refresh_request not active and we're in a ram cycle, go do a ram access
end else if (ram_cycle_sync[1] && !FCS_n) begin
end else if (ram_cycle && z3_state >= Z3_START) begin
`cmd(cmd_active)
cycle_type <= ram_cycle_access;
ram_state <= access_cycle_wait;
ram_state <= 5'h1;
maddr_r[12:0] <= ADDR[23:11];
ba_r[1:0] <= ADDR[25:24];
cs_r_n[1:0] <= {ADDR[26],~ADDR[26]};
@ -237,7 +230,7 @@ begin
// Wait for tRCD and also wait until we see data strobes before committing writes
access_cycle_wait: begin
`cmd(cmd_nop)
if (DS_n[3:0] != 4'b1111 && DOE)
if (z3_state == Z3_DATA)
ram_state <= access_cycle_rw;
else
ram_state <= access_cycle_wait; // No data strobes seen yet, hold off
@ -268,12 +261,13 @@ begin
// For write cycles, just keep NOP'ing
access_cycle_hold: begin
`cmd(cmd_nop)
if (!FCS_n && DS_n[3:0] != 4'b1111) begin
if (z3_state >= Z3_DATA) begin
if (RW)
CKE <= 0;
ram_state <= access_cycle_hold;
end else begin
CKE <= 1;
dtack <= 0;
ram_state <= access_cycle_precharge;
end
end
@ -309,15 +303,5 @@ begin
end
end
reg [2:0] dtack_delayed;
always @(posedge CLK or negedge RESET_n) begin
if (!RESET_n)
dtack_delayed[2:0] <= 3'b0;
else
dtack_delayed[2:0] <= {dtack_delayed[1:0], dtack};
end
assign DTACK_EN = dtack_delayed[CAS_LATENCY-1];
endmodule

112
RTL/top.v
View File

@ -31,8 +31,8 @@ module GottaGoFaZt3r(
output SLAVE_n,
output MTACK_n,
// RAM
output BUFDIR,
output BUFOE_n,
output reg BUFDIR,
output reg BUFOE_n,
output CAS_n,
output CKE,
output [1:0] CS_n,
@ -44,6 +44,8 @@ module GottaGoFaZt3r(
output WE_n
);
`include "globalparams.vh"
assign MEMCLK = ~CLK;
// Synchronizers
@ -72,9 +74,7 @@ end
// Autoconf
wire [3:0] autoconfig_dout;
wire autoconfig_cycle;
wire autoconfig_cfgout;
wire configured;
// addr_match comes from the autoconfig unit
// At reset it is 4'hF to match autoconfig cycles
@ -88,6 +88,9 @@ wire [3:0] addr_match;
reg [27:8] ADDR;
reg match;
wire configured;
wire validspace = FC[1] ^ FC[0]; // 1 when FC indicates user/supervisor data/program space
always @(negedge FCS_n or negedge RST_n)
begin
@ -95,6 +98,7 @@ begin
ADDR <= 20'b0;
match <= 1'b0;
end else begin
BUFDIR <= READ;
ADDR[27:8] <= A[27:8];
if (AD[31:28] == addr_match) begin
// Match 8 address bits when unconfigured (8'hFF) but only 4 when configured (256MB Blocks)
@ -105,32 +109,90 @@ begin
end
end
reg [1:0] z3_state;
reg dtack;
reg ram_cycle;
reg autoconfig_cycle;
wire autoconfig_dtack;
wire ram_dtack;
wire shutup;
always @(posedge CLK or negedge RST_n)
begin
if (!RST_n) begin
z3_state <= Z3_IDLE;
dtack <= 1'b0;
ram_cycle <= 1'b0;
autoconfig_cycle <= 1'b0;
end else begin
case (z3_state)
Z3_IDLE:
begin
dtack <= 0;
if (!FCS_n_sync[1] && match && validspace) begin
z3_state <= Z3_START;
autoconfig_cycle <= match && !configured && !shutup;
ram_cycle <= match && configured;
end else begin
autoconfig_cycle <= 0;
ram_cycle <= 0;
z3_state <= Z3_IDLE;
end
end
Z3_START:
begin
if (FCS_n_sync[1]) begin
z3_state <= Z3_IDLE;
end else if ((!DS0_n_sync[1] || !DS1_n_sync[1] || !DS2_n_sync[1] || !DS3_n_sync[1]) && DOE) begin
z3_state <= Z3_DATA;
end else begin
z3_state <= Z3_START;
end
end
Z3_DATA:
begin
if (FCS_n_sync[1]) begin
z3_state <= Z3_IDLE;
end else if (autoconfig_dtack && autoconfig_cycle || ram_dtack && ram_cycle) begin
z3_state <= Z3_END;
end
end
Z3_END:
begin
if (FCS_n_sync[1]) begin
z3_state <= Z3_IDLE;
ram_cycle <= 0;
autoconfig_cycle <= 0;
dtack <= 0;
end else begin
z3_state <= Z3_END;
dtack <= 1;
end
end
endcase
end
end
Autoconfig AUTOCONFIG (
.match (match),
.addr_match (addr_match),
.ADDRL ({ADDR[8], A[7:2]}),
.FCS_n (FCS_n_sync[1]),
.CLK (CLK),
.READ (READ),
.DS_n (DS3_n_sync[1]),
.CFGIN_n (CFGIN_n),
.DIN (AD[31:28]),
.FC (FC[2:0]),
.RESET_n (RST_n),
.CFGOUT_n (autoconfig_cfgout),
.ram_cycle (ram_cycle),
.autoconfig_cycle (autoconfig_cycle),
.dtack (autoconfig_dtack),
.configured (configured),
.DOUT (autoconfig_dout),
.SENSEZ3 (SENSEZ3)
.z3_state (z3_state),
.shutup (shutup)
);
SDRAM SDRAM (
.ADDR ({ADDR[27:8], A[7:2]}),
.DS_n ({DS3_n_sync[1], DS2_n_sync[1], DS1_n_sync[1], DS0_n_sync[1]}),
.DOE (DOE),
.FCS_n (FCS_n_sync[1]),
.ram_cycle (ram_cycle),
.RESET_n (RST_n),
.RW (READ),
@ -144,20 +206,30 @@ SDRAM SDRAM (
.WE_n (WE_n),
.CKE (CKE),
.DQM_n (DQM_n),
.DTACK_EN (ram_dtack),
.MTCR_n (MTCR_n),
.configured (configured)
.dtack (ram_dtack),
.configured (configured),
.z3_state (z3_state)
);
assign AD[31:28] = (autoconfig_cycle && BERR_n && DOE && READ && !DS_n[3]) ? autoconfig_dout[3:0] : 4'bZ;
assign AD[31:28] = (autoconfig_cycle && BERR_n && DOE && READ) ? autoconfig_dout[3:0] : 4'bZ;
always @(posedge CLK or posedge FCS_n or negedge BERR_n)
begin
if (FCS_n) begin
BUFOE_n <= 1;
end else if (!BERR_n) begin
BUFOE_n <= 1;
end else begin
if (!FCS_n_sync[1] && ram_cycle && DOE)
BUFOE_n <= 0;
end
end
assign BUFOE_n = !ram_cycle || FCS_n || !DOE || !BERR_n;
assign BUFDIR = READ;
assign CFGOUT_n = (SENSEZ3) ? autoconfig_cfgout : CFGIN_n;
assign SLAVE_n = !(!FCS_n && (autoconfig_cycle || ram_cycle));
assign DTACK_n = (!SLAVE_n) ? !(ram_dtack || autoconfig_dtack) : 1'bZ;
assign SLAVE_n = !(!FCS_n && match && validspace);
assign DTACK_n = (!SLAVE_n) ? !dtack : 1'bZ;
assign MTACK_n = 1'bZ;
endmodule