// simulate together CPU, DRAM and VIDEO FETCH
 
 
 
`include "../include/tune.v"
 
 
 
module tb_cdv;
 
 
 
 
 
        reg rst_n;
 
        reg clk;
 
 
 
        wire zclk,zclk_out;
 
        wire mreq_n,iorq_n,rd_n,wrbad_n,m1_n,rfsh_n;
 
        reg wr_n;
 
        tri [7:0] zdata;
 
        wire [15:0] zaddr;
 
 
 
        wire [7:0] ramout;
 
        wire ram_ena;
 
 
 
        wire [4:0] rompg;
 
        wire romoe_n,romwe_n,csrom;
 
        wire [7:0] romdata;
 
 
 
 
 
        wire cbeg,pre_cend,cend;
 
 
 
        wire cpu_req,cpu_rnw,cpu_wrbsel,cpu_strobe;
 
        wire [20:0] cpu_addr;
 
        wire [7:0] cpu_wrdata;
 
        wire [15:0] cpu_rddata;
 
        wire cpu_stall;
 
        wire [4:0] cpu_waitcyc;
 
 
 
        wire video_strobe,video_next;
 
        wire [15:0] video_data;
 
        wire [20:0] video_addr;
 
 
 
        wire go;
 
        wire [1:0] bw;
 
 
 
 
 
        wire [20:0] daddr;
 
        wire dreq,drnw,drrdy;
 
        wire [1:0] dbsel;
 
        wire [15:0] drddata;
 
        wire [15:0] dwrdata;
 
 
 
 
 
        wire [9:0] ra;
 
        tri [15:0] rd;
 
        wire rwe_n,rucas_n,rlcas_n,rras0_n,rras1_n;
 
 
 
 
 
 
 
 
 
        wire hsync,hblank,hpix,hsync_start,line_start;
 
 
 
        wire vblank,vsync,vpix,int_start;
 
 
 
        wire [5:0] pixel;
 
 
 
 
 
        initial
 
        begin
 
                clk = 1'b0;
 
                forever #17 clk = ~clk;
 
        end
 
 
 
 
 
        integer rst_count;
 
        initial
 
        begin
 
            rst_n <= 1'b0;
 
 
 
                for(rst_count=0;rst_count<=32;rst_count=rst_count+1) @(posedge clk);
 
 
 
                rst_n <= 1'b1;
 
        end
 
 
 
 
 
 
 
 
 
        // for simulation
 
        integer i;
 
        initial
 
        begin
 
                for(i=0;i<32768;i=i+1)
 
                begin
 
                        chip0.array[i] = 16'd0;
 
                        chip1.array[i] = 16'd0;
 
                end
 
 
 
 
 
 
 
                for(i=16'h000;i<16'h1b00;i=i+2)
 
                begin
 
//                      zxmemwrite(5,i,i+16'h4000); // this particular thing is to check zx-mode addressing
 
 
 
                        zxmemwrite(4,i,i);
 
                        zxmemwrite(5,i,i+16'h4000);
 
                        zxmemwrite(4,i+16'h2000,i+16'h2000);
 
                        zxmemwrite(5,i+16'h2000,i+16'h6000);
 
 
 
                end
 
 
 
 
 
 
 
        end
 
 
 
 
 
        task zxmemwrite; // writes a word given zx page and page offset (must be even)
 
 
 
                input [2:0] page;
 
                input [13:0] offset;
 
                input [15:0] data;
 
 
 
                reg [14:0] wordaddr;
 
                begin
 
                        wordaddr = { page[2:0], offset[13:2] };
 
 
 
                        if( !offset[1] )
 
                                        chip0.array[wordaddr] = data;
 
                        else
 
                                        chip1.array[wordaddr] = data;
 
                end
 
 
 
        endtask
 
 
 
 
 
 
 
        // route data to the Z80 bus
 
 
 
        assign zdata = ram_ena ? ramout : 8'hZZ;
 
        assign zdata = romdata;
 
 
 
 
 
 
 
 
 
 
 
        T80a z80( .RESET_n(/*rst_n*/1'b0),
 
                  .CLK_n(zclk),
 
                  .WAIT_n(1'b1),
 
                  .INT_n(1'b1),
 
                  .NMI_n(1'b1),
 
                  .M1_n(m1_n),
 
                  .RFSH_n(rfsh_n),
 
                  .MREQ_n(mreq_n),
 
                  .IORQ_n(iorq_n),
 
                  .RD_n(rd_n),
 
                  .WR_n(wrbad_n),
 
                  .BUSRQ_n(1'b1),
 
                  .A(zaddr),
 
                  .D(zdata) );
 
 
 
        //correct wr_n (valid only for MEMORY operations!)
 
        always @(negedge zclk)
 
                wr_n <= wrbad_n;
 
 
 
 
 
 
 
        zclock z80clock( .rst_n(rst_n),
 
                         .fclk(clk),
 
                         .zclk_out(zclk_out),
 
                         .zclk(zclk),
 
                         .turbo(2'b01),
 
                         .pre_cend(pre_cend) );
 
 
 
        assign zclk = ~zclk_out; // inversion in the schematics!
 
 
 
 
 
 
 
        zmem z80memory( .rst_n(rst_n),
 
                        .fclk(clk),
 
                        .zpos(1'b1),
 
                        .zneg(1'b0),
 
 
 
                        .cend(cend),
 
                        .pre_cend(pre_cend),
 
 
 
                        .za(zaddr),
 
                        .zd_in(zdata),
 
                        .zd_out(ramout),
 
                        .zd_ena(ram_ena),
 
 
 
                        .m1_n(m1_n),
 
                        .rfsh_n(rfsh_n),
 
                        .mreq_n(mreq_n),
 
                        .iorq_n(iorq_n),
 
                        .rd_n(rd_n),
 
                        .wr_n(wr_n),
 
 
 
                        .win0_romnram(1'b1),
 
                        .win1_romnram(1'b0),
 
                        .win2_romnram(1'b0),
 
                        .win3_romnram(1'b0),
 
 
 
                        .win0_page(8'd0),
 
                        .win1_page(8'd1),
 
                        .win2_page(8'd2),
 
                        .win3_page(8'd3),
 
 
 
                        .dos(1'b0),
 
 
 
                        .rompg(rompg),
 
                        .romoe_n(romoe_n),
 
                        .romwe_n(romwe_n),
 
                        .csrom(csrom),
 
 
 
 
 
                        .cpu_req(cpu_req),
 
                        .cpu_rnw(cpu_rnw),
 
                        .cpu_wrbsel(cpu_wrbsel),
 
                        .cpu_strobe(cpu_strobe),
 
 
 
                        .cpu_addr(cpu_addr),
 
                        .cpu_wrdata(cpu_wrdata),
 
                        .cpu_rddata(cpu_rddata) );
 
 
 
 
 
        arbiter dramarb( .clk(clk),
 
                         .rst_n(rst_n),
 
 
 
                         .dram_addr(daddr),
 
                         .dram_req(dreq),
 
                         .dram_rnw(drnw),
 
                         .dram_cbeg(cbeg),
 
                         .dram_rrdy(drrdy),
 
                         .dram_bsel(dbsel),
 
                         .dram_rddata(drddata),
 
                         .dram_wrdata(dwrdata),
 
 
 
                         .cend(cend),
 
                         .pre_cend(pre_cend),
 
 
 
                         .go(go),
 
                         .bw(bw),
 
 
 
                         .video_addr(video_addr),
 
                         .video_data(video_data),
 
                         .video_strobe(video_strobe),
 
                         .video_next(video_next),
 
 
 
                         .cpu_waitcyc(cpu_waitcyc),
 
                         .cpu_stall(cpu_stall),
 
                         .cpu_req(cpu_req),
 
                         .cpu_rnw(cpu_rnw),
 
                         .cpu_addr(cpu_addr),
 
                         .cpu_wrbsel(cpu_wrbsel),
 
                         .cpu_wrdata(cpu_wrdata),
 
                         .cpu_rddata(cpu_rddata),
 
                         .cpu_strobe(cpu_strobe) );
 
 
 
 
 
        dram dramko( .clk(clk),
 
                     .rst_n(rst_n),
 
 
 
                     .addr(daddr),
 
                     .req(dreq),
 
                     .rnw(drnw),
 
                     .cbeg(cbeg),
 
                     .rrdy(drrdy),
 
                     .rddata(drddata),
 
                     .wrdata(dwrdata),
 
                     .bsel(dbsel),
 
 
 
                     .ra(ra),
 
                     .rd(rd),
 
                     .rwe_n(rwe_n),
 
                     .rucas_n(rucas_n),
 
                     .rlcas_n(rlcas_n),
 
                     .rras0_n(rras0_n),
 
                     .rras1_n(rras1_n) );
 
 
 
 
 
 
 
        drammem chip0( .ma(ra),
 
                       .d(rd),
 
                       .ras_n(rras0_n),
 
                       .ucas_n(rucas_n),
 
                       .lcas_n(rlcas_n),
 
                       .we_n(rwe_n) );
 
 
 
        drammem chip1( .ma(ra),
 
                       .d(rd),
 
                       .ras_n(rras1_n),
 
                       .ucas_n(rucas_n),
 
                       .lcas_n(rlcas_n),
 
                       .we_n(rwe_n) );
 
 
 
        defparam chip0._add_to_addr_=0;
 
        defparam chip1._add_to_addr_=1;
 
 
 
        defparam chip0._filter_out_=0;
 
        defparam chip1._filter_out_=0;
 
 
 
 
 
 
 
        rom romko( .addr( {rompg[1:0],zaddr[13:0]} ),
 
                   .data(romdata),
 
                   .ce_n( (~csrom)|romoe_n ) );
 
 
 
 
 
 
 
 
 
        synch horiz_sync( .clk(clk), .init(1'b0), .cend(cend), .pre_cend(pre_cend),
 
                          .hsync(hsync), .hblank(hblank), .hpix(hpix), .hsync_start(hsync_start),
 
                          .line_start(line_start) );
 
 
 
 
 
        syncv vert_sync( .clk(clk), .hsync_start(hsync_start), .line_start(line_start),
 
                         .vblank(vblank), .vsync(vsync), .int_start(int_start),
 
                         .vpix(vpix) );
 
 
 
 
 
 
 
        fetch fecher( .clk(clk), .cend(cend), .line_start(line_start), .vpix(vpix), .int_start(int_start),
 
                      .vmode(1'b1), .screen(1'b0), .video_addr(video_addr), .video_data(video_data), .video_strobe(video_strobe),
 
                      .video_next(video_next), .go(go), .bw(bw), .pixel(pixel) );
 
 
 
 
 
 
 
 
 
`ifdef FETCH_VERBOSE
 
 
 
        always
 
        begin
 
                @(posedge video_next);
 
                $write("video addr=$%h, ",video_addr); // address just before video_addr changes!
 
                @(posedge video_strobe); @(negedge clk);
 
                $write("data=$%h\n",video_data);
 
        end
 
 
 
        always
 
        begin
 
                @(negedge hsync)
 
                        if( vpix )
 
                                $display("new line");
 
        end
 
 
 
 
 
 
 
`endif
 
 
 
 
 
 
 
 
 
endmodule