[SC64][FW] EEPROM 4/16K save type implementation

This commit is contained in:
Polprzewodnikowy 2020-10-10 04:38:26 +02:00
parent 7025f39fcc
commit 160ff68af3
8 changed files with 580 additions and 715 deletions

View File

@ -165,7 +165,7 @@ set_location_assignment PIN_11 -to io_pmod[7]
set_location_assignment PIN_22 -to io_rtc_sda
set_location_assignment PIN_21 -to o_rtc_scl
set_location_assignment PIN_17 -to o_led
set_global_assignment -name OPTIMIZATION_MODE "HIGH PERFORMANCE EFFORT"
set_global_assignment -name OPTIMIZATION_MODE BALANCED
set_global_assignment -name ENABLE_SIGNALTAP ON
set_global_assignment -name USE_SIGNALTAP_FILE misc/SignalTapLogicAnalyzer.stp
set_global_assignment -name RESERVE_ALL_UNUSED_PINS_WEAK_PULLUP "AS INPUT TRI-STATED WITH WEAK PULL-UP"
@ -189,6 +189,7 @@ set_global_assignment -name ROUTER_CLOCKING_TOPOLOGY_ANALYSIS ON
set_instance_assignment -name GLOBAL_SIGNAL GLOBAL_CLOCK -to "pll:sys_pll|altpll:altpll_component|pll_altpll:auto_generated|wire_pll1_clk[0]"
set_instance_assignment -name GLOBAL_SIGNAL GLOBAL_CLOCK -to "pll:sys_pll|altpll:altpll_component|pll_altpll:auto_generated|wire_pll1_clk[1]"
set_global_assignment -name FITTER_EFFORT "STANDARD FIT"
set_global_assignment -name VERILOG_FILE rtl/n64_si.v
set_global_assignment -name VERILOG_FILE rtl/cart_config.v
set_global_assignment -name VERILOG_FILE rtl/sdram.v
set_global_assignment -name VERILOG_FILE rtl/external/wbsdram.v
@ -204,5 +205,6 @@ set_global_assignment -name QIP_FILE rtl/intel/gpio/gpio_ddro.qip
set_global_assignment -name QIP_FILE rtl/intel/fifo/fifo_bus_to_pc.qip
set_global_assignment -name QIP_FILE rtl/intel/fifo/fifo_pc_to_bus.qip
set_global_assignment -name SIGNALTAP_FILE misc/SignalTapLogicAnalyzer.stp
set_global_assignment -name QIP_FILE rtl/intel/ram/ram_n64_eeprom.qip
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
set_global_assignment -name SLD_FILE db/SignalTapLogicAnalyzer_auto_stripped.stp

File diff suppressed because one or more lines are too long

View File

@ -5,9 +5,11 @@ module address_decoder (
output o_flash,
output o_flash_cfg,
output o_sdram,
output o_eeprom,
input i_flash_enable,
input i_sdram_enable,
input i_eeprom_pi_enable,
output o_address_valid
);
@ -32,6 +34,11 @@ module address_decoder (
assign o_sdram = i_sdram_enable && (i_address[31:SDRAM_WIDTH] == SDRAM_ADDR[31:SDRAM_WIDTH]);
assign o_address_valid = (|{o_cart_config, o_flash, o_flash_cfg, o_sdram});
localparam EEPROM_ADDR = 32'h1D00_0000;
localparam EEPROM_WIDTH = 11;
assign o_eeprom = i_eeprom_pi_enable && (i_address[31:EEPROM_WIDTH] == EEPROM_ADDR[31:EEPROM_WIDTH]);
assign o_address_valid = (|{o_cart_config, o_flash, o_flash_cfg, o_sdram, o_eeprom});
endmodule

View File

@ -11,61 +11,57 @@ module cart_config (
output reg o_ack,
input [31:0] i_address,
input [31:0] i_data,
output [31:0] o_data,
output reg [31:0] o_data,
input i_n64_disabled,
output o_flash_enable,
output o_sdram_enable
output o_sdram_enable,
output o_eeprom_pi_enable,
output o_eeprom_enable,
output o_eeprom_16k_enable
);
reg [1:0] r_cart_config;
reg [4:0] r_cart_config;
reg [7:0] r_cic_type;
wire [31:0] w_regs [1:0];
assign w_regs[0] = {30'd0, r_cart_config};
assign w_regs[1] = {24'd0, r_cic_type};
always @(*) begin
o_data = 32'd0;
if (!i_address[2]) o_data = {27'd0, r_cart_config};
if (i_address[2]) o_data = {24'd0, r_cic_type};
end
assign o_data = w_regs[i_address[2]];
assign o_flash_enable = r_cart_config[0];
assign o_sdram_enable = r_cart_config[1];
assign {
o_eeprom_16k_enable,
o_eeprom_enable,
o_eeprom_pi_enable,
o_sdram_enable,
o_flash_enable,
} = r_cart_config;
reg r_last_n64_reset;
reg r_last_n64_nmi;
wire w_n64_reset_op = !i_n64_disabled && !r_last_n64_reset && i_n64_reset;
wire w_n64_nmi_op = !i_n64_disabled && !r_last_n64_nmi && i_n64_nmi;
wire w_n64_reset_op = !i_n64_disabled && ((!r_last_n64_reset && i_n64_reset) || (!r_last_n64_nmi && i_n64_nmi));
always @(posedge i_clk or posedge i_reset) begin
if (i_reset) begin
r_last_n64_reset <= 1'b0;
r_last_n64_nmi <= 1'b0;
end else begin
r_last_n64_reset <= i_n64_reset;
r_last_n64_nmi <= i_n64_nmi;
end
end
always @(posedge i_clk or posedge i_reset or posedge w_n64_reset_op or posedge w_n64_nmi_op) begin
if (i_reset || w_n64_reset_op || w_n64_nmi_op) begin
r_cart_config <= 2'b01;
end else begin
if (i_select && i_write_rq && !i_address[2]) r_cart_config <= i_data[1:0];
end
end
always @(posedge i_clk or posedge i_reset) begin
if (i_reset) begin
r_cic_type <= 8'd0;
end else begin
if (i_select && i_write_rq && i_address[2]) r_cic_type <= i_data[7:0];
end
always @(posedge i_clk) begin
r_last_n64_reset <= i_n64_reset;
r_last_n64_nmi <= i_n64_nmi;
end
always @(posedge i_clk) begin
o_ack <= 1'b0;
if (i_select && (i_read_rq || i_write_rq)) o_ack <= 1'b1;
if (i_reset) r_cart_config[4:0] <= 5'b00001;
if (w_n64_reset_op) r_cart_config[2:0] <= 3'b001;
if (!i_reset && i_select && i_write_rq && !i_address[2]) r_cart_config <= i_data[4:0];
end
always @(posedge i_clk) begin
if (i_reset) r_cic_type <= 8'd0;
if (!i_reset && i_select && i_write_rq && i_address[2]) r_cic_type <= i_data[7:0];
end
always @(posedge i_clk) begin
o_ack <= !i_reset && i_select && (i_read_rq || i_write_rq);
end
endmodule

View File

@ -0,0 +1,4 @@
set_global_assignment -name IP_TOOL_NAME "RAM: 2-PORT"
set_global_assignment -name IP_TOOL_VERSION "20.1"
set_global_assignment -name IP_GENERATED_DEVICE_FAMILY "{MAX 10}"
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "ram_n64_eeprom.v"]

View File

@ -0,0 +1,243 @@
// megafunction wizard: %RAM: 2-PORT%
// GENERATION: STANDARD
// VERSION: WM1.0
// MODULE: altsyncram
// ============================================================
// File Name: ram_n64_eeprom.v
// Megafunction Name(s):
// altsyncram
//
// Simulation Library Files(s):
// altera_mf
// ============================================================
// ************************************************************
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
//
// 20.1.0 Build 711 06/05/2020 SJ Lite Edition
// ************************************************************
//Copyright (C) 2020 Intel Corporation. All rights reserved.
//Your use of Intel Corporation's design tools, logic functions
//and other software and tools, and any partner logic
//functions, and any output files from any of the foregoing
//(including device programming or simulation files), and any
//associated documentation or information are expressly subject
//to the terms and conditions of the Intel Program License
//Subscription Agreement, the Intel Quartus Prime License Agreement,
//the Intel FPGA IP License Agreement, or other applicable license
//agreement, including, without limitation, that your use is for
//the sole purpose of programming logic devices manufactured by
//Intel and sold by Intel or its authorized distributors. Please
//refer to the applicable agreement for further details, at
//https://fpgasoftware.intel.com/eula.
// synopsys translate_off
`timescale 1 ps / 1 ps
// synopsys translate_on
module ram_n64_eeprom (
address_a,
address_b,
clock,
data_a,
data_b,
wren_a,
wren_b,
q_a,
q_b);
input [10:0] address_a;
input [8:0] address_b;
input clock;
input [7:0] data_a;
input [31:0] data_b;
input wren_a;
input wren_b;
output [7:0] q_a;
output [31:0] q_b;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_off
`endif
tri1 clock;
tri0 wren_a;
tri0 wren_b;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_on
`endif
wire [7:0] sub_wire0;
wire [31:0] sub_wire1;
wire [7:0] q_a = sub_wire0[7:0];
wire [31:0] q_b = sub_wire1[31:0];
altsyncram altsyncram_component (
.address_a (address_a),
.address_b (address_b),
.clock0 (clock),
.data_a (data_a),
.data_b (data_b),
.wren_a (wren_a),
.wren_b (wren_b),
.q_a (sub_wire0),
.q_b (sub_wire1),
.aclr0 (1'b0),
.aclr1 (1'b0),
.addressstall_a (1'b0),
.addressstall_b (1'b0),
.byteena_a (1'b1),
.byteena_b (1'b1),
.clock1 (1'b1),
.clocken0 (1'b1),
.clocken1 (1'b1),
.clocken2 (1'b1),
.clocken3 (1'b1),
.eccstatus (),
.rden_a (1'b1),
.rden_b (1'b1));
defparam
altsyncram_component.address_reg_b = "CLOCK0",
altsyncram_component.clock_enable_input_a = "BYPASS",
altsyncram_component.clock_enable_input_b = "BYPASS",
altsyncram_component.clock_enable_output_a = "BYPASS",
altsyncram_component.clock_enable_output_b = "BYPASS",
altsyncram_component.indata_reg_b = "CLOCK0",
altsyncram_component.intended_device_family = "MAX 10",
altsyncram_component.lpm_type = "altsyncram",
altsyncram_component.numwords_a = 2048,
altsyncram_component.numwords_b = 512,
altsyncram_component.operation_mode = "BIDIR_DUAL_PORT",
altsyncram_component.outdata_aclr_a = "NONE",
altsyncram_component.outdata_aclr_b = "NONE",
altsyncram_component.outdata_reg_a = "CLOCK0",
altsyncram_component.outdata_reg_b = "CLOCK0",
altsyncram_component.power_up_uninitialized = "FALSE",
altsyncram_component.read_during_write_mode_mixed_ports = "DONT_CARE",
altsyncram_component.read_during_write_mode_port_a = "NEW_DATA_WITH_NBE_READ",
altsyncram_component.read_during_write_mode_port_b = "NEW_DATA_WITH_NBE_READ",
altsyncram_component.widthad_a = 11,
altsyncram_component.widthad_b = 9,
altsyncram_component.width_a = 8,
altsyncram_component.width_b = 32,
altsyncram_component.width_byteena_a = 1,
altsyncram_component.width_byteena_b = 1,
altsyncram_component.wrcontrol_wraddress_reg_b = "CLOCK0";
endmodule
// ============================================================
// CNX file retrieval info
// ============================================================
// Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0"
// Retrieval info: PRIVATE: ADDRESSSTALL_B NUMERIC "0"
// Retrieval info: PRIVATE: BYTEENA_ACLR_A NUMERIC "0"
// Retrieval info: PRIVATE: BYTEENA_ACLR_B NUMERIC "0"
// Retrieval info: PRIVATE: BYTE_ENABLE_A NUMERIC "0"
// Retrieval info: PRIVATE: BYTE_ENABLE_B NUMERIC "0"
// Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8"
// Retrieval info: PRIVATE: BlankMemory NUMERIC "1"
// Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0"
// Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_B NUMERIC "0"
// Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0"
// Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_B NUMERIC "0"
// Retrieval info: PRIVATE: CLRdata NUMERIC "0"
// Retrieval info: PRIVATE: CLRq NUMERIC "0"
// Retrieval info: PRIVATE: CLRrdaddress NUMERIC "0"
// Retrieval info: PRIVATE: CLRrren NUMERIC "0"
// Retrieval info: PRIVATE: CLRwraddress NUMERIC "0"
// Retrieval info: PRIVATE: CLRwren NUMERIC "0"
// Retrieval info: PRIVATE: Clock NUMERIC "0"
// Retrieval info: PRIVATE: Clock_A NUMERIC "0"
// Retrieval info: PRIVATE: Clock_B NUMERIC "0"
// Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0"
// Retrieval info: PRIVATE: INDATA_ACLR_B NUMERIC "0"
// Retrieval info: PRIVATE: INDATA_REG_B NUMERIC "1"
// Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A"
// Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0"
// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "MAX 10"
// Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0"
// Retrieval info: PRIVATE: JTAG_ID STRING "NONE"
// Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0"
// Retrieval info: PRIVATE: MEMSIZE NUMERIC "16384"
// Retrieval info: PRIVATE: MEM_IN_BITS NUMERIC "1"
// Retrieval info: PRIVATE: MIFfilename STRING ""
// Retrieval info: PRIVATE: OPERATION_MODE NUMERIC "3"
// Retrieval info: PRIVATE: OUTDATA_ACLR_B NUMERIC "0"
// Retrieval info: PRIVATE: OUTDATA_REG_B NUMERIC "1"
// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0"
// Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_MIXED_PORTS NUMERIC "2"
// Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_A NUMERIC "4"
// Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_B NUMERIC "4"
// Retrieval info: PRIVATE: REGdata NUMERIC "1"
// Retrieval info: PRIVATE: REGq NUMERIC "1"
// Retrieval info: PRIVATE: REGrdaddress NUMERIC "0"
// Retrieval info: PRIVATE: REGrren NUMERIC "0"
// Retrieval info: PRIVATE: REGwraddress NUMERIC "1"
// Retrieval info: PRIVATE: REGwren NUMERIC "1"
// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
// Retrieval info: PRIVATE: USE_DIFF_CLKEN NUMERIC "0"
// Retrieval info: PRIVATE: UseDPRAM NUMERIC "1"
// Retrieval info: PRIVATE: VarWidth NUMERIC "1"
// Retrieval info: PRIVATE: WIDTH_READ_A NUMERIC "8"
// Retrieval info: PRIVATE: WIDTH_READ_B NUMERIC "32"
// Retrieval info: PRIVATE: WIDTH_WRITE_A NUMERIC "8"
// Retrieval info: PRIVATE: WIDTH_WRITE_B NUMERIC "32"
// Retrieval info: PRIVATE: WRADDR_ACLR_B NUMERIC "0"
// Retrieval info: PRIVATE: WRADDR_REG_B NUMERIC "1"
// Retrieval info: PRIVATE: WRCTRL_ACLR_B NUMERIC "0"
// Retrieval info: PRIVATE: enable NUMERIC "0"
// Retrieval info: PRIVATE: rden NUMERIC "0"
// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
// Retrieval info: CONSTANT: ADDRESS_REG_B STRING "CLOCK0"
// Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS"
// Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_B STRING "BYPASS"
// Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS"
// Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_B STRING "BYPASS"
// Retrieval info: CONSTANT: INDATA_REG_B STRING "CLOCK0"
// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "MAX 10"
// Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram"
// Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "2048"
// Retrieval info: CONSTANT: NUMWORDS_B NUMERIC "512"
// Retrieval info: CONSTANT: OPERATION_MODE STRING "BIDIR_DUAL_PORT"
// Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE"
// Retrieval info: CONSTANT: OUTDATA_ACLR_B STRING "NONE"
// Retrieval info: CONSTANT: OUTDATA_REG_A STRING "CLOCK0"
// Retrieval info: CONSTANT: OUTDATA_REG_B STRING "CLOCK0"
// Retrieval info: CONSTANT: POWER_UP_UNINITIALIZED STRING "FALSE"
// Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_MIXED_PORTS STRING "DONT_CARE"
// Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_PORT_A STRING "NEW_DATA_WITH_NBE_READ"
// Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_PORT_B STRING "NEW_DATA_WITH_NBE_READ"
// Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "11"
// Retrieval info: CONSTANT: WIDTHAD_B NUMERIC "9"
// Retrieval info: CONSTANT: WIDTH_A NUMERIC "8"
// Retrieval info: CONSTANT: WIDTH_B NUMERIC "32"
// Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1"
// Retrieval info: CONSTANT: WIDTH_BYTEENA_B NUMERIC "1"
// Retrieval info: CONSTANT: WRCONTROL_WRADDRESS_REG_B STRING "CLOCK0"
// Retrieval info: USED_PORT: address_a 0 0 11 0 INPUT NODEFVAL "address_a[10..0]"
// Retrieval info: USED_PORT: address_b 0 0 9 0 INPUT NODEFVAL "address_b[8..0]"
// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT VCC "clock"
// Retrieval info: USED_PORT: data_a 0 0 8 0 INPUT NODEFVAL "data_a[7..0]"
// Retrieval info: USED_PORT: data_b 0 0 32 0 INPUT NODEFVAL "data_b[31..0]"
// Retrieval info: USED_PORT: q_a 0 0 8 0 OUTPUT NODEFVAL "q_a[7..0]"
// Retrieval info: USED_PORT: q_b 0 0 32 0 OUTPUT NODEFVAL "q_b[31..0]"
// Retrieval info: USED_PORT: wren_a 0 0 0 0 INPUT GND "wren_a"
// Retrieval info: USED_PORT: wren_b 0 0 0 0 INPUT GND "wren_b"
// Retrieval info: CONNECT: @address_a 0 0 11 0 address_a 0 0 11 0
// Retrieval info: CONNECT: @address_b 0 0 9 0 address_b 0 0 9 0
// Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0
// Retrieval info: CONNECT: @data_a 0 0 8 0 data_a 0 0 8 0
// Retrieval info: CONNECT: @data_b 0 0 32 0 data_b 0 0 32 0
// Retrieval info: CONNECT: @wren_a 0 0 0 0 wren_a 0 0 0 0
// Retrieval info: CONNECT: @wren_b 0 0 0 0 wren_b 0 0 0 0
// Retrieval info: CONNECT: q_a 0 0 8 0 @q_a 0 0 8 0
// Retrieval info: CONNECT: q_b 0 0 32 0 @q_b 0 0 32 0
// Retrieval info: GEN_FILE: TYPE_NORMAL ram_n64_eeprom.v TRUE
// Retrieval info: GEN_FILE: TYPE_NORMAL ram_n64_eeprom.inc FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL ram_n64_eeprom.cmp FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL ram_n64_eeprom.bsf FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL ram_n64_eeprom_inst.v FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL ram_n64_eeprom_bb.v FALSE
// Retrieval info: LIB_FILE: altera_mf

210
fw/rtl/n64_si.v Normal file
View File

@ -0,0 +1,210 @@
module n64_si (
input i_clk,
input i_reset,
input i_si_clk,
input i_si_reset,
input i_si_dq,
output reg o_si_dq,
input i_eeprom_select,
input i_read_rq,
input i_write_rq,
output reg o_ack,
input [31:0] i_address,
input [31:0] i_data,
output [31:0] o_data,
input i_eeprom_enable,
input i_eeprom_16k_enable
);
localparam CMD_EEPROM_STATUS = 8'h00;
localparam CMD_EEPROM_READ = 8'h04;
localparam CMD_EEPROM_WRITE = 8'h05;
localparam EEPROM_4K_ID = 8'h80;
localparam EEPROM_16K_ID = 8'hC0;
reg r_last_si_clk;
reg r_last_si_dq;
wire w_si_clk_falling_edge = !i_reset && !i_si_reset && r_last_si_clk && !i_si_clk;
wire w_si_clk_rising_edge = !i_reset && !i_si_reset && !r_last_si_clk && i_si_clk;
wire w_si_dq_falling_edge = r_last_si_dq && !i_si_dq;
wire w_si_dq_rising_edge = !r_last_si_dq && i_si_dq;
always @(posedge i_clk) begin
r_last_si_clk <= i_si_clk;
if (w_si_clk_rising_edge) r_last_si_dq <= i_si_dq;
end
// RX module
reg r_rx_enabled;
reg [2:0] r_rx_sub_bit_counter;
reg [2:0] r_rx_bit_counter;
reg [3:0] r_rx_byte_counter;
reg [7:0] r_rx_buffer;
reg r_rx_byte_ready;
reg r_rx_finished, r_last_rx_finished;
wire w_rx_sub_bit_counter_timeout = &r_rx_sub_bit_counter;
wire w_rx_bit_value = r_rx_sub_bit_counter <= 3'd4;
wire w_rx_start = r_last_rx_finished && !r_rx_finished;
wire w_rx_finish = !r_last_rx_finished && r_rx_finished;
always @(posedge i_clk) begin
r_rx_byte_ready <= 1'b0;
r_last_rx_finished <= r_rx_finished;
if (r_rx_enabled && w_si_clk_rising_edge) begin
if (w_rx_sub_bit_counter_timeout) r_rx_finished <= 1'b1;
else r_rx_sub_bit_counter <= r_rx_sub_bit_counter + 3'd1;
if (w_si_dq_falling_edge) begin
r_rx_sub_bit_counter <= 3'd0;
if (r_rx_finished) begin
r_rx_bit_counter <= 3'd0;
r_rx_byte_counter <= 4'b1111;
end
r_rx_finished <= 1'b0;
end
if (w_si_dq_rising_edge) begin
r_rx_bit_counter <= r_rx_bit_counter + 3'd1;
r_rx_buffer <= {r_rx_buffer[6:0], w_rx_bit_value};
if (&r_rx_bit_counter) begin
r_rx_byte_counter <= r_rx_byte_counter + 4'd1;
r_rx_byte_ready <= 1'b1;
end
end
end
end
reg r_tx_finished;
reg r_cmd_eeprom_status;
reg r_cmd_eeprom_read;
reg r_cmd_eeprom_write;
wire w_cmd_valid = r_cmd_eeprom_status || r_cmd_eeprom_read || r_cmd_eeprom_write;
wire w_cmd_op = r_rx_byte_ready && r_rx_byte_counter == 4'd0;
always @(posedge i_clk) begin
if (i_reset || i_si_reset || w_rx_start || r_tx_finished) begin
r_cmd_eeprom_status <= 1'b0;
r_cmd_eeprom_read <= 1'b0;
r_cmd_eeprom_write <= 1'b0;
end else if (w_cmd_op) begin
if (i_eeprom_enable) begin
r_cmd_eeprom_status <= r_rx_buffer == CMD_EEPROM_STATUS;
r_cmd_eeprom_read <= r_rx_buffer == CMD_EEPROM_READ;
r_cmd_eeprom_write <= r_rx_buffer == CMD_EEPROM_WRITE;
end
end
end
reg r_eeprom_read_rq;
reg [10:0] r_eeprom_address;
wire w_eeprom_write_op = r_rx_byte_ready && r_rx_byte_counter >= 4'd2 && r_cmd_eeprom_write;
wire w_eeprom_address_op = r_rx_byte_ready && r_rx_byte_counter == 4'd1 && (r_cmd_eeprom_read || r_cmd_eeprom_write);
wire w_eeprom_address_next_op = r_eeprom_read_rq || w_eeprom_write_op;
always @(posedge i_clk) begin
if (w_eeprom_address_op) r_eeprom_address <= {r_rx_buffer, 3'b000};
if (w_eeprom_address_next_op) r_eeprom_address[2:0] <= r_eeprom_address[2:0] + 3'd1;
end
// TX module
reg [2:0] r_tx_sub_bit_counter;
reg [2:0] r_tx_bit_counter;
reg [3:0] r_tx_byte_counter;
reg [3:0] r_tx_bytes_to_send;
reg [7:0] r_tx_data;
wire [7:0] w_eeprom_o_data;
wire w_tx_current_bit = r_tx_data[3'd7 - r_tx_bit_counter];
wire w_tx_stop_bit = r_tx_byte_counter == r_tx_bytes_to_send;
always @(*) begin
r_tx_data = 8'h00;
if (r_cmd_eeprom_status && r_tx_byte_counter == 4'd1) r_tx_data = i_eeprom_16k_enable ? EEPROM_16K_ID : EEPROM_4K_ID;
if (r_cmd_eeprom_read) r_tx_data = w_eeprom_o_data;
end
always @(posedge i_clk) begin
if (i_reset || i_si_reset) begin
o_si_dq <= 1'b1;
r_rx_enabled <= 1'b1;
r_tx_finished <= 1'b0;
r_eeprom_read_rq <= 1'b0;
end else begin
r_tx_finished <= 1'b0;
r_eeprom_read_rq <= 1'b0;
if (w_rx_finish && w_cmd_valid) begin
r_rx_enabled <= 1'b0;
r_tx_sub_bit_counter <= 3'd0;
r_tx_bit_counter <= 3'd0;
r_tx_byte_counter <= 4'd0;
r_tx_bytes_to_send <= 4'd0;
if (r_cmd_eeprom_status) r_tx_bytes_to_send <= 4'd3;
if (r_cmd_eeprom_read) r_tx_bytes_to_send <= 4'd8;
if (r_cmd_eeprom_write) r_tx_bytes_to_send <= 4'd1;
end
if (!r_rx_enabled) begin
if (w_si_clk_falling_edge) begin
r_tx_sub_bit_counter <= r_tx_sub_bit_counter + 3'd1;
if (r_tx_sub_bit_counter == 3'd0) o_si_dq <= 1'b0;
if ((w_tx_current_bit && r_tx_sub_bit_counter == 3'd2) ||
(!w_tx_current_bit && r_tx_sub_bit_counter == 3'd6) ||
(w_tx_stop_bit && r_tx_sub_bit_counter == 3'd4)) begin
o_si_dq <= 1'b1;
end
if (&r_tx_sub_bit_counter) begin
if (w_tx_stop_bit) begin
r_rx_enabled <= 1'b1;
r_tx_finished <= 1'b1;
end
r_tx_bit_counter <= r_tx_bit_counter + 3'd1;
if (&r_tx_bit_counter) begin
r_eeprom_read_rq <= 1'b1;
r_tx_byte_counter <= r_tx_byte_counter + 4'd1;
end
end
end
end
end
end
// Block RAM
ram_n64_eeprom ram_n64_eeprom_inst (
.clock(i_clk),
.address_a(r_eeprom_address),
.data_a(r_rx_buffer),
.wren_a(w_eeprom_write_op),
.q_a(w_eeprom_o_data),
.address_b(i_address[10:2]),
.data_b({i_data[7:0], i_data[15:8], i_data[23:16], i_data[31:24]}),
.wren_b(!i_reset && i_eeprom_select && i_write_rq),
.q_b({o_data[7:0], o_data[15:8], o_data[23:16], o_data[31:24]})
);
// Bus logic
always @(posedge i_clk) begin
o_ack <= !i_reset && i_eeprom_select && (i_read_rq || i_write_rq);
end
endmodule

View File

@ -82,47 +82,19 @@ module top (
reg r_n64_write_ff1, r_n64_write_ff2;
reg r_n64_si_clk_ff1, r_n64_si_clk_ff2;
reg r_n64_si_dq_ff1, r_n64_si_dq_ff2;
reg r_n64_cic_clk_ff1, r_n64_cic_clk_ff2;
always @(posedge w_sys_clk) begin
{r_n64_nmi_ff2, r_n64_nmi_ff1} <= {r_n64_nmi_ff1, i_n64_nmi};
{r_n64_reset_ff2, r_n64_reset_ff1} <= {r_n64_reset_ff1, i_n64_reset};
always @(posedge w_sys_clk or posedge w_sys_reset) begin
if (w_sys_reset) begin
r_n64_nmi_ff1 <= 1'b0;
r_n64_nmi_ff2 <= 1'b0;
{r_n64_alel_ff2, r_n64_alel_ff1} <= {r_n64_alel_ff1, i_n64_pi_alel};
{r_n64_aleh_ff2, r_n64_aleh_ff1} <= {r_n64_aleh_ff1, i_n64_pi_aleh};
{r_n64_read_ff2, r_n64_read_ff1} <= {r_n64_read_ff1, i_n64_pi_read};
{r_n64_write_ff2, r_n64_write_ff1} <= {r_n64_write_ff1, i_n64_pi_write};
r_n64_reset_ff1 <= 1'b0;
r_n64_reset_ff2 <= 1'b0;
r_n64_alel_ff1 <= 1'b0;
r_n64_alel_ff2 <= 1'b0;
r_n64_aleh_ff1 <= 1'b0;
r_n64_aleh_ff2 <= 1'b0;
r_n64_read_ff1 <= 1'b0;
r_n64_read_ff2 <= 1'b0;
r_n64_write_ff1 <= 1'b0;
r_n64_write_ff2 <= 1'b0;
r_n64_si_clk_ff1 <= 1'b0;
r_n64_si_clk_ff2 <= 1'b0;
r_n64_cic_clk_ff1 <= 1'b0;
r_n64_cic_clk_ff2 <= 1'b0;
end else begin
{r_n64_nmi_ff2, r_n64_nmi_ff1} <= {r_n64_nmi_ff1, i_n64_nmi};
{r_n64_reset_ff2, r_n64_reset_ff1} <= {r_n64_reset_ff1, i_n64_reset};
{r_n64_alel_ff2, r_n64_alel_ff1} <= {r_n64_alel_ff1, i_n64_pi_alel};
{r_n64_aleh_ff2, r_n64_aleh_ff1} <= {r_n64_aleh_ff1, i_n64_pi_aleh};
{r_n64_read_ff2, r_n64_read_ff1} <= {r_n64_read_ff1, i_n64_pi_read};
{r_n64_write_ff2, r_n64_write_ff1} <= {r_n64_write_ff1, i_n64_pi_write};
{r_n64_si_clk_ff2, r_n64_si_clk_ff1} <= {r_n64_si_clk_ff1, i_n64_si_clk};
{r_n64_cic_clk_ff2, r_n64_cic_clk_ff1} <= {r_n64_cic_clk_ff1, i_n64_cic_clk};
end
{r_n64_si_clk_ff2, r_n64_si_clk_ff1} <= {r_n64_si_clk_ff1, i_n64_si_clk};
{r_n64_si_dq_ff2, r_n64_si_dq_ff1} <= {r_n64_si_dq_ff1, io_n64_si_dq};
end
// Tri-state connection management
@ -164,7 +136,6 @@ module top (
// Temporary assignments
assign w_n64_si_dq_o = 1'b1;
assign w_n64_cic_dq_o = 1'b1;
assign w_sd_cmd_mode = 1'b0;
assign w_sd_dat_mode = 2'b00;
@ -188,15 +159,15 @@ module top (
wire [31:0] w_pc_i_data;
wire [31:0] w_pc_o_data;
wire w_n64_disable;
wire w_bus_read_rq;
wire w_bus_write_rq;
wire w_bus_ack;
wire [31:0] w_bus_address;
wire [31:0] w_bus_i_data;
reg [31:0] r_bus_i_data;
wire [31:0] w_bus_o_data;
wire w_n64_disable;
assign w_n64_ack = !w_n64_disable && w_bus_ack;
assign w_pc_ack = w_n64_disable && w_bus_ack;
@ -209,9 +180,13 @@ module top (
wire w_flash_select;
wire w_flash_cfg_select;
wire w_sdram_select;
wire w_eeprom_select;
wire w_flash_enable;
wire w_sdram_enable;
wire w_eeprom_pi_enable;
wire w_eeprom_enable;
wire w_eeprom_16k_enable;
wire w_address_valid;
@ -224,12 +199,20 @@ module top (
wire w_sdram_ack;
wire [31:0] w_sdram_o_data;
wire w_eeprom_ack;
wire [31:0] w_eeprom_o_data;
reg r_empty_ack;
assign w_bus_ack = w_cart_config_ack || w_flash_ack || w_sdram_ack || r_empty_ack;
assign w_bus_i_data = w_cart_config_select ? w_cart_config_o_data :
(w_flash_select || w_flash_cfg_select) ? w_flash_o_data :
w_sdram_select ? w_sdram_o_data : 32'hFFFF_FFFF;
assign w_bus_ack = w_cart_config_ack || w_flash_ack || w_sdram_ack || w_eeprom_ack || r_empty_ack;
always @(*) begin
r_bus_i_data = 32'hFFFF_FFFF;
if (w_cart_config_select) r_bus_i_data = w_cart_config_o_data;
if (w_flash_select || w_flash_cfg_select) r_bus_i_data = w_flash_o_data;
if (w_sdram_select) r_bus_i_data = w_sdram_o_data;
if (w_eeprom_select) r_bus_i_data = w_eeprom_o_data;
end
always @(posedge w_sys_clk) begin
r_empty_ack <= !w_address_valid && (w_bus_read_rq || w_bus_write_rq);
@ -264,7 +247,7 @@ module top (
.o_write_rq(w_pc_write_rq),
.i_ack(w_pc_ack),
.o_address(w_pc_address),
.i_data(w_bus_i_data),
.i_data(r_bus_i_data),
.o_data(w_pc_o_data),
.i_bus_active(w_bus_active),
@ -287,12 +270,33 @@ module top (
.o_write_rq(w_n64_write_rq),
.i_ack(w_n64_ack),
.o_address(w_n64_address),
.i_data(w_bus_i_data),
.i_data(r_bus_i_data),
.o_data(w_n64_o_data),
.i_address_valid(w_address_valid)
);
n64_si n64_si_inst (
.i_clk(w_sys_clk),
.i_reset(w_sys_reset),
.i_si_clk(r_n64_si_clk_ff2),
.i_si_reset(~r_n64_reset_ff2),
.i_si_dq(r_n64_si_dq_ff2),
.o_si_dq(w_n64_si_dq_o),
.i_eeprom_select(w_eeprom_select),
.i_read_rq(w_bus_read_rq),
.i_write_rq(w_bus_write_rq),
.o_ack(w_eeprom_ack),
.i_address(w_bus_address),
.i_data(w_bus_o_data),
.o_data(w_eeprom_o_data),
.i_eeprom_enable(w_eeprom_enable),
.i_eeprom_16k_enable(w_eeprom_16k_enable)
);
address_decoder address_decoder_inst (
.i_address(w_bus_address),
@ -300,9 +304,11 @@ module top (
.o_flash(w_flash_select),
.o_flash_cfg(w_flash_cfg_select),
.o_sdram(w_sdram_select),
.o_eeprom(w_eeprom_select),
.i_flash_enable(w_flash_enable),
.i_sdram_enable(w_sdram_enable),
.i_eeprom_pi_enable(w_eeprom_pi_enable),
.o_address_valid(w_address_valid)
);
@ -325,7 +331,10 @@ module top (
.i_n64_disabled(w_n64_disable),
.o_flash_enable(w_flash_enable),
.o_sdram_enable(w_sdram_enable)
.o_sdram_enable(w_sdram_enable),
.o_eeprom_pi_enable(w_eeprom_pi_enable),
.o_eeprom_enable(w_eeprom_enable),
.o_eeprom_16k_enable(w_eeprom_16k_enable)
);
flash flash_inst (