mirror of
https://github.com/LIV2/GottaGoFaZt3r.git
synced 2025-12-06 00:32:44 +00:00
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:
parent
1fc7c53392
commit
0a770dc2d6
File diff suppressed because it is too large
Load Diff
@ -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
4
RTL/globalparams.vh
Normal file
@ -0,0 +1,4 @@
|
||||
localparam Z3_IDLE = 2'd0,
|
||||
Z3_START = 2'd1,
|
||||
Z3_DATA = 2'd2,
|
||||
Z3_END = 2'd3;
|
||||
38
RTL/sdram.v
38
RTL/sdram.v
@ -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
112
RTL/top.v
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user