mirror of
https://github.com/MiSTer-devel/PCXT_MiSTer.git
synced 2026-05-17 03:04:20 +00:00
8
PCXT.sv
8
PCXT.sv
@@ -213,8 +213,9 @@ module emu
|
||||
"S0,IMGIMAVFD,Floppy A:;",
|
||||
"S1,IMGIMAVFD,Floppy B:;",
|
||||
"OJK,Write Protect,None,A:,B:,A: & B:;",
|
||||
"-;",
|
||||
"S2,IMG,HDD Image:;",
|
||||
// "S2,IMG,HDD Image:;",
|
||||
"S2,VHD,IDE 0-0;",
|
||||
"S3,VHD,IDE 0-1;",
|
||||
"-;",
|
||||
"OHI,CPU Speed,4.77MHz,7.16MHz,14.318MHz;",
|
||||
"-;",
|
||||
@@ -373,7 +374,7 @@ module emu
|
||||
wire mgmt_rd;
|
||||
wire mgmt_wr;
|
||||
wire [7:0] mgmt_req;
|
||||
assign mgmt_req[5:0] = 6'b000000;
|
||||
assign mgmt_req[5:3] = 3'b000;
|
||||
|
||||
wire [35:0] EXT_BUS;
|
||||
hps_ext hps_ext
|
||||
@@ -1033,6 +1034,7 @@ module emu
|
||||
.clock_rate (cur_rate),
|
||||
.floppy_wp (status[20:19]),
|
||||
.fdd_request (mgmt_req[7:6]),
|
||||
.ide0_request (mgmt_req[2:0]),
|
||||
.xtctl (xtctl),
|
||||
.enable_a000h (a000h)
|
||||
);
|
||||
|
||||
@@ -137,6 +137,7 @@ module CHIPSET (
|
||||
input logic [27:0] clock_rate,
|
||||
input logic [1:0] floppy_wp,
|
||||
output logic [1:0] fdd_request,
|
||||
output logic [2:0] ide0_request,
|
||||
// XTCTL DATA
|
||||
output logic [7:0] xtctl,
|
||||
// Optional flags
|
||||
@@ -345,6 +346,7 @@ module CHIPSET (
|
||||
.clock_rate (clock_rate),
|
||||
.floppy_wp (floppy_wp),
|
||||
.fdd_request (fdd_request),
|
||||
.ide0_request (ide0_request),
|
||||
.fdd_dma_req (fdd_dma_req),
|
||||
.fdd_dma_ack (~dma_acknowledge_n[2]),
|
||||
.terminal_count (terminal_count_n),
|
||||
|
||||
@@ -108,6 +108,7 @@ module PERIPHERALS #(
|
||||
input logic [27:0] clock_rate,
|
||||
input logic [1:0] floppy_wp,
|
||||
output logic [1:0] fdd_request,
|
||||
output logic [2:0] ide0_request,
|
||||
output logic fdd_dma_req,
|
||||
input logic fdd_dma_ack,
|
||||
input logic terminal_count,
|
||||
@@ -205,6 +206,7 @@ module PERIPHERALS #(
|
||||
assign ems_b3 = (~iorq && ena_ems[2] && (address[19:14] == {ems_page_address, 2'b10})); // C8000h - D8000h - E8000h
|
||||
assign ems_b4 = (~iorq && ena_ems[3] && (address[19:14] == {ems_page_address, 2'b11})); // CC000h - DC000h - EC000h
|
||||
|
||||
wire ide0_cs_n = ~(iorq && ~address_enable_n && ({address[15:4], 4'd0} == 16'h0300));
|
||||
wire floppy0_select_n = ~(~address_enable_n && (({address[15:2], 2'd0} == 16'h03F0) || ({address[15:1], 1'd0} == 16'h03F4) || ({address[15:0]} == 16'h03F7)));
|
||||
|
||||
logic [1:0] ems_access_address;
|
||||
@@ -976,10 +978,113 @@ module PERIPHERALS #(
|
||||
);
|
||||
|
||||
|
||||
//
|
||||
// XT2IDE
|
||||
//
|
||||
logic [7:0] xt2ide0_data_bus_out;
|
||||
logic ide0_cs1fx;
|
||||
logic ide0_cs3fx;
|
||||
logic ide0_io_read_n;
|
||||
logic ide0_io_write_n;
|
||||
logic [2:0] ide0_address;
|
||||
logic ide0_data_bus_io;
|
||||
logic [15:0] ide0_data_bus_in;
|
||||
logic [15:0] ide0_data_bus_out;
|
||||
|
||||
XT2IDE xt2ide0 (
|
||||
.clock (clock),
|
||||
.reset (reset),
|
||||
|
||||
.high_speed (0),
|
||||
|
||||
.chip_select_n (ide0_cs_n),
|
||||
.io_read_n (io_read_n),
|
||||
.io_write_n (io_write_n),
|
||||
|
||||
.address (address[3:0]),
|
||||
.data_bus_in (internal_data_bus),
|
||||
.data_bus_out (xt2ide0_data_bus_out),
|
||||
|
||||
.ide_cs1fx (ide0_cs1fx),
|
||||
.ide_cs3fx (ide0_cs3fx),
|
||||
.ide_io_read_n (ide0_io_read_n),
|
||||
.ide_io_write_n (ide0_io_write_n),
|
||||
|
||||
.ide_address (ide0_address),
|
||||
.ide_data_bus_io (ide0_data_bus_io),
|
||||
.ide_data_bus_in (ide0_data_bus_in),
|
||||
.ide_data_bus_out (ide0_data_bus_out)
|
||||
);
|
||||
|
||||
|
||||
//
|
||||
// IDE
|
||||
//
|
||||
logic mgmt_ide0_cs;
|
||||
logic [15:0] mgmt_ide0_readdata;
|
||||
logic ide0_command_cs;
|
||||
logic ide0_control_cs;
|
||||
logic ide0_comd_ctrl_select;
|
||||
logic ide0_io_read;
|
||||
logic ide0_io_read_1;
|
||||
logic ide0_io_write;
|
||||
logic prev_ide0_io_read;
|
||||
logic prev_ide0_io_write;
|
||||
logic [3:0] ide0_address_1;
|
||||
logic [15:0] ide0_writedata;
|
||||
|
||||
assign mgmt_ide0_cs = (mgmt_address[15:8] == 8'hF0);
|
||||
|
||||
assign ide0_command_cs = ~ide0_cs1fx;
|
||||
assign ide0_control_cs = ~ide0_cs3fx & &ide0_address[2:1];
|
||||
assign ide0_io_read = ~ide0_io_read_n & (ide0_command_cs | ide0_control_cs);
|
||||
assign ide0_io_write = ~ide0_io_write_n & (ide0_command_cs | ide0_control_cs);
|
||||
|
||||
always_ff @(posedge clock)
|
||||
begin
|
||||
ide0_io_read_1 <= ide0_io_read;
|
||||
prev_ide0_io_read <= ide0_io_read_1;
|
||||
prev_ide0_io_write <= ide0_io_write;
|
||||
ide0_address_1 <= ~ide0_control_cs ? {1'b0, ide0_address} : {1'b1, ide0_address};
|
||||
ide0_writedata <= ide0_data_bus_out;
|
||||
end
|
||||
|
||||
ide ide
|
||||
(
|
||||
.clk (clock),
|
||||
.rst_n (~reset),
|
||||
|
||||
// .irq (),
|
||||
// .drq (),
|
||||
|
||||
.use_fast (0),
|
||||
// .no_data (),
|
||||
|
||||
// .drive_en (),
|
||||
|
||||
.io_address (ide0_address_1),
|
||||
.io_read (ide0_io_read & ~prev_ide0_io_read),
|
||||
.io_readdata (ide0_data_bus_in),
|
||||
.io_write (~ide0_io_write & prev_ide0_io_write),
|
||||
.io_writedata (ide0_writedata),
|
||||
.io_32 (0),
|
||||
|
||||
// .io_wait (),
|
||||
|
||||
.request (ide0_request),
|
||||
.mgmt_address (mgmt_address[3:0]),
|
||||
.mgmt_writedata (mgmt_writedata),
|
||||
.mgmt_readdata (mgmt_ide0_readdata),
|
||||
.mgmt_write (mgmt_write & mgmt_ide0_cs),
|
||||
.mgmt_read (mgmt_read & mgmt_ide0_cs)
|
||||
);
|
||||
|
||||
|
||||
//
|
||||
// FDC
|
||||
//
|
||||
logic mgmt_fdd_cs;
|
||||
logic [15:0] mgmt_fdd_readdata;
|
||||
logic [7:0] write_to_fdd;
|
||||
logic [2:0] fdd_io_address;
|
||||
logic fdd_io_read;
|
||||
@@ -1061,7 +1166,7 @@ module PERIPHERALS #(
|
||||
.mgmt_write (mgmt_write & mgmt_fdd_cs),
|
||||
.mgmt_writedata (mgmt_writedata),
|
||||
.mgmt_read (mgmt_read & mgmt_fdd_cs),
|
||||
.mgmt_readdata (mgmt_readdata),
|
||||
.mgmt_readdata (mgmt_fdd_readdata),
|
||||
|
||||
.wp (floppy_wp),
|
||||
|
||||
@@ -1091,6 +1196,12 @@ module PERIPHERALS #(
|
||||
end
|
||||
|
||||
|
||||
//
|
||||
// mgmt_readdata
|
||||
//
|
||||
assign mgmt_readdata = mgmt_ide0_cs ? mgmt_ide0_readdata : mgmt_fdd_readdata;
|
||||
|
||||
|
||||
//
|
||||
// KFTVGA
|
||||
//
|
||||
@@ -1227,6 +1338,11 @@ module PERIPHERALS #(
|
||||
data_bus_out_from_chipset <= 1'b1;
|
||||
data_bus_out <= joy_data;
|
||||
end
|
||||
else if ((~ide0_cs_n) && (~io_read_n))
|
||||
begin
|
||||
data_bus_out_from_chipset <= 1'b1;
|
||||
data_bus_out <= xt2ide0_data_bus_out;
|
||||
end
|
||||
else if ((~floppy0_select_n || fdd_dma_read) && (~io_read_n))
|
||||
begin
|
||||
data_bus_out_from_chipset <= 1'b1;
|
||||
|
||||
114
rtl/KFPC-XT/HDL/XT2IDE.sv
Normal file
114
rtl/KFPC-XT/HDL/XT2IDE.sv
Normal file
@@ -0,0 +1,114 @@
|
||||
//
|
||||
// XT2IDE written by kitune-san
|
||||
//
|
||||
module XT2IDE
|
||||
(
|
||||
input logic clock,
|
||||
input logic reset,
|
||||
|
||||
input logic high_speed,
|
||||
|
||||
input logic chip_select_n,
|
||||
input logic io_read_n,
|
||||
input logic io_write_n,
|
||||
|
||||
input logic [4:0] address,
|
||||
input logic [7:0] data_bus_in,
|
||||
output logic [7:0] data_bus_out,
|
||||
|
||||
output logic ide_cs1fx,
|
||||
output logic ide_cs3fx,
|
||||
output logic ide_io_read_n,
|
||||
output logic ide_io_write_n,
|
||||
|
||||
output logic [2:0] ide_address,
|
||||
output logic ide_data_bus_io,
|
||||
input logic [15:0] ide_data_bus_in,
|
||||
output logic [15:0] ide_data_bus_out
|
||||
);
|
||||
|
||||
logic select_1;
|
||||
logic select_2;
|
||||
logic latch_high_read_byte;
|
||||
logic read_high_byte;
|
||||
logic latch_high_write_byte;
|
||||
logic [7:0] read_buffer;
|
||||
|
||||
//
|
||||
// Control Signals
|
||||
//
|
||||
assign select_1 = high_speed ? address[0] : address[3];
|
||||
assign select_2 = high_speed ? address[3] : address[0];
|
||||
|
||||
always_comb
|
||||
begin
|
||||
latch_high_read_byte = 1'b0;
|
||||
ide_data_bus_io = 1'b1;
|
||||
read_high_byte = 1'b0;
|
||||
latch_high_write_byte = 1'b0;
|
||||
|
||||
if (~address[2] & ~address[1] & ~select_2 & ~chip_select_n) begin
|
||||
casez ({select_1, io_read_n, io_write_n})
|
||||
3'b001: latch_high_read_byte = 1'b1;
|
||||
3'b010: ide_data_bus_io = 1'b0;
|
||||
3'b101: read_high_byte = 1'b1;
|
||||
3'b110: latch_high_write_byte = 1'b1;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
assign ide_io_read_n = io_read_n;
|
||||
assign ide_io_write_n = io_write_n;
|
||||
assign ide_cs1fx = select_1 | chip_select_n;
|
||||
assign ide_cs3fx = ~select_1 | chip_select_n;
|
||||
|
||||
//
|
||||
// XT Address -> IDE Address
|
||||
//
|
||||
assign ide_address = {address[2:1], select_2};
|
||||
|
||||
//
|
||||
// XT Data Bus -> IDE Data Bus
|
||||
//
|
||||
always_ff @(posedge clock, posedge reset)
|
||||
begin
|
||||
if (reset)
|
||||
ide_data_bus_out[15:8] <= 8'hFF;
|
||||
else if (~chip_select_n & latch_high_write_byte)
|
||||
ide_data_bus_out[15:8] <= data_bus_in;
|
||||
else
|
||||
ide_data_bus_out[15:8] <= ide_data_bus_out[15:8];
|
||||
end
|
||||
|
||||
always_comb
|
||||
begin
|
||||
if (io_write_n | chip_select_n)
|
||||
ide_data_bus_out[7:0] = 8'hFF;
|
||||
else
|
||||
ide_data_bus_out[7:0] = data_bus_in;
|
||||
end
|
||||
|
||||
//
|
||||
// IDE Data Bus -> XT Data Bus
|
||||
//
|
||||
always_ff @(posedge clock, posedge reset)
|
||||
begin
|
||||
if (reset)
|
||||
read_buffer <= 8'hFF;
|
||||
else if (~ide_io_read_n & latch_high_read_byte)
|
||||
read_buffer <= ide_data_bus_in[15:8];
|
||||
else
|
||||
read_buffer <= read_buffer;
|
||||
end
|
||||
|
||||
always_comb
|
||||
begin
|
||||
if (read_high_byte)
|
||||
data_bus_out = read_buffer;
|
||||
else if (~io_read_n & ~chip_select_n)
|
||||
data_bus_out = ide_data_bus_in[7:0];
|
||||
else
|
||||
data_bus_out = 8'hFF;
|
||||
end
|
||||
|
||||
endmodule
|
||||
330
rtl/common/bram.vhd
Normal file
330
rtl/common/bram.vhd
Normal file
@@ -0,0 +1,330 @@
|
||||
--------------------------------------------------------------
|
||||
-- Single port Block RAM
|
||||
--------------------------------------------------------------
|
||||
|
||||
LIBRARY ieee;
|
||||
USE ieee.std_logic_1164.all;
|
||||
|
||||
LIBRARY altera_mf;
|
||||
USE altera_mf.altera_mf_components.all;
|
||||
|
||||
ENTITY spram IS
|
||||
generic (
|
||||
addr_width : integer := 8;
|
||||
data_width : integer := 8;
|
||||
mem_init_file : string := " ";
|
||||
mem_name : string := "MEM" -- for InSystem Memory content editor.
|
||||
);
|
||||
PORT
|
||||
(
|
||||
clock : in STD_LOGIC;
|
||||
address : in STD_LOGIC_VECTOR (addr_width-1 DOWNTO 0);
|
||||
data : in STD_LOGIC_VECTOR (data_width-1 DOWNTO 0) := (others => '0');
|
||||
enable : in STD_LOGIC := '1';
|
||||
wren : in STD_LOGIC := '0';
|
||||
q : out STD_LOGIC_VECTOR (data_width-1 DOWNTO 0);
|
||||
cs : in std_logic := '1'
|
||||
);
|
||||
END spram;
|
||||
|
||||
|
||||
ARCHITECTURE SYN OF spram IS
|
||||
BEGIN
|
||||
spram_sz : work.spram_sz
|
||||
generic map(addr_width, data_width, 2**addr_width, mem_init_file, mem_name)
|
||||
port map(clock,address,data,enable,wren,q,cs);
|
||||
END SYN;
|
||||
|
||||
|
||||
--------------------------------------------------------------
|
||||
-- Single port Block RAM with specific size
|
||||
--------------------------------------------------------------
|
||||
|
||||
LIBRARY ieee;
|
||||
USE ieee.std_logic_1164.all;
|
||||
|
||||
LIBRARY altera_mf;
|
||||
USE altera_mf.altera_mf_components.all;
|
||||
|
||||
ENTITY spram_sz IS
|
||||
generic (
|
||||
addr_width : integer := 8;
|
||||
data_width : integer := 8;
|
||||
numwords : integer := 2**8;
|
||||
mem_init_file : string := " ";
|
||||
mem_name : string := "MEM" -- for InSystem Memory content editor.
|
||||
);
|
||||
PORT
|
||||
(
|
||||
clock : in STD_LOGIC;
|
||||
address : in STD_LOGIC_VECTOR (addr_width-1 DOWNTO 0);
|
||||
data : in STD_LOGIC_VECTOR (data_width-1 DOWNTO 0) := (others => '0');
|
||||
enable : in STD_LOGIC := '1';
|
||||
wren : in STD_LOGIC := '0';
|
||||
q : out STD_LOGIC_VECTOR (data_width-1 DOWNTO 0);
|
||||
cs : in std_logic := '1'
|
||||
);
|
||||
END ENTITY;
|
||||
|
||||
ARCHITECTURE SYN OF spram_sz IS
|
||||
signal q0 : std_logic_vector((data_width - 1) downto 0);
|
||||
BEGIN
|
||||
q<= q0 when cs = '1' else (others => '1');
|
||||
|
||||
altsyncram_component : altsyncram
|
||||
GENERIC MAP (
|
||||
clock_enable_input_a => "BYPASS",
|
||||
clock_enable_output_a => "BYPASS",
|
||||
intended_device_family => "Cyclone V",
|
||||
lpm_hint => "ENABLE_RUNTIME_MOD=YES,INSTANCE_NAME="&mem_name,
|
||||
lpm_type => "altsyncram",
|
||||
numwords_a => numwords,
|
||||
operation_mode => "SINGLE_PORT",
|
||||
outdata_aclr_a => "NONE",
|
||||
outdata_reg_a => "UNREGISTERED",
|
||||
power_up_uninitialized => "FALSE",
|
||||
read_during_write_mode_port_a => "NEW_DATA_NO_NBE_READ",
|
||||
init_file => mem_init_file,
|
||||
widthad_a => addr_width,
|
||||
width_a => data_width,
|
||||
width_byteena_a => 1
|
||||
)
|
||||
PORT MAP (
|
||||
address_a => address,
|
||||
clock0 => clock,
|
||||
data_a => data,
|
||||
wren_a => wren and cs,
|
||||
q_a => q0
|
||||
);
|
||||
|
||||
END SYN;
|
||||
|
||||
--------------------------------------------------------------
|
||||
-- Dual port Block RAM same parameters on both ports
|
||||
--------------------------------------------------------------
|
||||
LIBRARY ieee;
|
||||
USE ieee.std_logic_1164.all;
|
||||
|
||||
LIBRARY altera_mf;
|
||||
USE altera_mf.altera_mf_components.all;
|
||||
|
||||
entity dpram is
|
||||
generic (
|
||||
addr_width : integer := 8;
|
||||
data_width : integer := 8;
|
||||
mem_init_file : string := " "
|
||||
);
|
||||
PORT
|
||||
(
|
||||
clock : in STD_LOGIC;
|
||||
|
||||
address_a : in STD_LOGIC_VECTOR (addr_width-1 DOWNTO 0);
|
||||
data_a : in STD_LOGIC_VECTOR (data_width-1 DOWNTO 0) := (others => '0');
|
||||
enable_a : in STD_LOGIC := '1';
|
||||
wren_a : in STD_LOGIC := '0';
|
||||
q_a : out STD_LOGIC_VECTOR (data_width-1 DOWNTO 0);
|
||||
cs_a : in std_logic := '1';
|
||||
|
||||
address_b : in STD_LOGIC_VECTOR (addr_width-1 DOWNTO 0) := (others => '0');
|
||||
data_b : in STD_LOGIC_VECTOR (data_width-1 DOWNTO 0) := (others => '0');
|
||||
enable_b : in STD_LOGIC := '1';
|
||||
wren_b : in STD_LOGIC := '0';
|
||||
q_b : out STD_LOGIC_VECTOR (data_width-1 DOWNTO 0);
|
||||
cs_b : in std_logic := '1'
|
||||
);
|
||||
end entity;
|
||||
|
||||
|
||||
ARCHITECTURE SYN OF dpram IS
|
||||
BEGIN
|
||||
ram : work.dpram_dif generic map(addr_width,data_width,addr_width,data_width,mem_init_file)
|
||||
port map(clock,address_a,data_a,enable_a,wren_a,q_a,cs_a,address_b,data_b,enable_b,wren_b,q_b,cs_b);
|
||||
END SYN;
|
||||
|
||||
--------------------------------------------------------------
|
||||
-- Dual port Block RAM different parameters on ports
|
||||
--------------------------------------------------------------
|
||||
LIBRARY ieee;
|
||||
USE ieee.std_logic_1164.all;
|
||||
|
||||
LIBRARY altera_mf;
|
||||
USE altera_mf.altera_mf_components.all;
|
||||
|
||||
entity dpram_dif is
|
||||
generic (
|
||||
addr_width_a : integer := 8;
|
||||
data_width_a : integer := 8;
|
||||
addr_width_b : integer := 8;
|
||||
data_width_b : integer := 8;
|
||||
mem_init_file : string := " "
|
||||
);
|
||||
PORT
|
||||
(
|
||||
clock : in STD_LOGIC;
|
||||
|
||||
address_a : in STD_LOGIC_VECTOR (addr_width_a-1 DOWNTO 0);
|
||||
data_a : in STD_LOGIC_VECTOR (data_width_a-1 DOWNTO 0) := (others => '0');
|
||||
enable_a : in STD_LOGIC := '1';
|
||||
wren_a : in STD_LOGIC := '0';
|
||||
q_a : out STD_LOGIC_VECTOR (data_width_a-1 DOWNTO 0);
|
||||
cs_a : in std_logic := '1';
|
||||
|
||||
address_b : in STD_LOGIC_VECTOR (addr_width_b-1 DOWNTO 0) := (others => '0');
|
||||
data_b : in STD_LOGIC_VECTOR (data_width_b-1 DOWNTO 0) := (others => '0');
|
||||
enable_b : in STD_LOGIC := '1';
|
||||
wren_b : in STD_LOGIC := '0';
|
||||
q_b : out STD_LOGIC_VECTOR (data_width_b-1 DOWNTO 0);
|
||||
cs_b : in std_logic := '1'
|
||||
);
|
||||
end entity;
|
||||
|
||||
|
||||
ARCHITECTURE SYN OF dpram_dif IS
|
||||
|
||||
signal q0 : std_logic_vector((data_width_a - 1) downto 0);
|
||||
signal q1 : std_logic_vector((data_width_b - 1) downto 0);
|
||||
|
||||
BEGIN
|
||||
q_a<= q0 when cs_a = '1' else (others => '1');
|
||||
q_b<= q1 when cs_b = '1' else (others => '1');
|
||||
|
||||
altsyncram_component : altsyncram
|
||||
GENERIC MAP (
|
||||
address_reg_b => "CLOCK1",
|
||||
clock_enable_input_a => "NORMAL",
|
||||
clock_enable_input_b => "NORMAL",
|
||||
clock_enable_output_a => "BYPASS",
|
||||
clock_enable_output_b => "BYPASS",
|
||||
indata_reg_b => "CLOCK1",
|
||||
intended_device_family => "Cyclone V",
|
||||
lpm_type => "altsyncram",
|
||||
numwords_a => 2**addr_width_a,
|
||||
numwords_b => 2**addr_width_b,
|
||||
operation_mode => "BIDIR_DUAL_PORT",
|
||||
outdata_aclr_a => "NONE",
|
||||
outdata_aclr_b => "NONE",
|
||||
outdata_reg_a => "UNREGISTERED",
|
||||
outdata_reg_b => "UNREGISTERED",
|
||||
power_up_uninitialized => "FALSE",
|
||||
read_during_write_mode_port_a => "NEW_DATA_NO_NBE_READ",
|
||||
read_during_write_mode_port_b => "NEW_DATA_NO_NBE_READ",
|
||||
init_file => mem_init_file,
|
||||
widthad_a => addr_width_a,
|
||||
widthad_b => addr_width_b,
|
||||
width_a => data_width_a,
|
||||
width_b => data_width_b,
|
||||
width_byteena_a => 1,
|
||||
width_byteena_b => 1,
|
||||
wrcontrol_wraddress_reg_b => "CLOCK1"
|
||||
)
|
||||
PORT MAP (
|
||||
address_a => address_a,
|
||||
address_b => address_b,
|
||||
clock0 => clock,
|
||||
clock1 => clock,
|
||||
clocken0 => enable_a,
|
||||
clocken1 => enable_b,
|
||||
data_a => data_a,
|
||||
data_b => data_b,
|
||||
wren_a => wren_a and cs_a,
|
||||
wren_b => wren_b and cs_b,
|
||||
q_a => q0,
|
||||
q_b => q1
|
||||
);
|
||||
|
||||
END SYN;
|
||||
|
||||
|
||||
--------------------------------------------------------------
|
||||
-- Dual port Block RAM different parameters and clocks on ports
|
||||
--------------------------------------------------------------
|
||||
LIBRARY ieee;
|
||||
USE ieee.std_logic_1164.all;
|
||||
|
||||
LIBRARY altera_mf;
|
||||
USE altera_mf.altera_mf_components.all;
|
||||
|
||||
entity dpram_difclk is
|
||||
generic (
|
||||
addr_width_a : integer := 8;
|
||||
data_width_a : integer := 8;
|
||||
addr_width_b : integer := 8;
|
||||
data_width_b : integer := 8;
|
||||
mem_init_file : string := " "
|
||||
);
|
||||
PORT
|
||||
(
|
||||
clk_a : in STD_LOGIC;
|
||||
clk_b : in STD_LOGIC;
|
||||
|
||||
address_a : in STD_LOGIC_VECTOR (addr_width_a-1 DOWNTO 0);
|
||||
data_a : in STD_LOGIC_VECTOR (data_width_a-1 DOWNTO 0) := (others => '0');
|
||||
enable_a : in STD_LOGIC := '1';
|
||||
wren_a : in STD_LOGIC := '0';
|
||||
q_a : out STD_LOGIC_VECTOR (data_width_a-1 DOWNTO 0);
|
||||
cs_a : in std_logic := '1';
|
||||
|
||||
address_b : in STD_LOGIC_VECTOR (addr_width_b-1 DOWNTO 0) := (others => '0');
|
||||
data_b : in STD_LOGIC_VECTOR (data_width_b-1 DOWNTO 0) := (others => '0');
|
||||
enable_b : in STD_LOGIC := '1';
|
||||
wren_b : in STD_LOGIC := '0';
|
||||
q_b : out STD_LOGIC_VECTOR (data_width_b-1 DOWNTO 0);
|
||||
cs_b : in std_logic := '1'
|
||||
);
|
||||
end entity;
|
||||
|
||||
|
||||
ARCHITECTURE SYN OF dpram_difclk IS
|
||||
|
||||
signal q0 : std_logic_vector((data_width_a - 1) downto 0);
|
||||
signal q1 : std_logic_vector((data_width_b - 1) downto 0);
|
||||
|
||||
BEGIN
|
||||
q_a<= q0 when cs_a = '1' else (others => '1');
|
||||
q_b<= q1 when cs_b = '1' else (others => '1');
|
||||
|
||||
altsyncram_component : altsyncram
|
||||
GENERIC MAP (
|
||||
address_reg_b => "CLOCK1",
|
||||
clock_enable_input_a => "NORMAL",
|
||||
clock_enable_input_b => "NORMAL",
|
||||
clock_enable_output_a => "BYPASS",
|
||||
clock_enable_output_b => "BYPASS",
|
||||
indata_reg_b => "CLOCK1",
|
||||
intended_device_family => "Cyclone V",
|
||||
lpm_type => "altsyncram",
|
||||
numwords_a => 2**addr_width_a,
|
||||
numwords_b => 2**addr_width_b,
|
||||
operation_mode => "BIDIR_DUAL_PORT",
|
||||
outdata_aclr_a => "NONE",
|
||||
outdata_aclr_b => "NONE",
|
||||
outdata_reg_a => "UNREGISTERED",
|
||||
outdata_reg_b => "UNREGISTERED",
|
||||
power_up_uninitialized => "FALSE",
|
||||
read_during_write_mode_port_a => "NEW_DATA_NO_NBE_READ",
|
||||
read_during_write_mode_port_b => "NEW_DATA_NO_NBE_READ",
|
||||
init_file => mem_init_file,
|
||||
widthad_a => addr_width_a,
|
||||
widthad_b => addr_width_b,
|
||||
width_a => data_width_a,
|
||||
width_b => data_width_b,
|
||||
width_byteena_a => 1,
|
||||
width_byteena_b => 1,
|
||||
wrcontrol_wraddress_reg_b => "CLOCK1"
|
||||
)
|
||||
PORT MAP (
|
||||
address_a => address_a,
|
||||
address_b => address_b,
|
||||
clock0 => clk_a,
|
||||
clock1 => clk_b,
|
||||
clocken0 => enable_a,
|
||||
clocken1 => enable_b,
|
||||
data_a => data_a,
|
||||
data_b => data_b,
|
||||
wren_a => wren_a and cs_a,
|
||||
wren_b => wren_b and cs_b,
|
||||
q_a => q0,
|
||||
q_b => q1
|
||||
);
|
||||
|
||||
END SYN;
|
||||
314
rtl/common/ide.v
Normal file
314
rtl/common/ide.v
Normal file
@@ -0,0 +1,314 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Alexey Melnikov
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
module ide
|
||||
(
|
||||
input clk,
|
||||
input rst_n,
|
||||
|
||||
output reg irq,
|
||||
output drq,
|
||||
|
||||
input use_fast, // 1 - supports fast read mode
|
||||
output no_data, // pause for system when no data is available in fast mode
|
||||
|
||||
output [1:0] drive_en,
|
||||
|
||||
input [3:0] io_address,
|
||||
input io_read,
|
||||
output reg [31:0] io_readdata,
|
||||
input io_write,
|
||||
input [31:0] io_writedata,
|
||||
input io_32,
|
||||
|
||||
output reg io_wait,
|
||||
|
||||
output reg [2:0] request,
|
||||
|
||||
input [3:0] mgmt_address,
|
||||
input mgmt_write,
|
||||
input [15:0] mgmt_writedata,
|
||||
input mgmt_read,
|
||||
output reg [15:0] mgmt_readdata
|
||||
);
|
||||
|
||||
assign drq = status[3];
|
||||
assign drive_en = present;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
wire io_wr = io_write & |present;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
always @(posedge clk) if(io_read) begin
|
||||
if(!present) io_readdata <= 32'hFFFFFFFF;
|
||||
else begin
|
||||
case(io_address)
|
||||
0: io_readdata <= status[3] ? {buf_q[31:16], (~io_32 & io_cnt[0]) ? buf_q[31:16] : buf_q[15:0]} : 32'd0;
|
||||
1: io_readdata <= error;
|
||||
2: io_readdata <= (hob ? sector_count[15:8] : sector_count[7:0] );
|
||||
3: io_readdata <= (hob ? sector[15:8] : sector[7:0] );
|
||||
4: io_readdata <= (hob ? cylinder[23:16] : cylinder[7:0] );
|
||||
5: io_readdata <= (hob ? cylinder[31:24] : cylinder[15:8] );
|
||||
6: io_readdata <= drv_addr;
|
||||
7: io_readdata <= status;
|
||||
14: io_readdata <= status;
|
||||
15: io_readdata <= { 2'b10, ~drv_addr[3:0], ~drv_addr[4], drv_addr[4]};
|
||||
default: io_readdata <= 0;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
reg [7:0] features;
|
||||
always @(posedge clk) begin
|
||||
if(~rst_n) features <= 8'h00;
|
||||
else if(io_wr && io_address == 1) features <= io_writedata[7:0];
|
||||
end
|
||||
|
||||
reg [15:0] blk_size;
|
||||
always @(posedge clk) begin
|
||||
if(~rst_n) blk_size <= 16'h0000;
|
||||
else if(mgmt_write && mgmt_address == 0) blk_size <= {mgmt_writedata[7:0], 8'h00};
|
||||
else if(mgmt_write && mgmt_address == 4 && blk_size[15]) blk_size <= mgmt_writedata[15:0];
|
||||
end
|
||||
|
||||
reg [7:0] error;
|
||||
always @(posedge clk) begin
|
||||
if(~rst_n) error <= 8'h00;
|
||||
else if(mgmt_write && mgmt_address == 0) error <= mgmt_writedata[15:8];
|
||||
end
|
||||
|
||||
reg [15:0] sector_count;
|
||||
always @(posedge clk) begin
|
||||
if(~rst_n) sector_count <= 16'd1;
|
||||
else if(mgmt_write && mgmt_address == 1) sector_count[7:0] <= mgmt_writedata[7:0];
|
||||
else if(mgmt_write && mgmt_address == 3) sector_count[15:8] <= mgmt_writedata[7:0];
|
||||
else if(io_wr && io_address == 2) sector_count <= {sector_count[7:0], io_writedata[7:0]};
|
||||
end
|
||||
|
||||
reg [15:0] sector;
|
||||
always @(posedge clk) begin
|
||||
if(~rst_n) sector <= 16'd1;
|
||||
else if(mgmt_write && mgmt_address == 1) sector[7:0] <= mgmt_writedata[15:8];
|
||||
else if(mgmt_write && mgmt_address == 3) sector[15:8] <= mgmt_writedata[15:8];
|
||||
else if(io_wr && io_address == 3) sector <= {sector[7:0],io_writedata[7:0]};
|
||||
end
|
||||
|
||||
reg [31:0] cylinder;
|
||||
always @(posedge clk) begin
|
||||
if(~rst_n) cylinder <= 32'hFFFFFFFF;
|
||||
else if(mgmt_write && mgmt_address == 2) cylinder[15:0] <= mgmt_writedata[15:0];
|
||||
else if(mgmt_write && mgmt_address == 4) cylinder[31:16] <= mgmt_writedata[15:0];
|
||||
else if(io_wr && io_address == 4) {cylinder[23:16], cylinder[7:0] } <= {cylinder[7:0], io_writedata[7:0]};
|
||||
else if(io_wr && io_address == 5) {cylinder[31:24], cylinder[15:8]} <= {cylinder[15:8], io_writedata[7:0]};
|
||||
end
|
||||
|
||||
reg [7:0] drv_addr;
|
||||
always @(posedge clk) begin
|
||||
if(~rst_n) drv_addr <= 8'd0;
|
||||
else if(mgmt_write && mgmt_address == 5) drv_addr <= mgmt_writedata[7:0];
|
||||
else if(io_wr && io_address == 6) drv_addr <= io_writedata[7:0];
|
||||
end
|
||||
|
||||
reg [7:0] cmd;
|
||||
always @(posedge clk) begin
|
||||
if(~rst_n) cmd <= 8'd0;
|
||||
else if(io_wr && io_address == 7) cmd <= io_writedata[7:0];
|
||||
end
|
||||
|
||||
reg [7:0] status = 0;
|
||||
always @(posedge clk) begin
|
||||
if(reset) status <= 8'h80;
|
||||
else if(mgmt_write && mgmt_address == 5) status <= {mgmt_writedata[15:14],1'b0,mgmt_writedata[12:11],2'b00,mgmt_writedata[8]};
|
||||
else if(io_wr && io_address == 7) status <= 8'h80;
|
||||
else if(io_done & drq & last_read) status <= 8'h40;
|
||||
else if(io_done & drq) status <= 8'h80;
|
||||
end
|
||||
|
||||
reg last_read = 0;
|
||||
always @(posedge clk) begin
|
||||
if(reset) last_read <= 0;
|
||||
else if(mgmt_write && mgmt_address == 5) last_read <= mgmt_writedata[9];
|
||||
else if(io_done & drq) last_read <= 0;
|
||||
end
|
||||
|
||||
reg fast_read = 0;
|
||||
always @(posedge clk) begin
|
||||
if(reset) fast_read <= 0;
|
||||
else if(mgmt_write && mgmt_address == 5) fast_read <= mgmt_writedata[13];
|
||||
else if(io_done & drq) fast_read <= 0;
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if(~rst_n) io_wait <= 1'd0;
|
||||
else if(sw_reset) io_wait <= use_wait;
|
||||
else if(mgmt_write && mgmt_address == 5) io_wait <= 1'd0;
|
||||
else if(io_wr && io_address == 7) io_wait <= use_wait;
|
||||
else if(io_done & drq) io_wait <= use_wait;
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if(reset) request <= 3'b110; // reset
|
||||
else if(mgmt_write && mgmt_address == 5) request <= 3'b000;
|
||||
else if(io_wr && io_address == 7) request <= 3'b100; // new command
|
||||
else if(io_done & drq & ~last_read) request <= 3'b101; // data send/recv
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if(reset) irq <= 1'b0;
|
||||
else if(mgmt_write && mgmt_address == 5 && mgmt_writedata[10] && ~disable_irq) irq <= 1'b1;
|
||||
else if((io_read | io_wr) && io_address == 7) irq <= 1'b0;
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
case(mgmt_address)
|
||||
0: mgmt_readdata <= {features, 6'd0, use_fast, io_done};
|
||||
1: mgmt_readdata <= {sector[7:0], sector_count[7:0]};
|
||||
2: mgmt_readdata <= {cylinder[15:0]};
|
||||
3: mgmt_readdata <= {sector[15:8], sector_count[15:8]};
|
||||
4: mgmt_readdata <= {cylinder[31:16]};
|
||||
5: mgmt_readdata <= {cmd, drv_addr};
|
||||
default: mgmt_readdata <= (mgmt_cnt[0]) ? buf_readdata[31:16] : buf_readdata[15:0];
|
||||
endcase
|
||||
end
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
reg [1:0] hob_ena = 0;
|
||||
reg [1:0] present = 0;
|
||||
always @(posedge clk) begin
|
||||
if(mgmt_write && mgmt_address == 6 && mgmt_writedata[3]) {hob_ena[0], present[0]} <= mgmt_writedata[1:0];
|
||||
if(mgmt_write && mgmt_address == 6 && mgmt_writedata[7]) {hob_ena[1], present[1]} <= mgmt_writedata[5:4];
|
||||
end
|
||||
|
||||
reg use_wait = 0;
|
||||
always @(posedge clk) begin
|
||||
if(mgmt_write && mgmt_address == 6 && mgmt_writedata[9]) use_wait <= mgmt_writedata[8];
|
||||
end
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
wire reset = ~rst_n | sw_reset;
|
||||
|
||||
reg disable_irq;
|
||||
always @(posedge clk) begin
|
||||
if(reset) disable_irq <= 1'b0;
|
||||
else if(io_wr && io_address == 14) disable_irq <= io_writedata[1];
|
||||
end
|
||||
|
||||
reg sw_reset;
|
||||
always @(posedge clk) begin
|
||||
if(~rst_n) sw_reset <= 1'b0;
|
||||
else if(io_wr && io_address == 14) sw_reset <= io_writedata[2];
|
||||
end
|
||||
|
||||
reg hob_pre;
|
||||
always @(posedge clk) begin
|
||||
if(reset) hob_pre <= 1'b0;
|
||||
else if(io_wr && io_address == 14) hob_pre <= io_writedata[7];
|
||||
end
|
||||
|
||||
reg hob;
|
||||
always @(posedge clk) hob <= hob_pre & hob_ena[drv_addr[4]];
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
wire write_data_io = io_wr && io_address == 0 && drq;
|
||||
wire read_data_io = io_read && io_address == 0 && drq;
|
||||
|
||||
wire io_done = (blk_size && io_cnt >= blk_size);
|
||||
reg [13:0] io_cnt;
|
||||
wire io_stb = read_data_io | write_data_io;
|
||||
|
||||
always @(posedge clk) begin
|
||||
reg old_stb, r_32;
|
||||
old_stb <= io_stb;
|
||||
|
||||
if(io_stb) r_32 <= io_32;
|
||||
|
||||
if(reset) io_cnt <= 0;
|
||||
else if(mgmt_write && mgmt_address == 5) io_cnt <= 0;
|
||||
else if(old_stb & ~io_stb) io_cnt <= io_cnt + 1'd1 + r_32;
|
||||
end
|
||||
|
||||
reg [13:0] mgmt_cnt;
|
||||
always @(posedge clk) begin
|
||||
reg old_wr, old_rd;
|
||||
|
||||
old_wr <= mgmt_write;
|
||||
old_rd <= mgmt_read;
|
||||
if((old_wr & ~mgmt_write) | (old_rd & ~mgmt_read)) begin
|
||||
if(&mgmt_address) mgmt_cnt <= mgmt_cnt + 1'd1;
|
||||
else mgmt_cnt <= 0;
|
||||
end
|
||||
|
||||
if(~rst_n) mgmt_cnt <= 0;
|
||||
end
|
||||
|
||||
wire n_data = (mgmt_cnt[13:1] <= io_cnt[13:1]) && drq && fast_read;
|
||||
reg [1:0] n_data_r;
|
||||
assign no_data = n_data || n_data_r;
|
||||
always @(posedge clk) n_data_r <= {n_data_r[0], n_data};
|
||||
|
||||
wire [31:0] buf_readdata;
|
||||
wire [31:0] buf_q;
|
||||
|
||||
dpram #(12,16) io_buf0
|
||||
(
|
||||
.clock(clk),
|
||||
|
||||
.address_a(mgmt_cnt[12:1]),
|
||||
.data_a(mgmt_writedata),
|
||||
.wren_a(mgmt_write & &mgmt_address & ~mgmt_cnt[0]),
|
||||
.q_a(buf_readdata[15:0]),
|
||||
|
||||
.address_b(io_cnt[12:1]),
|
||||
.data_b(io_writedata[15:0]),
|
||||
.wren_b(write_data_io & (io_32 | ~io_cnt[0])),
|
||||
.q_b(buf_q[15:0])
|
||||
);
|
||||
|
||||
dpram #(12,16) io_buf1
|
||||
(
|
||||
.clock(clk),
|
||||
|
||||
.address_a(mgmt_cnt[12:1]),
|
||||
.data_a(mgmt_writedata),
|
||||
.wren_a(mgmt_write & &mgmt_address & mgmt_cnt[0]),
|
||||
.q_a(buf_readdata[31:16]),
|
||||
|
||||
.address_b(io_cnt[12:1]),
|
||||
.data_b(io_32 ? io_writedata[31:16] : io_writedata[15:0]),
|
||||
.wren_b(write_data_io & (io_32 | io_cnt[0])),
|
||||
.q_b(buf_q[31:16])
|
||||
);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
endmodule
|
||||
Reference in New Issue
Block a user