From 909eb02485b9c0699057213786f9b452e910ce3d Mon Sep 17 00:00:00 2001 From: kitune-san <19359213+kitune-san@users.noreply.github.com> Date: Thu, 3 Nov 2022 21:48:12 +0900 Subject: [PATCH 1/2] Added IDE module from AO486_Mister project. --- rtl/common/bram.vhd | 330 ++++++++++++++++++++++++++++++++++++++++++++ rtl/common/ide.v | 314 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 644 insertions(+) create mode 100644 rtl/common/bram.vhd create mode 100644 rtl/common/ide.v diff --git a/rtl/common/bram.vhd b/rtl/common/bram.vhd new file mode 100644 index 0000000..28abdbd --- /dev/null +++ b/rtl/common/bram.vhd @@ -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; \ No newline at end of file diff --git a/rtl/common/ide.v b/rtl/common/ide.v new file mode 100644 index 0000000..3efe611 --- /dev/null +++ b/rtl/common/ide.v @@ -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 From 004b8d2428093a27b015561677993259b5715481 Mon Sep 17 00:00:00 2001 From: kitune-san <19359213+kitune-san@users.noreply.github.com> Date: Thu, 3 Nov 2022 21:50:52 +0900 Subject: [PATCH 2/2] Added XT-IDE conversion. --- PCXT.sv | 8 ++- rtl/KFPC-XT/HDL/Chipset.sv | 2 + rtl/KFPC-XT/HDL/Peripherals.sv | 118 ++++++++++++++++++++++++++++++++- rtl/KFPC-XT/HDL/XT2IDE.sv | 114 +++++++++++++++++++++++++++++++ 4 files changed, 238 insertions(+), 4 deletions(-) create mode 100644 rtl/KFPC-XT/HDL/XT2IDE.sv diff --git a/PCXT.sv b/PCXT.sv index 1a03433..b4b3b7f 100644 --- a/PCXT.sv +++ b/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) ); diff --git a/rtl/KFPC-XT/HDL/Chipset.sv b/rtl/KFPC-XT/HDL/Chipset.sv index 83f5e6e..4667099 100644 --- a/rtl/KFPC-XT/HDL/Chipset.sv +++ b/rtl/KFPC-XT/HDL/Chipset.sv @@ -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), diff --git a/rtl/KFPC-XT/HDL/Peripherals.sv b/rtl/KFPC-XT/HDL/Peripherals.sv index d6ef5ea..62472bf 100644 --- a/rtl/KFPC-XT/HDL/Peripherals.sv +++ b/rtl/KFPC-XT/HDL/Peripherals.sv @@ -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; diff --git a/rtl/KFPC-XT/HDL/XT2IDE.sv b/rtl/KFPC-XT/HDL/XT2IDE.sv new file mode 100644 index 0000000..fb14e3d --- /dev/null +++ b/rtl/KFPC-XT/HDL/XT2IDE.sv @@ -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