mirror of
https://github.com/LIV2/GottaGoFaZt3r.git
synced 2025-12-06 00:32:44 +00:00
* Split out ram / autoconf address match * Ensure autoconfig cycles don't run unless CFGIN_n is asserted
240 lines
5.5 KiB
Verilog
240 lines
5.5 KiB
Verilog
/*
|
|
GottaGoFaZt3r
|
|
Copyright 2022 Matthew Harlum
|
|
|
|
GottaGoFaZt3r is licensed under a
|
|
Creative Commons Attribution-ShareAlike 4.0 International License.
|
|
|
|
You should have received a copy of the license along with this
|
|
work. If not, see <http://creativecommons.org/licenses/by-sa/4.0/>.
|
|
*/
|
|
|
|
module GottaGoFaZt3r(
|
|
input [27:2] A,
|
|
inout [31:28] AD,
|
|
input BERR_n,
|
|
input CFGIN_n,
|
|
input CLK,
|
|
input DOE,
|
|
input [3:0] DS_n,
|
|
input E,
|
|
input [2:0] FC,
|
|
input FCS_n,
|
|
input MTCR_n,
|
|
input READ,
|
|
input RST_n,
|
|
input SENSEZ3,
|
|
output TP1,
|
|
output TP2,
|
|
output CFGOUT_n,
|
|
output DTACK_n,
|
|
output SLAVE_n,
|
|
output MTACK_n,
|
|
// RAM
|
|
output reg BUFDIR,
|
|
output reg BUFOE_n,
|
|
output CAS_n,
|
|
output CKE,
|
|
output [1:0] CS_n,
|
|
output [1:0] BA,
|
|
output [3:0] DQM_n,
|
|
output [12:0] MA,
|
|
output MEMCLK,
|
|
output RAS_n,
|
|
output WE_n
|
|
);
|
|
|
|
`include "globalparams.vh"
|
|
|
|
assign MEMCLK = ~CLK;
|
|
|
|
// Synchronizers
|
|
reg [1:0] DS0_n_sync;
|
|
reg [1:0] DS1_n_sync;
|
|
reg [1:0] DS2_n_sync;
|
|
reg [1:0] DS3_n_sync;
|
|
reg [1:0] FCS_n_sync;
|
|
|
|
always @(posedge CLK or negedge RST_n)
|
|
begin
|
|
if (!RST_n) begin
|
|
DS0_n_sync[1:0] <= 2'b11;
|
|
DS1_n_sync[1:0] <= 2'b11;
|
|
DS2_n_sync[1:0] <= 2'b11;
|
|
DS3_n_sync[1:0] <= 2'b11;
|
|
FCS_n_sync[1:0] <= 2'b11;
|
|
end else begin
|
|
DS0_n_sync[1:0] <= {DS0_n_sync[0], DS_n[0]};
|
|
DS1_n_sync[1:0] <= {DS1_n_sync[0], DS_n[1]};
|
|
DS2_n_sync[1:0] <= {DS2_n_sync[0], DS_n[2]};
|
|
DS3_n_sync[1:0] <= {DS3_n_sync[0], DS_n[3]};
|
|
FCS_n_sync[1:0] <= {FCS_n_sync[0], FCS_n};
|
|
end
|
|
end
|
|
|
|
// Autoconf
|
|
wire [3:0] autoconfig_dout;
|
|
wire autoconfig_cfgout;
|
|
|
|
wire [3:0] ram_base_addr;
|
|
|
|
reg [27:8] ADDR;
|
|
reg autoconfig_addr_match;
|
|
reg ram_addr_match;
|
|
|
|
wire match = autoconfig_addr_match || ram_addr_match;
|
|
wire configured;
|
|
wire validspace = FC[1] ^ FC[0]; // 1 when FC indicates user/supervisor data/program space
|
|
wire shutup;
|
|
|
|
// Latch address bits 27-8 on FCS_n asserted
|
|
//
|
|
always @(negedge FCS_n or negedge RST_n)
|
|
begin
|
|
if (!RST_n) begin
|
|
ADDR <= 20'b0;
|
|
ram_addr_match <= 0;
|
|
autoconfig_addr_match <= 0;
|
|
end else begin
|
|
BUFDIR <= READ;
|
|
ADDR[27:8] <= A[27:8];
|
|
|
|
if (AD[31:28] == ram_base_addr && configured) begin
|
|
ram_addr_match <= 1;
|
|
end else begin
|
|
ram_addr_match <= 0;
|
|
end
|
|
|
|
if ({AD[31:28],A[27:24]} == 8'hFF && !configured && !shutup && !CFGIN_n) begin
|
|
autoconfig_addr_match <= 1;
|
|
end else begin
|
|
autoconfig_addr_match <= 0;
|
|
end
|
|
end
|
|
end
|
|
|
|
reg [1:0] z3_state;
|
|
reg dtack;
|
|
reg ram_cycle;
|
|
reg autoconfig_cycle;
|
|
wire autoconfig_dtack;
|
|
wire ram_dtack;
|
|
|
|
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 <= autoconfig_addr_match;
|
|
ram_cycle <= ram_addr_match;
|
|
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 (READ || (!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 (
|
|
.ram_base_addr (ram_base_addr),
|
|
.ADDRL ({ADDR[8], A[7:2]}),
|
|
.FCS_n (FCS_n_sync[1]),
|
|
.CLK (CLK),
|
|
.READ (READ),
|
|
.DIN (AD[31:28]),
|
|
.RESET_n (RST_n),
|
|
.CFGOUT_n (autoconfig_cfgout),
|
|
.autoconfig_cycle (autoconfig_cycle),
|
|
.dtack (autoconfig_dtack),
|
|
.configured (configured),
|
|
.DOUT (autoconfig_dout),
|
|
.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]}),
|
|
.ram_cycle (ram_cycle),
|
|
.RESET_n (RST_n),
|
|
.RW (READ),
|
|
.CLK (CLK),
|
|
.ECLK (E),
|
|
.BA (BA),
|
|
.MADDR (MA),
|
|
.CAS_n (CAS_n),
|
|
.RAS_n (RAS_n),
|
|
.CS_n (CS_n),
|
|
.WE_n (WE_n),
|
|
.CKE (CKE),
|
|
.DQM_n (DQM_n),
|
|
.dtack (ram_dtack),
|
|
.configured (configured),
|
|
.z3_state (z3_state)
|
|
);
|
|
|
|
assign AD[31:28] = (!FCS_n && 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 CFGOUT_n = (SENSEZ3) ? autoconfig_cfgout : CFGIN_n;
|
|
|
|
assign SLAVE_n = !(!FCS_n && match && validspace);
|
|
|
|
assign DTACK_n = (!SLAVE_n) ? !dtack : 1'bZ;
|
|
assign MTACK_n = 1'bZ;
|
|
|
|
endmodule
|
|
|