// ZXiznet project
 
// (c) NedoPC 2012
 
//
 
// zx-bus functions: ports mapping/access, ROM mapping
 
 
 
module zbus
 
#(
 
        parameter LCELLS=1
 
)
 
(
 
        input  wire [15:0] za,
 
        inout  wire [ 7:0] zd,
 
        //
 
        inout  wire [ 7:0] bd,
 
        //
 
        input  wire        ziorq_n,
 
        input  wire        zrd_n,
 
        input  wire        zwr_n,
 
        input  wire        zmreq_n,
 
        output wire        ziorqge,
 
        output wire        zblkrom,
 
        input  wire        zcsrom_n,
 
        input  wire        zrst_n,
 
 
 
        //
 
        output wire        ports_wrena,
 
        output wire        ports_wrstb_n,
 
        output wire [ 1:0] ports_addr,
 
        output wire [ 7:0] ports_wrdata,
 
        input  wire [ 7:0] ports_rddata,
 
        
 
        //
 
        input  wire [ 1:0] rommap_win,
 
        input  wire        rommap_ena,
 
 
 
        //
 
        output wire        sl811_cs_n,
 
        output wire        sl811_a0,
 
 
 
        //
 
        output wire        w5300_cs_n,
 
        input  wire        w5300_ports
 
);
 
        localparam BASE_ADDR = 8'hAB;
 
 
 
 
 
        wire ziorq_n_lcell;
 
        wire zi[LCELLS-1:0];
 
 
 
 
 
        wire io_addr_ok;
 
 
 
        wire mrd, mwr;
 
 
 
        wire ena_dbuf;
 
        wire ena_din;
 
        wire ena_dout;
 
 
 
 
 
        // addr decode
 
        assign io_addr_ok = (za[7:0]==BASE_ADDR);
 
 
 
 
 
        // IORQGE
 
        assign ziorqge = io_addr_ok ? 1'b1 : 1'bZ;
 
 
 
 
 
 
 
        // ports write
 
        assign ports_addr = za[9:8];
 
        //
 
        assign ports_wrdata = zd;
 
        //
 
        assign ports_wrena   = io_addr_ok && za[15];
 
        assign ports_wrstb_n = ziorq_n_lcell | zwr_n;
 
 
 
        genvar i;
 
        generate
 
                for(i=0;i<LCELLS;i=i+1)
 
                begin : gen_iorq_wait
 
                        if(i==0)
 
                                lcell lcelliorq(ziorq_n,zi[0]);
 
                        else
 
                                lcell lcelliorq(zi[i-1],zi[i]);
 
                end
 
        endgenerate
 
 
 
        lcell lcelliorq(ziorq_n & zi[LCELLS-1], ziorq_n_lcell);
 
 
 
 
 
        // sl811 chip select and A0
 
        assign sl811_cs_n = !( !w5300_ports && io_addr_ok && ( !za[15] || (za[15] && za[9:8]==2'b00) ) && !ziorq_n_lcell );
 
        //
 
        assign sl811_a0 = ~za[15];
 
 
 
 
 
        // w5300 chip select
 
        assign mwr = !zmreq_n && !zwr_n && (za[15:14]==rommap_win) && rommap_ena;
 
        assign mrd = !zmreq_n && !zrd_n && !zcsrom_n && (za[15:14]==rommap_win) && rommap_ena;
 
        //
 
        assign w5300_cs_n = ~(mwr || mrd || ( w5300_ports && io_addr_ok && !za[15] && !ziorq_n_lcell ) );
 
 
 
        // block ROM
 
        assign zblkrom = (rommap_ena && (za[15:14]==rommap_win)) ? 1'b1 : 1'bZ;
 
 
 
 
 
 
 
        assign ena_dbuf = (~sl811_cs_n) | (~w5300_cs_n);
 
        assign ena_din  = ~zwr_n;
 
        assign ena_dout = ~zrd_n;
 
 
 
 
 
        // ports data read/buffering
 
        assign zd = (io_addr_ok && !ziorq_n_lcell && !zrd_n && za[15] && (za[9:8]!=2'b00)) ?
 
                    ports_rddata : ( (ena_dbuf && ena_dout) ? bd : 8'bZZZZ_ZZZZ );
 
 
 
 
 
        assign bd = (ena_dbuf && ena_din) ? zd : 8'bZZZZ_ZZZZ;
 
 
 
endmodule