Top secrets sources NedoPC ngs

Rev

Rev 119 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed | ?url?

// part of NeoGS flash programmer project (c) 2014 lvd^NedoPC
//
// zxbus controller

module zxbus
(
        input  wire clk,
        input  wire rst_n,
       
        inout  wire [7:0] zxid, // zxbus DATA BUS in/out [7:0]
        input  wire [7:0] zxa,  // zxbus ADDRESS 7-0 in [7:0]
        input  wire       zxiorq_n,
        input  wire       zxmreq_n,
        input  wire       zxrd_n,
        input  wire       zxwr_n,
        output wire       zxblkiorq_n, // active low - signal to generate IORQGE
        output reg        zxbusin,    // controls 74hct245 buffer direction (1 - input from bus, 0 - output to zx)
        output reg        zxbusena_n, // 74hct245 buffer enable signal

        output reg        init, // positive pulse to cause reset/init to all board
        input  wire       init_in_progress, // 1 while init in progress

        output reg        led, // LED state

        output reg        autoinc_ena, // enable autoincrement

        output reg        wr_addr,   // to ROM controller
        output reg        wr_data,   //
        output reg        rd_data,   //
        output reg  [7:0] wr_buffer, //
        input  wire [7:0] rd_buffer  //
);

        wire iowr = ~(zxiorq_n | zxwr_n);
        wire iord = ~(zxiorq_n | zxrd_n);

        reg [2:0] iowr_r;
        reg [2:0] iord_r;

        wire iowr_begin, iowr_end;
        wire iord_begin, iord_end;
       
        wire io_begin, io_end;

        wire addr_ok;

        reg wrr;


        wire [1:0] regsel;


        reg [7:0] read_data;


        reg        zxid_oe;
        reg  [7:0] zxid_out;
        wire [7:0] zxid_in;



        reg [8:0] test_reg;
        reg [7:0] test_reg_pre;
        reg       test_reg_write;





        // register select (one of 4)
        assign regsel[1:0] = { zxa[7], zxa[3] };



        // addr decode
        assign addr_ok = (zxa==8'h33) || (zxa==8'h3B) || (zxa==8'hB3) || (zxa==8'hBB);

        // IORQGE
        assign zxblkiorq_n = ~addr_ok;


        // internal data bus control
        assign zxid = zxid_oe ? zxid_out : 8'bZZZZ_ZZZZ;
        //
        assign zxid_in = zxid;



        // resync strobes
        always @(posedge clk)
        begin
                iowr_r[2:0] <= { iowr_r[1:0], iowr };
                iord_r[2:0] <= { iord_r[1:0], iord };
        end
        //
        assign iowr_begin = iowr_r[1] && !iowr_r[2];
        assign iord_begin = iord_r[1] && !iord_r[2];
        //
        assign iowr_end = !iowr_r[1] && iowr_r[2];
        assign iord_end = !iord_r[1] && iord_r[2];
        //
        assign io_begin = iowr_begin || iord_begin;
        assign io_end   = iowr_end   || iord_end;


        // control ext bus buffer
        always @(posedge clk, negedge rst_n)
        if( !rst_n )
        begin
                zxbusin    <= 1'b1;
                zxbusena_n <= 1'b1;
        end
        else if( addr_ok && io_begin )
        begin
                zxbusin    <= ~iord_begin;
                zxbusena_n <= 1'b0;
        end
        else if( io_end )
        begin
                zxbusena_n <= 1'b1;
        end

        // control int bus buffer
        always @(posedge clk, negedge rst_n)
        if( !rst_n )
        begin
                zxid_oe <= 1'b0;
        end
        else if( addr_ok && io_begin )
        begin
                zxid_oe <= iord_begin;
        end
        else if( io_end )
        begin
                zxid_oe <= 1'b0;
        end

        // internal write strobe
        always @(posedge clk, negedge rst_n)
        if( !rst_n )
                wrr <= 1'b0;
        else
                wrr <= addr_ok && iowr_begin;



        // write to 33 (init/ctrl reg)
        //
        always @(posedge clk, negedge rst_n)
        if( !rst_n )
                led <= 1'b0;
        else if( init )
                led <= 1'b0;
        else if( wrr && regsel==2'b00 && zxid[6] )
                led <= ~led;
        //
        always @(posedge clk, negedge rst_n)
        if( !rst_n )
                init <= 1'b0;
        else if( wrr && regsel==2'b00 && zxid[7] )
                init <= 1'b1;
        else
                init <= 1'b0;
        //
        always @(posedge clk, negedge rst_n)
        if( !rst_n )
                autoinc_ena <= 1'b0;
        else if( wrr && regsel==2'b00 )
                autoinc_ena <= zxid[5];


        // write to 3B (test reg)
        always @(posedge clk, negedge rst_n)
        if( !rst_n )
        begin
                test_reg <= 9'd0;
        end
        else if( init )
        begin
                test_reg <= 9'd0;
        end
        else if( test_reg_write )
        begin
                test_reg[8:0] <= { (~test_reg_pre[7:0]), test_reg[8] };
        end
        //
        always @(posedge clk)
        if( wrr && regsel==2'b01 )
        begin
                test_reg_pre <= zxid_in;
                test_reg_write <= 1'b1;
        end
        else
        begin
                test_reg_write <= 1'b0;
        end


        // write to B3 (addr reg)
        always @(posedge clk)
        if( wrr && regsel==2'b10 )
                wr_addr <= 1'b1;
        else
                wr_addr <= 1'b0;

        // write to BB (data reg)
        always @(posedge clk)
        if( wrr && regsel==2'b11 )
                wr_data <= 1'b1;
        else
                wr_data <= 1'b0;

        // read from BB (data reg)
        always @(posedge clk)
        if( addr_ok && regsel==2'b11 && iord_begin )
                rd_data <= 1'b1;
        else
                rd_data <= 1'b0;

        // write data for B3 and BB
        always @(posedge clk)
        if( wrr && regsel[1]==1'b1 )
                wr_buffer <= zxid_in;


        // ports read
        always @*
        case( regsel )
                2'b00:   read_data = { init_in_progress, 7'd0 };
                2'b01:   read_data = test_reg[7:0];
                //2'b10:   read_data <= рег адреса (НОЛЬ!)
                2'b11:   read_data = rd_buffer;
                default: read_data = 8'd0;
        endcase
        //
        always @(posedge clk)
        if( addr_ok && iord_begin )
                zxid_out <= read_data;



endmodule