From 0eae2f445f7e36d18a26567f5ed8c1d218026a47 Mon Sep 17 00:00:00 2001 From: robinsonb5 Date: Tue, 26 Mar 2013 23:20:17 +0000 Subject: [PATCH] Added 2-way cache, 24-meg of RAM supported. (No OSD support yet) --- cores/minimig/fpga/altera/minimig_mist.qsf | 5 +- cores/minimig/rtl/cache/CacheBlockRAM.cmp | 29 + cores/minimig/rtl/cache/CacheBlockRAM.qip | 5 + cores/minimig/rtl/cache/CacheBlockRAM.v | 244 +++++++ cores/minimig/rtl/cache/CacheBlockRAM_bb.v | 180 +++++ cores/minimig/rtl/cache/Cache_DataRAM.qip | 4 + cores/minimig/rtl/cache/Cache_DataRAM.v | 242 +++++++ cores/minimig/rtl/cache/Cache_DataRAM_bb.v | 179 +++++ cores/minimig/rtl/cache/TwoWayCache.v | 415 +++++++++++ cores/minimig/rtl/mist/sdram.vhd | 799 +++++++++++++++------ cores/minimig/rtl/soc/minimig_mist_top.v | 3 +- cores/minimig/rtl/tg68k/TG68K.vhd | 149 +++- 12 files changed, 1980 insertions(+), 274 deletions(-) create mode 100644 cores/minimig/rtl/cache/CacheBlockRAM.cmp create mode 100644 cores/minimig/rtl/cache/CacheBlockRAM.qip create mode 100644 cores/minimig/rtl/cache/CacheBlockRAM.v create mode 100644 cores/minimig/rtl/cache/CacheBlockRAM_bb.v create mode 100644 cores/minimig/rtl/cache/Cache_DataRAM.qip create mode 100644 cores/minimig/rtl/cache/Cache_DataRAM.v create mode 100644 cores/minimig/rtl/cache/Cache_DataRAM_bb.v create mode 100644 cores/minimig/rtl/cache/TwoWayCache.v diff --git a/cores/minimig/fpga/altera/minimig_mist.qsf b/cores/minimig/fpga/altera/minimig_mist.qsf index 923a1ff..1f506f6 100755 --- a/cores/minimig/fpga/altera/minimig_mist.qsf +++ b/cores/minimig/fpga/altera/minimig_mist.qsf @@ -312,6 +312,9 @@ set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to VGA_B[2] set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to VGA_B[1] set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to VGA_B[0] +set_global_assignment -name VERILOG_FILE ../../rtl/cache/TwoWayCache.v +set_global_assignment -name QIP_FILE ../../rtl/cache/CacheBlockRAM.qip +set_global_assignment -name QIP_FILE ../../rtl/cache/Cache_DataRAM.qip set_global_assignment -name QIP_FILE ../../rtl/cycloneiii/MyPLLReconfig.qip set_global_assignment -name QIP_FILE ../../rtl/cycloneiii/MyPLL.qip set_global_assignment -name VHDL_FILE ../../rtl/cycloneiii/PLLWrapper.vhd @@ -323,8 +326,6 @@ set_global_assignment -name VHDL_FILE ../../rtl/tg68k/TG68K.vhd set_global_assignment -name VERILOG_FILE ../../rtl/soc/minimig_mist_top.v set_global_assignment -name VERILOG_FILE ../../rtl/soc/user_io.v set_global_assignment -name VERILOG_FILE ../../rtl/de1/amigaclk.v -set_global_assignment -name VERILOG_FILE ../../lib/altera/i_sync.v -set_global_assignment -name VERILOG_FILE ../../lib/altera/srl16e.v set_global_assignment -name VERILOG_FILE ../../rtl/minimig/Userio.v set_global_assignment -name VERILOG_FILE ../../rtl/minimig/Sprites.v set_global_assignment -name VERILOG_FILE ../../rtl/minimig/Paula.v diff --git a/cores/minimig/rtl/cache/CacheBlockRAM.cmp b/cores/minimig/rtl/cache/CacheBlockRAM.cmp new file mode 100644 index 0000000..57f2834 --- /dev/null +++ b/cores/minimig/rtl/cache/CacheBlockRAM.cmp @@ -0,0 +1,29 @@ +--Copyright (C) 1991-2012 Altera Corporation +--Your use of Altera Corporation's design tools, logic functions +--and other software and tools, and its AMPP 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 Altera Program License +--Subscription Agreement, Altera MegaCore Function License +--Agreement, or other applicable license agreement, including, +--without limitation, that your use is for the sole purpose of +--programming logic devices manufactured by Altera and sold by +--Altera or its authorized distributors. Please refer to the +--applicable agreement for further details. + + +component CacheBlockRAM + PORT + ( + address_a : IN STD_LOGIC_VECTOR (8 DOWNTO 0); + address_b : IN STD_LOGIC_VECTOR (8 DOWNTO 0); + clock : IN STD_LOGIC := '1'; + data_a : IN STD_LOGIC_VECTOR (17 DOWNTO 0); + data_b : IN STD_LOGIC_VECTOR (17 DOWNTO 0); + wren_a : IN STD_LOGIC := '0'; + wren_b : IN STD_LOGIC := '0'; + q_a : OUT STD_LOGIC_VECTOR (17 DOWNTO 0); + q_b : OUT STD_LOGIC_VECTOR (17 DOWNTO 0) + ); +end component; diff --git a/cores/minimig/rtl/cache/CacheBlockRAM.qip b/cores/minimig/rtl/cache/CacheBlockRAM.qip new file mode 100644 index 0000000..4154935 --- /dev/null +++ b/cores/minimig/rtl/cache/CacheBlockRAM.qip @@ -0,0 +1,5 @@ +set_global_assignment -name IP_TOOL_NAME "RAM: 2-PORT" +set_global_assignment -name IP_TOOL_VERSION "12.0" +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "CacheBlockRAM.v"] +set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "CacheBlockRAM_bb.v"] +set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "CacheBlockRAM.cmp"] diff --git a/cores/minimig/rtl/cache/CacheBlockRAM.v b/cores/minimig/rtl/cache/CacheBlockRAM.v new file mode 100644 index 0000000..8e1ea7e --- /dev/null +++ b/cores/minimig/rtl/cache/CacheBlockRAM.v @@ -0,0 +1,244 @@ +// megafunction wizard: %RAM: 2-PORT% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: altsyncram + +// ============================================================ +// File Name: CacheBlockRAM.v +// Megafunction Name(s): +// altsyncram +// +// Simulation Library Files(s): +// altera_mf +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 12.0 Build 232 07/05/2012 SP 1 SJ Web Edition +// ************************************************************ + + +//Copyright (C) 1991-2012 Altera Corporation +//Your use of Altera Corporation's design tools, logic functions +//and other software and tools, and its AMPP 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 Altera Program License +//Subscription Agreement, Altera MegaCore Function License +//Agreement, or other applicable license agreement, including, +//without limitation, that your use is for the sole purpose of +//programming logic devices manufactured by Altera and sold by +//Altera or its authorized distributors. Please refer to the +//applicable agreement for further details. + + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on +module CacheBlockRAM ( + address_a, + address_b, + clock, + data_a, + data_b, + wren_a, + wren_b, + q_a, + q_b); + + input [8:0] address_a; + input [8:0] address_b; + input clock; + input [17:0] data_a; + input [17:0] data_b; + input wren_a; + input wren_b; + output [17:0] q_a; + output [17: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 [17:0] sub_wire0; + wire [17:0] sub_wire1; + wire [17:0] q_a = sub_wire0[17:0]; + wire [17:0] q_b = sub_wire1[17:0]; + + altsyncram altsyncram_component ( + .clock0 (clock), + .wren_a (wren_a), + .address_b (address_b), + .data_b (data_b), + .wren_b (wren_b), + .address_a (address_a), + .data_a (data_a), + .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 = "Cyclone III", + altsyncram_component.lpm_type = "altsyncram", + altsyncram_component.numwords_a = 512, + 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 = "UNREGISTERED", + altsyncram_component.outdata_reg_b = "UNREGISTERED", + altsyncram_component.power_up_uninitialized = "FALSE", + altsyncram_component.ram_block_type = "M9K", + altsyncram_component.read_during_write_mode_mixed_ports = "DONT_CARE", + altsyncram_component.read_during_write_mode_port_a = "NEW_DATA_NO_NBE_READ", + altsyncram_component.read_during_write_mode_port_b = "NEW_DATA_NO_NBE_READ", + altsyncram_component.widthad_a = 9, + altsyncram_component.widthad_b = 9, + altsyncram_component.width_a = 18, + altsyncram_component.width_b = 18, + 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 "9" +// 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 "Cyclone III" +// 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 "9216" +// Retrieval info: PRIVATE: MEM_IN_BITS NUMERIC "0" +// 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 "0" +// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "2" +// Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_MIXED_PORTS NUMERIC "2" +// Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_A NUMERIC "3" +// Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_B NUMERIC "3" +// Retrieval info: PRIVATE: REGdata NUMERIC "1" +// Retrieval info: PRIVATE: REGq NUMERIC "0" +// 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 "0" +// Retrieval info: PRIVATE: WIDTH_READ_A NUMERIC "18" +// Retrieval info: PRIVATE: WIDTH_READ_B NUMERIC "18" +// Retrieval info: PRIVATE: WIDTH_WRITE_A NUMERIC "18" +// Retrieval info: PRIVATE: WIDTH_WRITE_B NUMERIC "18" +// 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 "Cyclone III" +// Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram" +// Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "512" +// 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 "UNREGISTERED" +// Retrieval info: CONSTANT: OUTDATA_REG_B STRING "UNREGISTERED" +// Retrieval info: CONSTANT: POWER_UP_UNINITIALIZED STRING "FALSE" +// Retrieval info: CONSTANT: RAM_BLOCK_TYPE STRING "M9K" +// Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_MIXED_PORTS STRING "DONT_CARE" +// Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_PORT_A STRING "NEW_DATA_NO_NBE_READ" +// Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_PORT_B STRING "NEW_DATA_NO_NBE_READ" +// Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "9" +// Retrieval info: CONSTANT: WIDTHAD_B NUMERIC "9" +// Retrieval info: CONSTANT: WIDTH_A NUMERIC "18" +// Retrieval info: CONSTANT: WIDTH_B NUMERIC "18" +// 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 9 0 INPUT NODEFVAL "address_a[8..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 18 0 INPUT NODEFVAL "data_a[17..0]" +// Retrieval info: USED_PORT: data_b 0 0 18 0 INPUT NODEFVAL "data_b[17..0]" +// Retrieval info: USED_PORT: q_a 0 0 18 0 OUTPUT NODEFVAL "q_a[17..0]" +// Retrieval info: USED_PORT: q_b 0 0 18 0 OUTPUT NODEFVAL "q_b[17..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 9 0 address_a 0 0 9 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 18 0 data_a 0 0 18 0 +// Retrieval info: CONNECT: @data_b 0 0 18 0 data_b 0 0 18 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 18 0 @q_a 0 0 18 0 +// Retrieval info: CONNECT: q_b 0 0 18 0 @q_b 0 0 18 0 +// Retrieval info: GEN_FILE: TYPE_NORMAL CacheBlockRAM.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL CacheBlockRAM.inc FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL CacheBlockRAM.cmp TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL CacheBlockRAM.bsf FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL CacheBlockRAM_inst.v FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL CacheBlockRAM_bb.v TRUE +// Retrieval info: LIB_FILE: altera_mf diff --git a/cores/minimig/rtl/cache/CacheBlockRAM_bb.v b/cores/minimig/rtl/cache/CacheBlockRAM_bb.v new file mode 100644 index 0000000..4102be6 --- /dev/null +++ b/cores/minimig/rtl/cache/CacheBlockRAM_bb.v @@ -0,0 +1,180 @@ +// megafunction wizard: %RAM: 2-PORT%VBB% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: altsyncram + +// ============================================================ +// File Name: CacheBlockRAM.v +// Megafunction Name(s): +// altsyncram +// +// Simulation Library Files(s): +// altera_mf +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 12.0 Build 232 07/05/2012 SP 1 SJ Web Edition +// ************************************************************ + +//Copyright (C) 1991-2012 Altera Corporation +//Your use of Altera Corporation's design tools, logic functions +//and other software and tools, and its AMPP 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 Altera Program License +//Subscription Agreement, Altera MegaCore Function License +//Agreement, or other applicable license agreement, including, +//without limitation, that your use is for the sole purpose of +//programming logic devices manufactured by Altera and sold by +//Altera or its authorized distributors. Please refer to the +//applicable agreement for further details. + +module CacheBlockRAM ( + address_a, + address_b, + clock, + data_a, + data_b, + wren_a, + wren_b, + q_a, + q_b); + + input [8:0] address_a; + input [8:0] address_b; + input clock; + input [17:0] data_a; + input [17:0] data_b; + input wren_a; + input wren_b; + output [17:0] q_a; + output [17: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 + +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 "9" +// 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 "Cyclone III" +// 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 "9216" +// Retrieval info: PRIVATE: MEM_IN_BITS NUMERIC "0" +// 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 "0" +// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "2" +// Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_MIXED_PORTS NUMERIC "2" +// Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_A NUMERIC "3" +// Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_B NUMERIC "3" +// Retrieval info: PRIVATE: REGdata NUMERIC "1" +// Retrieval info: PRIVATE: REGq NUMERIC "0" +// 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 "0" +// Retrieval info: PRIVATE: WIDTH_READ_A NUMERIC "18" +// Retrieval info: PRIVATE: WIDTH_READ_B NUMERIC "18" +// Retrieval info: PRIVATE: WIDTH_WRITE_A NUMERIC "18" +// Retrieval info: PRIVATE: WIDTH_WRITE_B NUMERIC "18" +// 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 "Cyclone III" +// Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram" +// Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "512" +// 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 "UNREGISTERED" +// Retrieval info: CONSTANT: OUTDATA_REG_B STRING "UNREGISTERED" +// Retrieval info: CONSTANT: POWER_UP_UNINITIALIZED STRING "FALSE" +// Retrieval info: CONSTANT: RAM_BLOCK_TYPE STRING "M9K" +// Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_MIXED_PORTS STRING "DONT_CARE" +// Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_PORT_A STRING "NEW_DATA_NO_NBE_READ" +// Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_PORT_B STRING "NEW_DATA_NO_NBE_READ" +// Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "9" +// Retrieval info: CONSTANT: WIDTHAD_B NUMERIC "9" +// Retrieval info: CONSTANT: WIDTH_A NUMERIC "18" +// Retrieval info: CONSTANT: WIDTH_B NUMERIC "18" +// 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 9 0 INPUT NODEFVAL "address_a[8..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 18 0 INPUT NODEFVAL "data_a[17..0]" +// Retrieval info: USED_PORT: data_b 0 0 18 0 INPUT NODEFVAL "data_b[17..0]" +// Retrieval info: USED_PORT: q_a 0 0 18 0 OUTPUT NODEFVAL "q_a[17..0]" +// Retrieval info: USED_PORT: q_b 0 0 18 0 OUTPUT NODEFVAL "q_b[17..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 9 0 address_a 0 0 9 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 18 0 data_a 0 0 18 0 +// Retrieval info: CONNECT: @data_b 0 0 18 0 data_b 0 0 18 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 18 0 @q_a 0 0 18 0 +// Retrieval info: CONNECT: q_b 0 0 18 0 @q_b 0 0 18 0 +// Retrieval info: GEN_FILE: TYPE_NORMAL CacheBlockRAM.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL CacheBlockRAM.inc FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL CacheBlockRAM.cmp TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL CacheBlockRAM.bsf FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL CacheBlockRAM_inst.v FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL CacheBlockRAM_bb.v TRUE +// Retrieval info: LIB_FILE: altera_mf diff --git a/cores/minimig/rtl/cache/Cache_DataRAM.qip b/cores/minimig/rtl/cache/Cache_DataRAM.qip new file mode 100644 index 0000000..46a1548 --- /dev/null +++ b/cores/minimig/rtl/cache/Cache_DataRAM.qip @@ -0,0 +1,4 @@ +set_global_assignment -name IP_TOOL_NAME "RAM: 2-PORT" +set_global_assignment -name IP_TOOL_VERSION "12.0" +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "Cache_DataRAM.v"] +set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "Cache_DataRAM_bb.v"] diff --git a/cores/minimig/rtl/cache/Cache_DataRAM.v b/cores/minimig/rtl/cache/Cache_DataRAM.v new file mode 100644 index 0000000..ef256c3 --- /dev/null +++ b/cores/minimig/rtl/cache/Cache_DataRAM.v @@ -0,0 +1,242 @@ +// megafunction wizard: %RAM: 2-PORT% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: altsyncram + +// ============================================================ +// File Name: Cache_DataRAM.v +// Megafunction Name(s): +// altsyncram +// +// Simulation Library Files(s): +// altera_mf +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 12.0 Build 232 07/05/2012 SP 1 SJ Web Edition +// ************************************************************ + + +//Copyright (C) 1991-2012 Altera Corporation +//Your use of Altera Corporation's design tools, logic functions +//and other software and tools, and its AMPP 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 Altera Program License +//Subscription Agreement, Altera MegaCore Function License +//Agreement, or other applicable license agreement, including, +//without limitation, that your use is for the sole purpose of +//programming logic devices manufactured by Altera and sold by +//Altera or its authorized distributors. Please refer to the +//applicable agreement for further details. + + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on +module Cache_DataRAM ( + address_a, + address_b, + clock, + data_a, + data_b, + wren_a, + wren_b, + q_a, + q_b); + + input [10:0] address_a; + input [10:0] address_b; + input clock; + input [17:0] data_a; + input [17:0] data_b; + input wren_a; + input wren_b; + output [17:0] q_a; + output [17: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 [17:0] sub_wire0; + wire [17:0] sub_wire1; + wire [17:0] q_a = sub_wire0[17:0]; + wire [17:0] q_b = sub_wire1[17:0]; + + altsyncram altsyncram_component ( + .clock0 (clock), + .wren_a (wren_a), + .address_b (address_b), + .data_b (data_b), + .wren_b (wren_b), + .address_a (address_a), + .data_a (data_a), + .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 = "Cyclone III", + altsyncram_component.lpm_type = "altsyncram", + altsyncram_component.numwords_a = 2048, + altsyncram_component.numwords_b = 2048, + altsyncram_component.operation_mode = "BIDIR_DUAL_PORT", + altsyncram_component.outdata_aclr_a = "NONE", + altsyncram_component.outdata_aclr_b = "NONE", + altsyncram_component.outdata_reg_a = "UNREGISTERED", + altsyncram_component.outdata_reg_b = "UNREGISTERED", + 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_NO_NBE_READ", + altsyncram_component.read_during_write_mode_port_b = "NEW_DATA_NO_NBE_READ", + altsyncram_component.widthad_a = 11, + altsyncram_component.widthad_b = 11, + altsyncram_component.width_a = 18, + altsyncram_component.width_b = 18, + 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 "9" +// 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 "Cyclone III" +// 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 "36864" +// Retrieval info: PRIVATE: MEM_IN_BITS NUMERIC "0" +// 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 "0" +// 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 "3" +// Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_B NUMERIC "3" +// Retrieval info: PRIVATE: REGdata NUMERIC "1" +// Retrieval info: PRIVATE: REGq NUMERIC "0" +// 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 "0" +// Retrieval info: PRIVATE: WIDTH_READ_A NUMERIC "18" +// Retrieval info: PRIVATE: WIDTH_READ_B NUMERIC "18" +// Retrieval info: PRIVATE: WIDTH_WRITE_A NUMERIC "18" +// Retrieval info: PRIVATE: WIDTH_WRITE_B NUMERIC "18" +// 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 "Cyclone III" +// Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram" +// Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "2048" +// Retrieval info: CONSTANT: NUMWORDS_B NUMERIC "2048" +// 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 "UNREGISTERED" +// Retrieval info: CONSTANT: OUTDATA_REG_B STRING "UNREGISTERED" +// 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_NO_NBE_READ" +// Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_PORT_B STRING "NEW_DATA_NO_NBE_READ" +// Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "11" +// Retrieval info: CONSTANT: WIDTHAD_B NUMERIC "11" +// Retrieval info: CONSTANT: WIDTH_A NUMERIC "18" +// Retrieval info: CONSTANT: WIDTH_B NUMERIC "18" +// 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 11 0 INPUT NODEFVAL "address_b[10..0]" +// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT VCC "clock" +// Retrieval info: USED_PORT: data_a 0 0 18 0 INPUT NODEFVAL "data_a[17..0]" +// Retrieval info: USED_PORT: data_b 0 0 18 0 INPUT NODEFVAL "data_b[17..0]" +// Retrieval info: USED_PORT: q_a 0 0 18 0 OUTPUT NODEFVAL "q_a[17..0]" +// Retrieval info: USED_PORT: q_b 0 0 18 0 OUTPUT NODEFVAL "q_b[17..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 11 0 address_b 0 0 11 0 +// Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0 +// Retrieval info: CONNECT: @data_a 0 0 18 0 data_a 0 0 18 0 +// Retrieval info: CONNECT: @data_b 0 0 18 0 data_b 0 0 18 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 18 0 @q_a 0 0 18 0 +// Retrieval info: CONNECT: q_b 0 0 18 0 @q_b 0 0 18 0 +// Retrieval info: GEN_FILE: TYPE_NORMAL Cache_DataRAM.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL Cache_DataRAM.inc FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL Cache_DataRAM.cmp FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL Cache_DataRAM.bsf FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL Cache_DataRAM_inst.v FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL Cache_DataRAM_bb.v TRUE +// Retrieval info: LIB_FILE: altera_mf diff --git a/cores/minimig/rtl/cache/Cache_DataRAM_bb.v b/cores/minimig/rtl/cache/Cache_DataRAM_bb.v new file mode 100644 index 0000000..1346e52 --- /dev/null +++ b/cores/minimig/rtl/cache/Cache_DataRAM_bb.v @@ -0,0 +1,179 @@ +// megafunction wizard: %RAM: 2-PORT%VBB% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: altsyncram + +// ============================================================ +// File Name: Cache_DataRAM.v +// Megafunction Name(s): +// altsyncram +// +// Simulation Library Files(s): +// altera_mf +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 12.0 Build 232 07/05/2012 SP 1 SJ Web Edition +// ************************************************************ + +//Copyright (C) 1991-2012 Altera Corporation +//Your use of Altera Corporation's design tools, logic functions +//and other software and tools, and its AMPP 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 Altera Program License +//Subscription Agreement, Altera MegaCore Function License +//Agreement, or other applicable license agreement, including, +//without limitation, that your use is for the sole purpose of +//programming logic devices manufactured by Altera and sold by +//Altera or its authorized distributors. Please refer to the +//applicable agreement for further details. + +module Cache_DataRAM ( + address_a, + address_b, + clock, + data_a, + data_b, + wren_a, + wren_b, + q_a, + q_b); + + input [10:0] address_a; + input [10:0] address_b; + input clock; + input [17:0] data_a; + input [17:0] data_b; + input wren_a; + input wren_b; + output [17:0] q_a; + output [17: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 + +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 "9" +// 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 "Cyclone III" +// 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 "36864" +// Retrieval info: PRIVATE: MEM_IN_BITS NUMERIC "0" +// 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 "0" +// 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 "3" +// Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_B NUMERIC "3" +// Retrieval info: PRIVATE: REGdata NUMERIC "1" +// Retrieval info: PRIVATE: REGq NUMERIC "0" +// 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 "0" +// Retrieval info: PRIVATE: WIDTH_READ_A NUMERIC "18" +// Retrieval info: PRIVATE: WIDTH_READ_B NUMERIC "18" +// Retrieval info: PRIVATE: WIDTH_WRITE_A NUMERIC "18" +// Retrieval info: PRIVATE: WIDTH_WRITE_B NUMERIC "18" +// 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 "Cyclone III" +// Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram" +// Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "2048" +// Retrieval info: CONSTANT: NUMWORDS_B NUMERIC "2048" +// 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 "UNREGISTERED" +// Retrieval info: CONSTANT: OUTDATA_REG_B STRING "UNREGISTERED" +// 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_NO_NBE_READ" +// Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_PORT_B STRING "NEW_DATA_NO_NBE_READ" +// Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "11" +// Retrieval info: CONSTANT: WIDTHAD_B NUMERIC "11" +// Retrieval info: CONSTANT: WIDTH_A NUMERIC "18" +// Retrieval info: CONSTANT: WIDTH_B NUMERIC "18" +// 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 11 0 INPUT NODEFVAL "address_b[10..0]" +// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT VCC "clock" +// Retrieval info: USED_PORT: data_a 0 0 18 0 INPUT NODEFVAL "data_a[17..0]" +// Retrieval info: USED_PORT: data_b 0 0 18 0 INPUT NODEFVAL "data_b[17..0]" +// Retrieval info: USED_PORT: q_a 0 0 18 0 OUTPUT NODEFVAL "q_a[17..0]" +// Retrieval info: USED_PORT: q_b 0 0 18 0 OUTPUT NODEFVAL "q_b[17..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 11 0 address_b 0 0 11 0 +// Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0 +// Retrieval info: CONNECT: @data_a 0 0 18 0 data_a 0 0 18 0 +// Retrieval info: CONNECT: @data_b 0 0 18 0 data_b 0 0 18 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 18 0 @q_a 0 0 18 0 +// Retrieval info: CONNECT: q_b 0 0 18 0 @q_b 0 0 18 0 +// Retrieval info: GEN_FILE: TYPE_NORMAL Cache_DataRAM.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL Cache_DataRAM.inc FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL Cache_DataRAM.cmp FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL Cache_DataRAM.bsf FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL Cache_DataRAM_inst.v FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL Cache_DataRAM_bb.v TRUE +// Retrieval info: LIB_FILE: altera_mf diff --git a/cores/minimig/rtl/cache/TwoWayCache.v b/cores/minimig/rtl/cache/TwoWayCache.v new file mode 100644 index 0000000..27fc21b --- /dev/null +++ b/cores/minimig/rtl/cache/TwoWayCache.v @@ -0,0 +1,415 @@ +// Two Way Cache, supporting 64 meg address space. +// Would be easy enough to extend to wider address spaces, just need +// to increase the width of the "tag" blockram. + +// If we're targetting Cyclone 3, then we have 9kbit blockrams to play with. +// Each burst, assuming we stick with 4-word bursts, is 64 bits, so a single M9K +// can hold 128 cachelines. Since we're building a 2-way cache, this will end +// up being 2 overlapping sets of 64 cachelines. + +// The address is broken down as follows: +// bit 0 is irrelevant because we're working in 16-bit words. +// bits 2:1 specify which word of a burst we're interested in. +// Bits 10:3 specify the six bit address of the cachelines; +// this will map to {1'b0,addr[8:3]} and {1;b1,addr[8:3]} respectively. +// Bits 25:11 have to be stored in the tag, which, it turns out is no problem, +// since we can use 18-bit wide words. The highest bit will be used as +// a "most recently used" flag, leaving one bit spare, so we can support 64 meg +// without changing bit widths. +// (Storing the MRU flag in both tags in a 2-way cache is redundant, so we'll only +// store it in the first tag.) + +// FIXME - add bus snooping. +// Bus snooping works simply by invalidating cachelines that match +// addresses appearing on the snoop_addr lines. This is triggered by +// the snoop_req line, which should be taken high when a chipset write to ChipRAM +// takes place. +// Since we can't afford to delay the chipset write accessed, we need to latch +// the snoop address. + + +module TwoWayCache +( + input clk, + input reset, // active low + output ready, + input [31:0] cpu_addr, + input cpu_req, // 1 to request attention + output reg cpu_ack, // 1 to signal that data is ready. + output reg cpu_wr_ack, // 1 to signal that write cycles have been actioned + input cpu_rw, // 1 for read cycles, 0 for write cycles + input cpu_rwl, + input cpu_rwu, + input [15:0] data_from_cpu, + output reg [15:0] data_to_cpu, + output reg [31:0] sdram_addr, + input [15:0] data_from_sdram, + output reg [15:0] data_to_sdram, + output reg sdram_req, + input sdram_fill, + output reg sdram_rw, // 1 for read cycles, 0 for write cycles + input [20:0] snoop_addr, // Address of chipram writes + input snoop_req // 1 when snoop_addr contains an address that requires invalidation. +); + +// States for state machine +parameter WAITING=0, WAITRD=1, WAITFILL=2, + FILL2=3, FILL3=4, FILL4=5, FILL5=6, PAUSE1=7, + WRITE1=8, WRITE2=9, INIT1=10, INIT2=11; +reg [4:0] state = INIT1; +reg init; +reg [7:0] initctr; +assign ready=~init; + + +// BlockRAM and related signals for data + +wire [10:0] data_port1_addr; +wire [10:0] data_port2_addr; +wire [17:0] data_port1_r; +wire [17:0] data_port2_r; +reg[17:0] data_ports_w; +reg data_wren1; +reg data_wren2; + +Cache_DataRAM dataram( + .clock(clk), + .address_a(data_port1_addr), + .address_b(data_port2_addr), + .data_a(data_ports_w), + .data_b(data_ports_w), + .q_a(data_port1_r), + .q_b(data_port2_r), + .wren_a(data_wren1), + .wren_b(data_wren2) +); + +wire data_valid1; +wire data_valid2; + +assign data_valid1 = data_port1_r[17] & data_port1_r[16]; +assign data_valid2 = data_port2_r[17] & data_port2_r[16]; + +// BlockRAM and related signals for tags. + +wire [8:0] tag_port1_addr; +wire [8:0] tag_port2_addr; +wire [17:0] tag_port1_r; +wire [17:0] tag_port2_r; +wire [17:0] tag_port1_w; +wire [17:0] tag_port2_w; + +reg tag_wren1; +reg tag_wren2; +reg tag_mru1; + +CacheBlockRAM tagram( + .clock(clk), + .address_a(tag_port1_addr), + .address_b(tag_port2_addr), + .data_a(tag_port1_w), + .data_b(tag_port2_w), + .q_a(tag_port1_r), + .q_b(tag_port2_r), + .wren_a(tag_wren1), + .wren_b(tag_wren2) +); + +// bits 2:1 specify which word of a burst we're interested in. +// Bits 10:3 specify the six bit address of the cachelines; +// Since we're building a 2-way cache, we'll map this to +// {1'b0,addr[10:3]} and {1;b1,addr[10:3]} respectively. + +wire [10:0] cacheline1; +wire [10:0] cacheline2; + +reg readword_burst; // Set to 1 when the lsb of the cache address should + // track the SDRAM controller. +reg [9:0] readword; + +//assign cacheline1 = {1'b0,cpu_addr[10:3],(readword_burst ? readword : cpu_addr[2:1])}; +//assign cacheline2 = {1'b1,cpu_addr[10:3],(readword_burst ? readword : cpu_addr[2:1])}; + +assign cacheline1 = {1'b0,readword_burst ? readword : cpu_addr[10:1]}; +assign cacheline2 = {1'b1,readword_burst ? readword : cpu_addr[10:1]}; + +// We share each tag between all four words of a cacheline. We therefore only need +// one M9K tag RAM for four M9Ks of data RAM. + +assign tag_port1_addr = cacheline1[10:2]; +assign tag_port2_addr = cacheline2[10:2]; + +// The first port contains the mru flag, so we have to write to it on every +// access. The second tag only needs writing when a cacheline in the second +// block is updated, so we tie the write port of the second tag to part of the +// CPU address. +// The first port has to be toggled between old and new data, depending upon +// the state of the mru flag. +// (Writing both ports on every access for troubleshooting) + +assign tag_port1_w = {tag_mru1,(tag_mru1 ? cpu_addr[25:9] : tag_port1_r[16:0])}; +assign tag_port2_w = {1'b0,(!tag_mru1 ? cpu_addr[25:9] : tag_port2_r[16:0])}; +//assign tag_port2_w = {1'b0,cpu_addr[25:9]}; + + +// Boolean signals to indicate cache hits. + +wire tag_hit1; +wire tag_hit2; + +assign tag_hit1 = tag_port1_r[16:0]==cpu_addr[25:9]; +assign tag_hit2 = tag_port2_r[16:0]==cpu_addr[25:9]; + + +// In the data blockram the lower two bits of the address determine +// which word of the burst we're reading. When reading from the cache, this comes +// from the CPU address; when writing to the cache it's determined by the state +// machine. + + +assign data_port1_addr = init ? {1'b0,initctr} : cacheline1; +assign data_port2_addr = init ? {1'b1,initctr} : cacheline2; + + +always @(posedge clk) +begin + + // Defaults + tag_wren1<=1'b0; + tag_wren2<=1'b0; + data_wren1<=1'b0; + data_wren2<=1'b0; + init<=1'b0; + readword_burst<=1'b0; + cpu_wr_ack<=1'b0; + + case(state) + + // FIXME - need an init state here that loops through the data clearing + // the valid flag - for which we'll use bit 17 of the data entry. + + INIT1: + begin + init<=1'b1; // need to mark the entire cache as invalid before starting. + initctr<=8'b0000_0000; + data_ports_w<=18'b0; // Mark entire cache as invalid + data_wren1<=1'b1; + data_wren2<=1'b1; + state<=INIT2; + end + + INIT2: + begin + init<=1'b1; + initctr<=initctr+1; + data_wren1<=1'b1; + data_wren2<=1'b1; + if(initctr==8'b1111_1111) + state<=WAITING; + end + + WAITING: + begin + state<=WAITING; + if(cpu_req==1'b1) + begin + if(cpu_rw==1'b1) // Read cycle + state<=WAITRD; + else // Write cycle + state<=WRITE1; + end + end + WRITE1: + begin + // If the current address is in cache, + // we must update the appropriate cacheline + + // We mark the two halves of the word separately. + // If this is a byte write, the byte not being written + // will be marked as invalid, triggering a re-read if + // the other byte or whole word is read. + data_ports_w<={~cpu_rwu,~cpu_rwl,data_from_cpu}; + + if(tag_hit1) + begin + // Write the data to the first cache way + data_wren1<=1'b1; + // Mark tag1 as most recently used. + tag_mru1<=1'b1; + tag_wren1<=1'b1; + end + // Note: it's possible that both ways of the cache will end up caching + // the same address; if so, we must write to both ways, or at least + // invalidate them both, otherwise we'll have problems with stale data. + if(tag_hit2) + begin + // Write the data to the second cache way + data_wren2<=1'b1; + // Mark tag2 as most recently used. + tag_mru1<=1'b0; + tag_wren1<=1'b1; + end + // FIXME - ultimately we should clear a cacheline here and cache + // the data for future use. Need to have a working valid flag first. + state<=WRITE2; + end + + WRITE2: + begin + cpu_wr_ack<=1'b1; // Indicate to the Write cache that it's safe to proceed. + if(cpu_req==1'b0) // Wait for the write cycle to finish + state<=WAITING; + end + + WAITRD: + begin + state<=PAUSE1; + // Check both tags for a match... + if(tag_hit1 && data_valid1) + begin + // Copy data to output + data_to_cpu<=data_port1_r; + cpu_ack<=1'b1; + + // Mark tag1 as most recently used. + tag_mru1<=1'b1; + tag_wren1<=1'b1; + end + else if(tag_hit2 && data_valid2) + begin + // Copy data to output + data_to_cpu<=data_port2_r; + cpu_ack<=1'b1; + + // Mark tag2 as most recently used. + tag_mru1<=1'b0; + tag_wren1<=1'b1; + end + else // No matches? How do we decide which one to use? + begin + // invert most recently used flags on both tags. + // (Whichever one was least recently used will be overwritten, so + // is now the most recently used.) + // If either tag matches, but the corresponding data is stale, + // we re-use the stale cacheline. + + if(tag_hit1) + tag_mru1<=1'b1; // Way 1 contains stale data + else if(tag_hit2) + tag_mru1<=1'b0; // Way 2 contains stale data + else + tag_mru1<=!tag_port1_r[17]; + +// For simulation only, to avoid the unknown value of unitialised blockram +// tag_mru1<=cpu_addr[1]; + + tag_wren1<=1'b1; + tag_wren2<=1'b1; + // If r[17] is 1, tag_mru1 is 0, so we need to write to the second tag. + // FIXME - might be simpler to just write every cycle and switch between new and old data. +// tag_wren2<=tag_port1_r[17]; + + // Pass request on to RAM controller. + sdram_addr<={cpu_addr[31:3],3'b000}; + sdram_req<=1'b1; + sdram_rw<=1'b1; // Read cycle + state<=WAITFILL; + end + end + + PAUSE1: + begin + state<=PAUSE1; + if(cpu_req==1'b0) + state<=WAITING; + end + + WAITFILL: + begin + readword_burst<=1'b1; + + // In the interests of performance, read the word we're waiting for first. + readword<=cpu_addr[10:1]; + + if (sdram_fill==1'b1) + begin + sdram_req<=1'b0; + + // Forward data to CPU + // (We now latch the address until the current cycle is complete. + // TAGRAM is already written, so just need to take care of + // Data RAM addresses, which we do with the readword signal. + data_to_cpu<=data_from_sdram; + cpu_ack<=1'b1; + + // write first word to Cache... + data_ports_w<={2'b11,data_from_sdram}; + data_wren1<=tag_mru1; + data_wren2<=!tag_mru1; + state<=FILL2; + end + end + + FILL2: + begin + // write second word to Cache... + readword_burst<=1'b1; + readword[1:0]<=readword[1:0]+1; + data_ports_w<={2'b11,data_from_sdram}; + data_wren1<=tag_mru1; + data_wren2<=!tag_mru1; + state<=FILL3; + end + + FILL3: + begin + // write third word to Cache... + readword_burst<=1'b1; + readword[1:0]<=readword[1:0]+1; + data_ports_w<={2'b11,data_from_sdram}; + data_wren1<=tag_mru1; + data_wren2<=!tag_mru1; + state<=FILL4; + end + + FILL4: + begin + // write last word to Cache... + readword_burst<=1'b1; + readword[1:0]<=readword[1:0]+1; + data_ports_w<={2'b11,data_from_sdram}; + data_wren1<=tag_mru1; + data_wren2<=!tag_mru1; + state<=FILL5; + end + + FILL5: + begin + state<=FILL5; + // Shouldn't need to worry about readword now - only used during burst +// readword=cpu_addr[2:1]; + + // Remain on state 5 until cpu_ack is low. + // We use this rather than cpu_req because in the time it's taken us to + // reach this point, it's possible the next request could have started. + if(cpu_ack==1'b0) + state<=WAITING; + end + + default: + state<=WAITING; + endcase + + // Cancel the ack flag as soon as req drops. + // The state machine will wait for this to happen before starting a new cycle. + if(cpu_req==1'b0) + cpu_ack<=1'b0; + + if(reset==1'b0) + begin + state<=INIT1; + cpu_ack<=1'b0; + end +end + +endmodule diff --git a/cores/minimig/rtl/mist/sdram.vhd b/cores/minimig/rtl/mist/sdram.vhd index 817e5a4..6427ed4 100644 --- a/cores/minimig/rtl/mist/sdram.vhd +++ b/cores/minimig/rtl/mist/sdram.vhd @@ -48,7 +48,7 @@ port cpuAddr : in std_logic_vector(24 downto 1); cpuU : in std_logic; cpuL : in std_logic; - cpustate : in std_logic_vector(5 downto 0); + cpustate : in std_logic_vector(5 downto 0); -- clkena & slower(1 downto 0) & ramcs & state; cpu_dma : in std_logic; chipWR : in std_logic_vector(15 downto 0); chipAddr : in std_logic_vector(23 downto 1); @@ -88,7 +88,7 @@ signal casaddr :std_logic_vector(24 downto 0); signal sdwrite :std_logic; signal sdata_reg :std_logic_vector(15 downto 0); -signal hostCycle :std_logic; +-- signal hostCycle :std_logic; signal zmAddr :std_logic_vector(24 downto 0); signal zena :std_logic; signal zcache :std_logic_vector(63 downto 0); @@ -110,6 +110,13 @@ signal cequal :std_logic; signal cpuStated :std_logic_vector(1 downto 0); signal cpuRDd :std_logic_vector(15 downto 0); +signal dcache :std_logic_vector(63 downto 0); +signal dcache_addr :std_logic_vector(24 downto 0); +signal dcache_fill :std_logic; +signal dcachehit :std_logic; +signal dvalid :std_logic_vector(3 downto 0); +signal dequal :std_logic; + signal hostSlot_cnt :std_logic_vector(7 downto 0); signal reset_cnt :std_logic_vector(7 downto 0); signal reset :std_logic; @@ -118,17 +125,85 @@ signal reset_sdstate :std_logic; signal c_7md :std_logic; signal c_7mdd :std_logic; signal c_7mdr :std_logic; -signal cpuCycle :std_logic; -signal chipCycle :std_logic; -signal slow :std_logic_vector(7 downto 0); +-- signal cpuCycle :std_logic; +-- signal chipCycle :std_logic; + +signal refreshcnt : std_logic_vector(8 downto 0); +signal refresh_pending : std_logic; type sdram_states is (ph0,ph1,ph2,ph3,ph4,ph5,ph6,ph7,ph8,ph9,ph10,ph11,ph12,ph13,ph14,ph15); signal sdram_state : sdram_states; type pass_states is (nop,ras,cas); signal pass : pass_states; +type slot_type is (refresh,chip,cpu_readcache,cpu_writecache,host,idle); +signal slot1_type : slot_type := idle; +signal slot2_type : slot_type := idle; +signal slot1_bank : std_logic_vector(1 downto 0); +signal slot2_bank : std_logic_vector(1 downto 0); + +signal cache_req : std_logic; +signal readcache_fill : std_logic; +signal cache_fill_1 : std_logic; +signal cache_fill_2 : std_logic; + +COMPONENT TwoWayCache + GENERIC ( WAITING : INTEGER := 0; WAITRD : INTEGER := 1; WAITFILL : INTEGER := 2; FILL2 : INTEGER := 3; + FILL3 : INTEGER := 4; FILL4 : INTEGER := 5; FILL5 : INTEGER := 6; PAUSE1 : INTEGER := 7 ); + + PORT + ( + clk : IN STD_LOGIC; + reset : IN std_logic; + ready : out std_logic; + cpu_addr : IN STD_LOGIC_VECTOR(31 DOWNTO 0); + cpu_req : IN STD_LOGIC; + cpu_ack : OUT STD_LOGIC; + cpu_wr_ack : OUT STD_LOGIC; + cpu_rw : IN STD_LOGIC; + cpu_rwl : in std_logic; + cpu_rwu : in std_logic; + data_from_cpu : IN STD_LOGIC_VECTOR(15 DOWNTO 0); + data_to_cpu : OUT STD_LOGIC_VECTOR(15 DOWNTO 0); + sdram_addr : OUT STD_LOGIC_VECTOR(31 DOWNTO 0); + data_from_sdram : IN STD_LOGIC_VECTOR(15 DOWNTO 0); + data_to_sdram : OUT STD_LOGIC_VECTOR(15 DOWNTO 0); + sdram_req : OUT STD_LOGIC; + sdram_fill : IN STD_LOGIC; + sdram_rw : OUT STD_LOGIC + ); +END COMPONENT; + +-- Write buffer signals + +signal writebuffer_req : std_logic; +signal writebuffer_ena : std_logic; +-- signal writebufferCycle : std_logic; +signal writebuffer_dqm : std_logic_vector(1 downto 0); +signal writebufferAddr : std_logic_vector(24 downto 1); +signal writebufferWR : std_logic_vector(15 downto 0); +signal writebufferWR_reg : std_logic_vector(15 downto 0); +signal writebuffer_cache_ack : std_logic; +signal writebuffer_hold : std_logic; -- 1 during write access, cleared to indicate that the buffer can accept the next word. + +type writebuffer_states is (waiting,write1,write2,write3); +signal writebuffer_state : writebuffer_states; + +signal cpuAddr_mangled : std_logic_vector(24 downto 1); + +-- Let's try some bank-interleaving. +-- For addresses in the upper 16 meg we shift bits around +-- so that one bank bit comes from addr(3). This should allow +-- bank interleaving to make things more efficient. + begin +-- Turns out this is counter-productive +--cpuAddr_mangled<=cpuAddr(24)&cpuAddr(3)&cpuAddr(22 downto 4)&cpuAddr(23)&cpuAddr(2 downto 1) +-- when cpuAddr(24)='1' else cpuAddr; + +cpuAddr_mangled<=cpuAddr; + process (sysclk, reset_in) begin if reset_in = '0' THEN reset_cnt <= "00000000"; @@ -152,7 +227,9 @@ begin -- SPIHOST cache ------------------------------------------------------------------------- hostena <= '1' when zena='1' or hostState(1 downto 0)="01" OR zcachehit='1' else '0'; - zmAddr <= '0'& NOT hostAddr(23) & hostAddr(22) & NOT hostAddr(21) & hostAddr(20 downto 0); + + -- Map host processor's address space to 0x400000 + zmAddr <= "00" & NOT hostAddr(22) & hostAddr(21 downto 0); process (sysclk, zmAddr, hostAddr, zcache_addr, zcache, zequal, zvalid, hostRDd) begin @@ -163,21 +240,6 @@ begin end if; zcachehit <= '0'; if zequal='1' and zvalid(0)='1' and hostStated(1)='0' THEN --- case (hostAddr(2 downto 1)-zcache_addr(2 downto 1)) is --- when "00"=> --- zcachehit <= zvalid(0); --- hostRD <= zcache(63 downto 48); --- when "01"=> --- zcachehit <= zvalid(1); --- hostRD <= zcache(47 downto 32); --- when "10"=> --- zcachehit <= zvalid(2); --- hostRD <= zcache(31 downto 16); --- when "11"=> --- zcachehit <= zvalid(3); --- hostRD <= zcache(15 downto 0); --- when others=> null; --- end case; case (hostAddr(2 downto 1)&zcache_addr(2 downto 1)) is when "0000"|"0101"|"1010"|"1111"=> zcachehit <= zvalid(0); @@ -199,7 +261,7 @@ begin end process; ---Datenübernahme +--Datenbernahme process (sysclk, reset) begin if reset = '0' THEN zcache_fill <= '0'; @@ -209,17 +271,13 @@ begin if enaWRreg='1' THEN zena <= '0'; end if; - if sdram_state=ph9 AND hostCycle='1' THEN + if sdram_state=ph9 AND slot1_type=host THEN hostRDd <= sdata_reg; --- if zmAddr=casaddr and cas_sd_cas='0' then --- zena <= '1'; --- end if; end if; - if sdram_state=ph11 AND hostCycle='1' THEN --- hostRDd <= sdata_reg; - if zmAddr=casaddr and cas_sd_cas='0' then + if sdram_state=ph11 AND slot1_type=host THEN +-- if zmAddr=casaddr then and cas_sd_cas='0' then zena <= '1'; - end if; +-- end if; end if; hostStated <= hostState(1 downto 0); if zequal='1' and hostState(1 downto 0)="11" THEN @@ -227,9 +285,7 @@ begin end if; case sdram_state is when ph7 => - if hostStated(1)='0' AND hostCycle='1' THEN --only instruction cache --- if cas_sd_we='1' AND hostStated(1)='0' AND hostCycle='1' THEN --only instruction cache --- if cas_sd_we='1' AND hostCycle='1' THEN + if hostStated(1)='0' AND slot1_type=host THEN --only instruction cache zcache_addr <= casaddr(23 downto 0); zcache_fill <= '1'; zvalid <= "0000"; @@ -237,143 +293,238 @@ begin when ph9 => if zcache_fill='1' THEN zcache(63 downto 48) <= sdata_reg; --- zvalid(0) <= '1'; end if; when ph10 => if zcache_fill='1' THEN zcache(47 downto 32) <= sdata_reg; --- zvalid(1) <= '1'; end if; when ph11 => if zcache_fill='1' THEN zcache(31 downto 16) <= sdata_reg; --- zvalid(2) <= '1'; end if; --- zena <= '0'; when ph12 => if zcache_fill='1' THEN zcache(15 downto 0) <= sdata_reg; --- zvalid(3) <= '1'; zvalid <= "1111"; end if; zcache_fill <= '0'; when others => null; end case; end if; - end process; + end process; ------------------------------------------------------------------------- -- cpu cache ------------------------------------------------------------------------- - cpuena <= '1' when cena='1' or ccachehit='1' else '0'; + +mytwc : component TwoWayCache + PORT map + ( + clk => sysclk, + reset => reset, + ready => open, + cpu_addr => "0000000"&cpuAddr_mangled&'0', + cpu_req => not cpustate(2), + cpu_ack => ccachehit, + cpu_wr_ack => writebuffer_cache_ack, + cpu_rw => NOT cpuState(1) OR NOT cpuState(0), + cpu_rwl => cpuL, + cpu_rwu => cpuU, + data_from_cpu => cpuWR, + data_to_cpu => cpuRD, + sdram_addr(31 downto 3) => open, + sdram_addr(2 downto 0) => open, + data_from_sdram => sdata_reg, + data_to_sdram => open, + sdram_req => cache_req, + sdram_fill => readcache_fill, + sdram_rw => open + ); + +-- Write buffer, enables CPU to continue while a write is in progress. + + process(sysclk, reset) begin + if reset='0' then + writebuffer_req<='0'; + writebuffer_ena<='0'; + writebuffer_state<=waiting; + elsif rising_edge(sysclk) then + + case writebuffer_state is + when waiting => + -- CPU write cycle, no cycle already pending. + if cpuState(2 downto 0)="011" then + writebufferAddr<=cpuAddr_mangled(24 downto 1); + writebufferWR<=cpuWR; + writebuffer_dqm<=cpuU & cpuL; + writebuffer_req<='1'; + if writebuffer_cache_ack='1' then + writebuffer_ena<='1'; + writebuffer_state<=write2; + end if; + end if; + when write2 => + if writebuffer_hold='1' then -- The SDRAM controller has picked up the request + writebuffer_req<='0'; + writebuffer_state<=write3; + end if; + when write3 => + if writebuffer_hold='0' then -- Wait for write cycle to finish, so it's safe to update the signals. + writebuffer_state<=waiting; + end if; + when others => + writebuffer_state<=waiting; + end case; + + if cpuState(2)='1' then -- the CPU has unpaused, so clear the ack signal. + writebuffer_ena<='0'; + end if; + end if; + end process; - process (sysclk, cpuAddr, ccache_addr, ccache, cequal, cvalid, cpuRDd) - begin - if cpuAddr(24 downto 3)=ccache_addr(24 downto 3) THEN - cequal <='1'; - else - cequal <='0'; - end if; - ccachehit <= '0'; - if cequal='1' and cvalid(0)='1' and cpuStated(1)='0' THEN --- case (cpuAddr(2 downto 1)-ccache_addr(2 downto 1)) is --- when "00"=> + cpuena <= '1' when cena='1' or ccachehit='1' or writebuffer_ena='1' else '0'; + readcache_fill<='1' when + (cache_fill_1='1' and slot1_type=cpu_readcache) or + (cache_fill_2='1' and slot2_type=cpu_readcache) + else '0'; + +-- cpuena <= '1' when cena='1' or ccachehit='1' or dcachehit='1' else '0'; +-- +-- process (sysclk, cpuAddr, ccache_addr, ccache, cequal, cvalid, cpuRDd) +-- begin +-- if cpuAddr(24 downto 3)=ccache_addr(24 downto 3) THEN +-- cequal <='1'; +-- else +-- cequal <='0'; +-- end if; +-- +-- if cpuAddr(24 downto 3)=dcache_addr(24 downto 3) THEN +-- dequal <='1'; +-- else +-- dequal <='0'; +-- end if; +-- +-- ccachehit <= '0'; +-- dcachehit <= '0'; +-- +-- if cequal='1' and cvalid(0)='1' and cpuStated(1)='0' THEN -- instruction cache +-- case (cpuAddr(2 downto 1)&ccache_addr(2 downto 1)) is +-- when "0000"|"0101"|"1010"|"1111"=> -- ccachehit <= cvalid(0); -- cpuRD <= ccache(63 downto 48); --- when "01"=> +-- when "0100"|"1001"|"1110"|"0011"=> -- ccachehit <= cvalid(1); -- cpuRD <= ccache(47 downto 32); --- when "10"=> +-- when "1000"|"1101"|"0010"|"0111"=> -- ccachehit <= cvalid(2); -- cpuRD <= ccache(31 downto 16); --- when "11"=> +-- when "1100"|"0001"|"0110"|"1011"=> -- ccachehit <= cvalid(3); -- cpuRD <= ccache(15 downto 0); -- when others=> null; +-- end case; +-- elsif dequal='1' and dvalid(0)='1' and cpuStated(1 downto 0)="10" THEN -- Read data +-- case (cpuAddr(2 downto 1)&dcache_addr(2 downto 1)) is +-- when "0000"|"0101"|"1010"|"1111"=> +-- dcachehit <= dvalid(0); +-- cpuRD <= dcache(63 downto 48); +-- when "0100"|"1001"|"1110"|"0011"=> +-- dcachehit <= dvalid(1); +-- cpuRD <= dcache(47 downto 32); +-- when "1000"|"1101"|"0010"|"0111"=> +-- dcachehit <= dvalid(2); +-- cpuRD <= dcache(31 downto 16); +-- when "1100"|"0001"|"0110"|"1011"=> +-- dcachehit <= dvalid(3); +-- cpuRD <= dcache(15 downto 0); +-- when others=> null; -- end case; - case (cpuAddr(2 downto 1)&ccache_addr(2 downto 1)) is - when "0000"|"0101"|"1010"|"1111"=> - ccachehit <= cvalid(0); - cpuRD <= ccache(63 downto 48); - when "0100"|"1001"|"1110"|"0011"=> - ccachehit <= cvalid(1); - cpuRD <= ccache(47 downto 32); - when "1000"|"1101"|"0010"|"0111"=> - ccachehit <= cvalid(2); - cpuRD <= ccache(31 downto 16); - when "1100"|"0001"|"0110"|"1011"=> - ccachehit <= cvalid(3); - cpuRD <= ccache(15 downto 0); - when others=> null; - end case; - else - cpuRD <= cpuRDd; - end if; - end process; - - ---Datenübernahme - process (sysclk, reset) begin - if reset = '0' THEN - ccache_fill <= '0'; - cena <= '0'; - cvalid <= "0000"; - elsif (sysclk'event and sysclk='1') THEN - if cpuState(5)='1' THEN - cena <= '0'; - end if; - if sdram_state=ph9 AND cpuCycle='1' THEN - cpuRDd <= sdata_reg; +-- else +-- cpuRD <= cpuRDd; +-- end if; +-- end process; +-- +-- +----Datenbernahme +-- process (sysclk, reset) begin +-- if reset = '0' THEN +-- ccache_fill <= '0'; +-- cena <= '0'; +-- dcache_fill <= '0'; +-- cvalid <= "0000"; +-- dvalid <= "0000"; +-- elsif (sysclk'event and sysclk='1') THEN +-- if cpuState(5)='1' THEN +-- cena <= '0'; +-- end if; +-- if sdram_state=ph9 AND cpuCycle='1' THEN +-- cpuRDd <= sdata_reg; +-- end if; +-- if sdram_state=ph11 AND cpuCycle='1' THEN -- if cpuAddr=casaddr(24 downto 1) and cas_sd_cas='0' then -- cena <= '1'; -- end if; - end if; - if sdram_state=ph11 AND cpuCycle='1' THEN --- cpuRDd <= sdata_reg; - if cpuAddr=casaddr(24 downto 1) and cas_sd_cas='0' then - cena <= '1'; - end if; - end if; - cpuStated <= cpuState(1 downto 0); - if cequal='1' and cpuState(1 downto 0)="11" THEN - cvalid <= "0000"; - end if; - case sdram_state is - when ph7 => - if cpuStated(1)='0' AND cpuCycle='1' THEN --only instruction cache --- if cas_sd_we='1' AND hostStated(1)='0' AND hostCycle='1' THEN --only instruction cache --- if cas_sd_we='1' AND hostCycle='1' THEN - ccache_addr <= casaddr; - ccache_fill <= '1'; - cvalid <= "0000"; - end if; - when ph9 => - if ccache_fill='1' THEN - ccache(63 downto 48) <= sdata_reg; --- cvalid(0) <= '1'; - end if; - when ph10 => - if ccache_fill='1' THEN - ccache(47 downto 32) <= sdata_reg; --- cvalid(1) <= '1'; - end if; - when ph11 => - if ccache_fill='1' THEN - ccache(31 downto 16) <= sdata_reg; --- cvalid(2) <= '1'; - end if; - when ph12 => - if ccache_fill='1' THEN - ccache(15 downto 0) <= sdata_reg; --- cvalid(3) <= '1'; - cvalid <= "1111"; - end if; - ccache_fill <= '0'; - when others => null; - end case; - end if; - end process; - +-- end if; +-- cpuStated <= cpuState(1 downto 0); +-- +-- -- Invalidate caches on write +-- if cequal='1' and cpuState(1 downto 0)="11" THEN +-- cvalid <= "0000"; +-- end if; +-- if dequal='1' and cpuState(1 downto 0)="11" THEN +-- dvalid <= "0000"; +-- end if; +-- +-- case sdram_state is +-- when ph7 => +-- if cpuCycle='1' then +-- if cpuStated(1)='0' THEN -- instruction cache +-- ccache_addr <= casaddr; +-- ccache_fill <= '1'; +-- cvalid <= "0000"; +-- elsif cpuStated(1 downto 0)="10" THEN -- data cache +-- dcache_addr <= casaddr; +-- dcache_fill <= '1'; +-- dvalid <= "0000"; +-- end if; +-- end if; +-- when ph9 => +-- if ccache_fill='1' THEN +-- ccache(63 downto 48) <= sdata_reg; +-- end if; +-- if dcache_fill='1' THEN +-- dcache(63 downto 48) <= sdata_reg; +-- end if; +-- when ph10 => +-- if ccache_fill='1' THEN +-- ccache(47 downto 32) <= sdata_reg; +-- end if; +-- if dcache_fill='1' THEN +-- dcache(47 downto 32) <= sdata_reg; +-- end if; +-- when ph11 => +-- if ccache_fill='1' THEN +-- ccache(31 downto 16) <= sdata_reg; +-- end if; +-- if dcache_fill='1' THEN +-- dcache(31 downto 16) <= sdata_reg; +-- end if; +-- when ph12 => +-- if ccache_fill='1' THEN +-- ccache(15 downto 0) <= sdata_reg; +-- cvalid <= "1111"; +-- end if; +-- if dcache_fill='1' THEN +-- dcache(15 downto 0) <= sdata_reg; +-- dvalid <= "1111"; +-- end if; +-- ccache_fill <= '0'; +-- dcache_fill <= '0'; +-- when others => null; +-- end case; +-- end if; +-- end process; + ------------------------------------------------------------------------- -- chip cache @@ -381,7 +532,7 @@ begin process (sysclk, sdata_reg) begin if (sysclk'event and sysclk='1') THEN - if sdram_state=ph9 AND chipCycle='1' THEN + if sdram_state=ph9 AND slot1_type=chip THEN chipRD <= sdata_reg; end if; end if; @@ -396,6 +547,7 @@ begin process (sysclk, reset, sdwrite, datain) begin IF sdwrite='1' THEN sdata <= datawr; +-- sdata <= datain; ELSE sdata <= "ZZZZZZZZZZZZZZZZ"; END IF; @@ -404,15 +556,29 @@ begin END IF; if (sysclk'event and sysclk='1') THEN + if sdram_state=ph2 THEN - IF chipCycle='1' THEN - datawr <= chipWR; - ELSIF cpuCycle='1' THEN - datawr <= cpuWR; - ELSE - datawr <= hostWR; - END IF; + case slot1_type is + when chip => + datawr <= chipWR; + when cpu_writecache => + datawr <= writebufferWR_reg; + when others => + datawr <= hostWR; + END case; END IF; + + if sdram_state=ph10 THEN + case slot2_type is + when chip => + datawr <= chipWR; + when cpu_writecache => + datawr <= writebufferWR_reg; + when others => + datawr <= hostWR; + END case; + END IF; + sdata_reg <= sdata; c_7mdd <= c_7md; c_7mdr <= c_7md AND NOT c_7mdd; @@ -429,18 +595,18 @@ begin ena7RDreg <= '0'; ena7WRreg <= '0'; case sdram_state is --LATENCY=3 - when ph2 => sdwrite <= '1'; - enaWRreg <= '1'; + when ph2 => enaWRreg <= '1'; when ph3 => sdwrite <= '1'; when ph4 => sdwrite <= '1'; when ph5 => sdwrite <= '1'; when ph6 => enaWRreg <= '1'; ena7RDreg <= '1'; --- when ph7 => c_7m <= '0'; when ph10 => enaWRreg <= '1'; + when ph11 => sdwrite<= '1'; -- Access slot 2 + when ph12 => sdwrite<= '1'; + when ph13 => sdwrite<= '1'; when ph14 => enaWRreg <= '1'; ena7WRreg <= '1'; --- when ph15 => c_7m <= '1'; when others => null; end case; END IF; @@ -459,25 +625,11 @@ begin END IF; IF c_7mdr='1' THEN sdram_state <= ph2; --- if reset_sdstate = '0' then --- sdram_state <= ph0; ELSE case sdram_state is --LATENCY=3 when ph0 => sdram_state <= ph1; when ph1 => sdram_state <= ph2; --- when ph1 => --- IF c_28md='1' THEN --- sdram_state <= ph2; --- ELSE --- sdram_state <= ph1; --- END IF; when ph2 => sdram_state <= ph3; --- when ph2 => --sdram_state <= ph3; --- IF c_28md='0' THEN --- sdram_state <= ph3; --- ELSE --- sdram_state <= ph2; --- END IF; when ph3 => sdram_state <= ph4; when ph4 => sdram_state <= ph5; when ph5 => sdram_state <= ph6; @@ -490,20 +642,25 @@ begin when ph12 => sdram_state <= ph13; when ph13 => sdram_state <= ph14; when ph14 => sdram_state <= ph15; --- when ph15 => sdram_state <= ph0; when others => sdram_state <= ph0; end case; END IF; END IF; end process; - +-- Address bits will be allocated as follows: +-- 24 downto 23: bank +-- 22 downto 10: row +-- 9 downto 1: column - process (sysclk, initstate, pass, hostAddr, datain, init_done, casaddr, cpuU, cpuL, hostCycle) begin - - - + process (sysclk, initstate, pass, hostAddr, datain, init_done, casaddr, cpuU, cpuL) begin + if (sysclk'event and sysclk='1') THEN + if reset='0' then + refresh_pending<='0'; + slot1_type<=idle; + slot2_type<=idle; + end if; sd_cs <="1111"; sd_ras <= '1'; sd_cas <= '1'; @@ -511,6 +668,13 @@ begin sdaddr <= "XXXXXXXXXXXXX"; ba <= "00"; dqm <= "00"; + cache_fill_1<='0'; + cache_fill_2<='0'; + + if cpuState(5)='1' then + cena<='0'; + end if; + if init_done='0' then if sdram_state =ph1 then case initstate is @@ -530,96 +694,255 @@ begin sd_ras <= '0'; sd_cas <= '0'; sd_we <= '0'; --- ba <= "00"; - -- sdaddr <= "0001000100010"; --BURST=4 LATENCY=2 sdaddr <= "0001000110010"; --BURST=4 LATENCY=3 when others => null; --NOP end case; END IF; else --- Time slot control - if sdram_state=ph1 THEN - cpuCycle <= '0'; - chipCycle <= '0'; - hostCycle <= '0'; - cas_sd_cs <= "1110"; - cas_sd_ras <= '1'; - cas_sd_cas <= '1'; - cas_sd_we <= '1'; - IF slow(2 downto 0)=5 THEN - slow <= slow+3; - ELSE - slow <= slow+1; - END IF; --- IF dma='0' OR cpu_dma='0' THEN - IF hostSlot_cnt /= "00000000" THEN - hostSlot_cnt <= hostSlot_cnt-1; - END IF; --- IF chip_dma='1' THEN - IF chip_dma='0' OR chipRW='0' THEN - chipCycle <= '1'; - sdaddr <= '0'&chipAddr(20 downto 9); --- ba <= "00"; - ba <= chipAddr(22 downto 21); --- cas_dqm <= "00"; --only word access - cas_dqm <= chipU& chipL; - sd_cs <= "1110"; --ACTIVE - sd_ras <= '0'; - casaddr <= '0'&chipAddr&'0'; - datain <= chipWR; - cas_sd_cas <= '0'; - cas_sd_we <= chipRW; --- ELSIF cpu_dma='1' AND hostSlot_cnt /= "00000000" THEN --- ELSIF cpu_dma='0' OR cpuRW='0' THEN - ELSIF cpuState(2)='0' AND cpuState(5)='0' THEN - cpuCycle <= '1'; - sdaddr <= cpuAddr(24)&cpuAddr(20 downto 9); - ba <= cpuAddr(22 downto 21); - cas_dqm <= cpuU& cpuL; - sd_cs <= "1110"; --ACTIVE - sd_ras <= '0'; - casaddr <= cpuAddr(24 downto 1)&'0'; - datain <= cpuWR; - cas_sd_cas <= '0'; - cas_sd_we <= NOT cpuState(1) OR NOT cpuState(0); - ELSE - hostSlot_cnt <= "00001111"; --- ELSIF hostState(2)='1' OR hostena='1' OR slow(3 downto 0)="0001" THEN --refresh cycle - IF hostState(2)='1' OR hostena='1' THEN --refresh cycle - -- ELSIF slow(3 downto 0)="0001" THEN --refresh cycle +-- Time slot control + case sdram_state is + when ph0 => + cache_fill_2 <='1'; -- slot 2 + + when ph1 => + cache_fill_2 <='1'; -- slot 2 + +-- cpuCycle <= '0'; +-- chipCycle <= '0'; +-- hostCycle <= '0'; +-- writebufferCycle <= '0'; + cas_sd_cs <= "1110"; + cas_sd_ras <= '1'; + cas_sd_cas <= '1'; + cas_sd_we <= '1'; + + IF hostSlot_cnt /= "00000000" THEN + hostSlot_cnt <= hostSlot_cnt-1; + END IF; + if refreshcnt = "000000000" then + refresh_pending<='1'; + else + refreshcnt <= refreshcnt-1; + end if; + +-- We give the chipset first priority... +-- (This includes anything on the "motherboard" - chip RAM, slow RAM and Kickstart, turbo modes notwithstanding + + IF chip_dma='0' OR chipRW='0' THEN + slot1_type<=chip; -- chipCycle <= '1'; + sdaddr <= chipAddr(22 downto 10); + ba <= "00"; -- Always bank zero for chipset accesses, so we can interleave Fast RAM access + slot1_bank<="00"; + cas_dqm <= chipU& chipL; + sd_cs <= "1110"; --ACTIVE + sd_ras <= '0'; + casaddr <= '0'&chipAddr&'0'; +-- datain <= chipWR; + cas_sd_cas <= '0'; + cas_sd_we <= chipRW; + +-- Next in line is refresh... +-- (A refresh cycle blocks both access slots) + elsif refresh_pending='1' and slot2_type=idle then sd_cs <="0000"; --AUTOREFRESH sd_ras <= '0'; sd_cas <= '0'; - ELSE - hostCycle <= '1'; - sdaddr <= '0'&zmAddr(20 downto 9); - ba <= zmAddr(22 downto 21); + refreshcnt <= "111111111"; + slot1_type<=refresh; + refresh_pending<='0'; + +-- -- The Amiga CPU gets next bite of the cherry, unless the OSD CPU has been cycle-starved... +-- -- ELSIF cpuState(2)='0' AND cpuState(5)='0' +-- -- Request from write buffer. + ELSIF (writebuffer_req='1') + and (hostslot_cnt/="00000000" or (hostState(2)='1' or hostena='1')) + and (slot2_type=idle or slot2_bank/=writebufferAddr(24 downto 23)) + then + -- We only yeild to the OSD CPU if it's both cycle-starved and ready to go. + slot1_type<=cpu_writecache; + sdaddr <= writebufferAddr(22 downto 10); + ba <= writebufferAddr(24 downto 23); + slot1_bank<=writebufferAddr(24 downto 23); + cas_dqm <= writebuffer_dqm; + sd_cs <= "1110"; --ACTIVE + sd_ras <= '0'; + casaddr <= writebufferAddr(24 downto 1)&'0'; + cas_sd_we <= '0'; +-- datain <= writebufferWR; + writebufferWR_reg <= writebufferWR; + cas_sd_cas <= '0'; + writebuffer_hold<='1'; -- Let the write buffer know we're about to write. + + -- Request from read cache + ELSIF (cache_req='1') + and (hostslot_cnt/="00000000" or (hostState(2)='1' or hostena='1')) + and (slot2_type=idle or slot2_bank/=cpuAddr_mangled(24 downto 23)) + then + -- We only yeild to the OSD CPU if it's both cycle-starved and ready to go. + slot1_type<=cpu_readcache; + sdaddr <= cpuAddr_mangled(22 downto 10); + ba <= cpuAddr_mangled(24 downto 23); + slot1_bank<=cpuAddr_mangled(24 downto 23); + cas_dqm <= cpuU& cpuL; + sd_cs <= "1110"; --ACTIVE + sd_ras <= '0'; + casaddr <= cpuAddr_mangled(24 downto 1)&'0'; +-- if (cpuState(1) and cpuState(0))='1' then -- Write cycle +-- casaddr <= cpuAddr(24 downto 1)&'0'; +-- cas_sd_we <= '0'; +-- else +---- casaddr <= cpuAddr(24 downto 3)&"000"; + cas_sd_we <= '1'; +-- end if; +-- datain <= cpuWR; + cas_sd_cas <= '0'; + ELSIF hostState(2)='0' AND hostena='0' THEN + hostSlot_cnt <= "00001111"; + slot1_type<=host; + sdaddr <= zmAddr(22 downto 10); + ba <= "00"; -- Always bank zero for SPI host CPU + slot1_bank<="00"; cas_dqm <= hostU& hostL; sd_cs <= "1110"; --ACTIVE sd_ras <= '0'; casaddr <= zmAddr; - datain <= hostWR; +-- datain <= hostWR; cas_sd_cas <= '0'; IF hostState="011" THEN cas_sd_we <= '0'; - -- dqm <= hostU& hostL; END IF; +-- elsif slot2_type=idle then +---- If no-one else wants this cycle we refresh the RAM. +-- sd_cs <="0000"; --AUTOREFRESH +-- sd_ras <= '0'; +-- sd_cas <= '0'; +-- refreshcnt <= "111111111"; +-- slot1_type<=refresh; + else + slot1_type<=idle; END IF; - END IF; - END IF; - if sdram_state=ph4 then - sdaddr <= '0'&'0' & '1' & '0' & casaddr(23)&casaddr(8 downto 1);--auto precharge - ba <= casaddr(22 downto 21); - sd_cs <= cas_sd_cs; - IF cas_sd_we='0' THEN - dqm <= cas_dqm; - END IF; - sd_ras <= cas_sd_ras; - sd_cas <= cas_sd_cas; - sd_we <= cas_sd_we; - END IF; - END IF; + + when ph2 => + cache_fill_2 <='1'; -- slot 2 + + when ph3 => + cache_fill_2 <='1'; -- slot 2 + + when ph4 => + sdaddr <= '0'&'0' & '1' & '0' & casaddr(9 downto 1);--auto precharge + ba <= casaddr(24 downto 23); + sd_cs <= cas_sd_cs; + IF cas_sd_we='0' THEN + dqm <= cas_dqm; + END IF; + sd_ras <= cas_sd_ras; + sd_cas <= cas_sd_cas; + sd_we <= cas_sd_we; + writebuffer_hold<='0'; -- Indicate to WriteBuffer that it's safe to accept the next write. + + when ph8 => + cache_fill_1<='1'; + when ph9 => + cache_fill_1<='1'; + +-- Access slot 2, RAS + cas_sd_cs <= "1110"; + cas_sd_ras <= '1'; + cas_sd_cas <= '1'; + cas_sd_we <= '1'; + + slot2_type<=idle; + if refresh_pending='0' and slot1_type/=refresh then + IF writebuffer_req='1' and writebufferAddr(24 downto 23)/="00" -- Reserve bank 0 for slot 1 + and (slot1_type=idle or slot1_bank/=writebufferAddr(24 downto 23)) + then + -- We only yeild to the OSD CPU if it's both cycle-starved and ready to go. + slot2_type<=cpu_writecache; + sdaddr <= writebufferAddr(22 downto 10); + ba <= writebufferAddr(24 downto 23); + slot2_bank <= writebufferAddr(24 downto 23); + cas_dqm <= writebuffer_dqm; + sd_cs <= "1110"; --ACTIVE + sd_ras <= '0'; + casaddr <= writebufferAddr(24 downto 1)&'0'; + cas_sd_we <= '0'; +-- datain <= writebufferWR; + writebufferWR_reg <= writebufferWR; + cas_sd_cas <= '0'; + writebuffer_hold<='1'; -- Let the write buffer know we're about to write. + -- Request from read cache + ELSIF cache_req='1' and cpuAddr(24 downto 23)/="00" -- Reserve bank 0 for slot 1 + and (slot1_type=idle or slot1_bank/=cpuAddr_mangled(24 downto 23)) + then + slot2_type<=cpu_readcache; + sdaddr <= cpuAddr_mangled(22 downto 10); + ba <= cpuAddr_mangled(24 downto 23); + slot2_bank <= cpuAddr_mangled(24 downto 23); + cas_dqm <= cpuU& cpuL; + sd_cs <= "1110"; --ACTIVE + sd_ras <= '0'; + casaddr <= cpuAddr_mangled(24 downto 1)&'0'; + cas_sd_we <= '1'; + cas_sd_cas <= '0'; + end if; + end if; + + when ph10 => + cache_fill_1<='1'; + when ph11 => + cache_fill_1<='1'; + + -- Slot 2 CAS + when ph12 => + sdaddr <= '0'&'0' & '1' & '0' & casaddr(9 downto 1);--auto precharge + ba <= casaddr(24 downto 23); + sd_cs <= cas_sd_cs; + IF cas_sd_we='0' THEN + dqm <= cas_dqm; + END IF; + sd_ras <= cas_sd_ras; + sd_cas <= cas_sd_cas; + sd_we <= cas_sd_we; + writebuffer_hold<='0'; -- Indicate to WriteBuffer that it's safe to accept the next write. + + when others => + null; + end case; + end if; END IF; END process; END; + +-- Slot 1 Slot 2 +-- ph0 (read) (Read 0 in sdata) + +-- ph1 Slot alloc, RAS (read) Read0 + +-- ph2 ... (read) Read1 + +-- ph3 ... (write) Read2 (read3 in sdata) + +-- ph4 CAS, write0 (write) Read3 + +-- ph5 write1 (write) + +-- ph6 write2 (write) + +-- ph7 write3 (read) + +-- ph8 (read0 in sdata) (rd) + +-- ph9 read0 in sdata_reg (rd) Slot alloc, RAS + +-- ph10 read1 (read) ... + +-- ph11 read2 (rd3 in sdata, wr) ... + +-- ph12 read3 (write) CAS, write 0 + +-- ph13 (write) write1 + +-- ph14 (write) write2 + +-- ph15 (read) write3 diff --git a/cores/minimig/rtl/soc/minimig_mist_top.v b/cores/minimig/rtl/soc/minimig_mist_top.v index 704677f..3b2c198 100755 --- a/cores/minimig/rtl/soc/minimig_mist_top.v +++ b/cores/minimig/rtl/soc/minimig_mist_top.v @@ -204,7 +204,8 @@ TG68K tg68k ( .fromram (tg68_cout ), .ramready (tg68_cpuena ), .cpu (cpu_config ), - .memcfg (memcfg ), + .turbochipram (1'b0), + .fastramcfg ({memcfg[5],memcfg[5:4]}), .ramaddr (tg68_cad ), .cpustate (tg68_cpustate ), .nResetOut ( ), diff --git a/cores/minimig/rtl/tg68k/TG68K.vhd b/cores/minimig/rtl/tg68k/TG68K.vhd index 1fc3693..859b24c 100644 --- a/cores/minimig/rtl/tg68k/TG68K.vhd +++ b/cores/minimig/rtl/tg68k/TG68K.vhd @@ -38,7 +38,7 @@ entity TG68K is ein : in std_logic:='1'; addr : buffer std_logic_vector(31 downto 0); data_read : in std_logic_vector(15 downto 0); - data_write : out std_logic_vector(15 downto 0); + data_write : buffer std_logic_vector(15 downto 0); as : out std_logic; uds : out std_logic; lds : out std_logic; @@ -53,7 +53,8 @@ entity TG68K is fromram : in std_logic_vector(15 downto 0); ramready : in std_logic:='0'; cpu : in std_logic_vector(1 downto 0); - memcfg : in std_logic_vector(5 downto 0); + fastramcfg : in std_logic_vector(5 downto 0); + turbochipram : in std_logic; ramaddr : out std_logic_vector(31 downto 0); cpustate : out std_logic_vector(5 downto 0); nResetOut : out std_logic; @@ -134,11 +135,19 @@ COMPONENT TG68KdotC_Kernel SIGNAL eind : std_logic; SIGNAL eindd : std_logic; SIGNAL sel_autoconfig: std_logic; - SIGNAL autoconfig_out: std_logic; - SIGNAL autoconfig_data: std_logic_vector(3 downto 0); + SIGNAL autoconfig_out: std_logic_vector(1 downto 0); -- We use this as a counter since we have two cards to configure + SIGNAL autoconfig_out_next: std_logic_vector(1 downto 0); -- We use this as a counter since we have two cards to configure + SIGNAL autoconfig_data: std_logic_vector(3 downto 0); -- Zorro II RAM + SIGNAL autoconfig_data2: std_logic_vector(3 downto 0); -- Zorro III RAM SIGNAL sel_fast: std_logic; + SIGNAL sel_chipram: std_logic; + SIGNAL turbochip_ena : std_logic := '0'; + SIGNAL turbochip_d : std_logic := '0'; SIGNAL slower : std_logic_vector(3 downto 0); + signal ziii_base : std_logic_vector(7 downto 0); + signal ziiiram_ena : std_logic; + signal sel_ziiiram : std_logic; type sync_states is (sync0, sync1, sync2, sync3, sync4, sync5, sync6, sync7, sync8, sync9); signal sync_state : sync_states; @@ -153,11 +162,31 @@ BEGIN addr <= cpuaddr;-- WHEN addr_akt_e='1' ELSE t_addr WHEN addr_akt_s='1' ELSE "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"; -- data <= data_write WHEN data_akt_e='1' ELSE t_data WHEN data_akt_s='1' ELSE "ZZZZZZZZZZZZZZZZ"; -- datatg68 <= fromram WHEN sel_fast='1' ELSE r_data; - datatg68 <= fromram WHEN sel_fast='1' ELSE r_data WHEN sel_autoconfig='0' ELSE autoconfig_data&r_data(11 downto 0); + datatg68 <= fromram WHEN sel_fast='1' + ELSE autoconfig_data&r_data(11 downto 0) when sel_autoconfig='1' and autoconfig_out="01" -- Zorro II autoconfig + ELSE autoconfig_data2&r_data(11 downto 0) when sel_autoconfig='1' and autoconfig_out="10" -- Zorro III autoconfig + ELSE r_data; -- toram <= data_write; - sel_autoconfig <= '1' when cpuaddr(23 downto 19)="11101" AND autoconfig_out='1' ELSE '0'; --$E80000 - $EFFFFF - sel_fast <= '1' when state/="01" AND (cpuaddr(23 downto 21)="001" OR cpuaddr(23 downto 21)="010" OR cpuaddr(23 downto 21)="011" OR cpuaddr(23 downto 21)="100") ELSE '0'; --$200000 - $9FFFFF + sel_autoconfig <= '1' when cpuaddr(23 downto 19)="11101" AND autoconfig_out/="00" ELSE '0'; --$E80000 - $EFFFFF + + sel_ziiiram <='1' when cpuaddr(31 downto 24)=ziii_base and ziiiram_ena='1' else '0'; + + sel_chipram <= '1' when state/="01" AND (cpuaddr(23 downto 21)="000") ELSE '0'; --$000000 - $1FFFFF + + -- FIXME - prevent TurboChip toggling while a transaction's in progress! + sel_fast <= '1' when state/="01" AND + ( + (turbochip_ena='1' and turbochip_d='1' AND cpuaddr(23 downto 21)="000" ) + OR cpuaddr(23 downto 21)="001" + OR cpuaddr(23 downto 21)="010" + OR cpuaddr(23 downto 21)="011" + OR cpuaddr(23 downto 21)="100" + OR sel_ziiiram='1' + ) + ELSE '0'; --$200000 - $9FFFFF + +-- sel_fast <= '1' when state/="01" AND (cpuaddr(23 downto 21)="001" OR cpuaddr(23 downto 21)="010" OR cpuaddr(23 downto 21)="011" OR cpuaddr(23 downto 21)="100") ELSE '0'; --$200000 - $9FFFFF -- sel_fast <= '1' when cpuaddr(23 downto 21)="001" OR cpuaddr(23 downto 21)="010" ELSE '0'; --$200000 - $5FFFFF -- sel_fast <= '1' when cpuaddr(23 downto 19)="11111" ELSE '0'; --$F800000; -- sel_fast <= '0'; --$200000 - $9FFFFF @@ -171,8 +200,14 @@ BEGIN -- ramaddr(23 downto 0) <= cpuaddr(23 downto 0); -- ramaddr(24) <= sel_fast; -- ramaddr(31 downto 25) <= cpuaddr(31 downto 25); - ramaddr(23 downto 0) <= sel_fast & cpuaddr(22 downto 0); -- Map ZII FastRAM to second 8 Meg. - ramaddr(31 downto 24) <= cpuaddr(31 downto 24); + ramaddr(20 downto 0) <= cpuaddr(20 downto 0); + ramaddr(31 downto 25) <= "0000000"; + ramaddr(24) <= sel_ziiiram; -- Remap the Zorro III RAM to 0x1000000 + ramaddr(23 downto 21) <= "100" when sel_ziiiram&cpuaddr(23 downto 21)="0001" -- 2 -> 8 + else "101" when sel_ziiiram&cpuaddr(23 downto 21)="0010" -- 4 -> A + else "110" when sel_ziiiram&cpuaddr(23 downto 21)="0011" -- 6 -> C + else "111" when sel_ziiiram&cpuaddr(23 downto 21)="0100" -- 8 -> E + else cpuaddr(23 downto 21); -- pass through others pf68K_Kernel_inst: TG68KdotC_Kernel @@ -203,35 +238,83 @@ pf68K_Kernel_inst: TG68KdotC_Kernel CPU => cpu, skipFetch => skipFetch -- : out std_logic ); - + + process(clk,turbochipram) +begin + if rising_edge(clk) then + if state="01" then -- No mem access, so safe to switch chipram access mode + turbochip_d<=turbochipram; + end if; + end if; +end process; + PROCESS (clk) BEGIN - autoconfig_data <= "1111"; - IF memcfg(5 downto 4)/="00" THEN - CASE cpuaddr(6 downto 1) IS - WHEN "000000" => autoconfig_data <= "1110"; --normal card, add mem, no ROM - WHEN "000001" => - CASE memcfg(5 downto 4) IS - WHEN "01" => autoconfig_data <= "0110"; --2MB - WHEN "10" => autoconfig_data <= "0111"; --4MB - WHEN OTHERS => autoconfig_data <= "0000"; --8MB --- WHEN OTHERS => autoconfig_data <= "0111"; --4MB - END CASE; - WHEN "001000" => autoconfig_data <= "1110"; --4626=icomp - WHEN "001001" => autoconfig_data <= "1101"; - WHEN "001010" => autoconfig_data <= "1110"; - WHEN "001011" => autoconfig_data <= "1101"; - WHEN "010011" => autoconfig_data <= "1110"; --serial=1 - WHEN OTHERS => null; - END CASE; - END IF; + + -- Zorro II RAM (Up to 8 meg at 0x200000) + autoconfig_data <= "1111"; + IF fastramcfg/="000" THEN + CASE cpuaddr(6 downto 1) IS + WHEN "000000" => autoconfig_data <= "1110"; --Zorro-II card, add mem, no ROM + WHEN "000001" => + CASE fastramcfg(1 downto 0) IS + WHEN "01" => autoconfig_data <= "0110"; --2MB + WHEN "10" => autoconfig_data <= "0111"; --4MB + WHEN OTHERS => autoconfig_data <= "0000"; --8MB + END CASE; + WHEN "001000" => autoconfig_data <= "1110"; --4626=icomp + WHEN "001001" => autoconfig_data <= "1101"; + WHEN "001010" => autoconfig_data <= "1110"; + WHEN "001011" => autoconfig_data <= "1101"; + WHEN "010011" => autoconfig_data <= "1110"; --serial=1 + WHEN OTHERS => null; + END CASE; + END IF; + + -- Zorro III RAM (Up to 16 meg, address assigned by ROM) + autoconfig_data2 <= "1111"; + IF fastramcfg(2)='1' THEN -- Zorro III RAM + CASE cpuaddr(6 downto 1) IS + WHEN "000000" => autoconfig_data2 <= "1010"; --Zorro-III card, add mem, no ROM + WHEN "000001" => autoconfig_data2 <= "0000"; --8MB (extended to 16 in reg 08) + when "000100" => autoconfig_data2 <= "0000"; --Memory card, not silenceable, Extended size (16 meg), reserved. + WHEN "001000" => autoconfig_data2 <= "1110"; --4626=icomp + WHEN "001001" => autoconfig_data2 <= "1101"; + WHEN "001010" => autoconfig_data2 <= "1110"; + WHEN "001011" => autoconfig_data2 <= "1101"; + WHEN "010011" => autoconfig_data2 <= "1101"; --serial=2 + WHEN OTHERS => null; + END CASE; + END IF; + IF rising_edge(clk) THEN IF reset='0' THEN - autoconfig_out <= '1'; --autoconfig on + autoconfig_out_next <= "01"; --autoconfig on + autoconfig_out <= "01"; --autoconfig on + turbochip_ena <= '0'; -- disable turbo_chipram until we know kickstart's running... + ziiiram_ena <='0'; + ziii_base<=X"01"; ELSIF enaWRreg='1' THEN - IF sel_autoconfig='1' AND state="11"AND uds_in='0' AND cpuaddr(6 downto 1)="100100" THEN - autoconfig_out <= '0'; --autoconfig off - END IF; + IF sel_autoconfig='1' AND state="11"AND uds_in='0' and clkena='1' then + case cpuaddr(6 downto 1) is + when "100100" => -- Register 0x48 - config + if autoconfig_out="01" then + autoconfig_out<=fastramcfg(2)&'0'; + end if; + turbochip_ena <= '1'; -- enable turbo_chipram after autoconfig has been done... + -- FIXME - this is a hack to allow ROM overlay to work. + when "100010" => -- Register 0x44, assign base address to ZIII RAM. + -- We ought to take 16 bits here, but for now we take liberties and use a single byte. + if autoconfig_out="10" then + ziii_base<=data_write(15 downto 8); + ziiiram_ena <='1'; + autoconfig_out<="00"; + end if; + + when others => + null; + end case; + END IF; END IF; END IF; END PROCESS;