OpenCores
URL https://opencores.org/ocsvn/zx_ula/zx_ula/trunk

Subversion Repositories zx_ula

[/] [zx_ula/] [trunk/] [fpga_version/] [rtl/] [ula.v] - Diff between revs 2 and 6

Only display areas with differences | Details | Blame | View Log

Rev 2 Rev 6
`timescale 1ns / 1ps
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
// Company:        Dept. Architecture and Computing Technology. University of Seville
// Company:        Dept. Architecture and Computing Technology. University of Seville
// Engineer:       Miguel Angel Rodriguez Jodar
// Engineer:       Miguel Angel Rodriguez Jodar. rodriguj@atc.us.es
// 
// 
// Create Date:    19:13:39 4-Apr-2012 
// Create Date:    19:13:39 4-Apr-2012 
// Design Name:    ULA
// Design Name:    ZX Spectrum
// Module Name:    ula_reference_design 
// Module Name:    ula 
// Project Name: 
// Project Name: 
// Target Devices: 
// Target Devices: 
// Tool versions: 
// Tool versions: 
// Description: 
// Description: 
//
//
// Dependencies: 
// Dependencies: 
//
//
// Revision: 
// Revision: 
// Revision 0.01 - File Created
// Revision 1.00 - File Created
// Additional Comments: 
// Additional Comments: GPL License policies apply to the contents of this file.
//
//
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
 
 
`define cyclestart(a,b) ((a)==(b))
`define cyclestart(a,b) ((a)==(b))
`define cycleend(a,b) ((a)==(b+1))
`define cycleend(a,b) ((a)==(b+1))
 
 
module ula(
module ula(
    input clk14,                        // 14MHz master clock
    input clk14,                        // 14MHz master clock
         // CPU interfacing
         // CPU interfacing
    input [15:0] a,              // Address bus from CPU (not all lines are used)
    input [15:0] a,              // Address bus from CPU (not all lines are used)
    input [7:0] din,             // Input data bus from CPU
    input [7:0] din,             // Input data bus from CPU
         output [7:0] dout,      // Output data bus to CPU
         output [7:0] dout,      // Output data bus to CPU
    input mreq_n,                       // MREQ from CPU
    input mreq_n,                       // MREQ from CPU
    input iorq_n,                       // IORQ from CPU
    input iorq_n,                       // IORQ from CPU
    input rd_n,                 // RD from CPU
    input rd_n,                 // RD from CPU
    input wr_n,                 // WR from CPU
    input wr_n,                 // WR from CPU
         input rfsh_n,                  // RFSH from CPU
         input rfsh_n,                  // RFSH from CPU
         output clkcpu,         // CLK to CPU
         output clkcpu,         // CLK to CPU
         output msk_int_n,      // Vertical retrace interrupt, to CPU
         output msk_int_n,      // Vertical retrace interrupt, to CPU
         // VRAM interfacing
         // VRAM interfacing
    output [13:0] va,     // Address bus to VRAM (16K)
    output [13:0] va,     // Address bus to VRAM (16K)
         input [7:0] vramdout,// Data from VRAM to ULA/CPU
         input [7:0] vramdout,// Data from VRAM to ULA/CPU
         output [7:0] vramdin,// Data from CPU to VRAM
         output [7:0] vramdin,// Data from CPU to VRAM
    output vramoe,               // 
    output vramoe,               // 
    output vramcs,               // Control signals for VRAM
    output vramcs,               // Control signals for VRAM
    output vramwe,               //
    output vramwe,               //
         // ULA I/O
         // ULA I/O
    input ear,                             //
    input ear,                             //
    output mic,                    // I/O ports
    output mic,                    // I/O ports
    output spk,            //
    output spk,            //
         output [7:0] kbrows,   // Keyboard rows
         output [7:0] kbrows,   // Keyboard rows
    input [4:0] kbcolumns,       //  Keyboard columns
    input [4:0] kbcolumns,       //  Keyboard columns
         // Video output
         // Video output
    output r,                           //
    output r,                           //
    output g,                           // RGB TTL signal
    output g,                           // RGB TTL signal
    output b,                           // with separate bright
    output b,                           // with separate bright
    output i,                           // and composite sync
    output i,                           // and composite sync
    output csync                        //               
    output csync                        //               
    );
    );
 
 
        reg [2:0] BorderColor = 3'b100;
        reg [2:0] BorderColor = 3'b100;
 
 
        // Pixel clock
        // Pixel clock
        reg clk7 = 0;
        reg clk7 = 0;
        always @(posedge clk14)
        always @(posedge clk14)
                clk7 <= !clk7;
                clk7 <= !clk7;
 
 
        // Horizontal counter
        // Horizontal counter
        reg [8:0] hc = 0;
        reg [8:0] hc = 0;
        always @(posedge clk7) begin
        always @(posedge clk7) begin
                if (hc==447)
                if (hc==447)
                        hc <= 0;
                        hc <= 0;
                else
                else
                        hc <= hc + 1;
                        hc <= hc + 1;
        end
        end
 
 
        // Vertical counter
        // Vertical counter
        reg [8:0] vc = 0;
        reg [8:0] vc = 0;
        always @(posedge clk7) begin
        always @(posedge clk7) begin
                if (hc==447) begin
                if (hc==447) begin
                        if (vc == 311)
                        if (vc == 311)
                                vc <= 0;
                                vc <= 0;
                        else
                        else
                                vc <= vc + 1;
                                vc <= vc + 1;
                end
                end
        end
        end
 
 
        // HBlank generation
        // HBlank generation
        reg HBlank_n = 1;
        reg HBlank_n = 1;
        always @(negedge clk7) begin
        always @(negedge clk7) begin
                if (`cyclestart(hc,320))
                if (`cyclestart(hc,320))
                        HBlank_n <= 0;
                        HBlank_n <= 0;
                else if (`cycleend(hc,415))
                else if (`cycleend(hc,415))
                        HBlank_n <= 1;
                        HBlank_n <= 1;
        end
        end
 
 
        // HSync generation (6C ULA version)
        // HSync generation (6C ULA version)
        reg HSync_n = 1;
        reg HSync_n = 1;
        always @(negedge clk7) begin
        always @(negedge clk7) begin
                if (`cyclestart(hc,344))
                if (`cyclestart(hc,344))
                        HSync_n <= 0;
                        HSync_n <= 0;
                else if (`cycleend(hc,375))
                else if (`cycleend(hc,375))
                        HSync_n <= 1;
                        HSync_n <= 1;
        end
        end
 
 
        // VBlank generation
        // VBlank generation
        reg VBlank_n = 1;
        reg VBlank_n = 1;
        always @(negedge clk7) begin
        always @(negedge clk7) begin
                if (`cyclestart(vc,248))
                if (`cyclestart(vc,248))
                        VBlank_n <= 0;
                        VBlank_n <= 0;
                else if (`cycleend(vc,255))
                else if (`cycleend(vc,255))
                        VBlank_n <= 1;
                        VBlank_n <= 1;
        end
        end
 
 
        // VSync generation (PAL)
        // VSync generation (PAL)
        reg VSync_n = 1;
        reg VSync_n = 1;
        always @(negedge clk7) begin
        always @(negedge clk7) begin
                if (`cyclestart(vc,248))
                if (`cyclestart(vc,248))
                        VSync_n <= 0;
                        VSync_n <= 0;
                else if (`cycleend(vc,251))
                else if (`cycleend(vc,251))
                        VSync_n <= 1;
                        VSync_n <= 1;
        end
        end
 
 
        // INT generation
        // INT generation
        reg INT_n = 1;
        reg INT_n = 1;
        assign msk_int_n = INT_n;
        assign msk_int_n = INT_n;
        always @(negedge clk7) begin
        always @(negedge clk7) begin
                if (`cyclestart(vc,248) && `cyclestart(hc,0))
                if (`cyclestart(vc,248) && `cyclestart(hc,0))
                        INT_n <= 0;
                        INT_n <= 0;
                else if (`cyclestart(vc,248) && `cycleend(hc,31))
                else if (`cyclestart(vc,248) && `cycleend(hc,31))
                        INT_n <= 1;
                        INT_n <= 1;
        end
        end
 
 
        // Border control signal (=0 when we're not displaying paper/ink pixels)
        // Border control signal (=0 when we're not displaying paper/ink pixels)
        reg Border_n = 1;
        reg Border_n = 1;
        always @(negedge clk7) begin
        always @(negedge clk7) begin
                if ( (vc[7] & vc[6]) | vc[8] | hc[8])
                if ( (vc[7] & vc[6]) | vc[8] | hc[8])
                        Border_n <= 0;
                        Border_n <= 0;
                else
                else
                        Border_n <= 1;
                        Border_n <= 1;
        end
        end
 
 
        // VidEN generation (delaying Border 8 clocks)
        // VidEN generation (delaying Border 8 clocks)
        reg VidEN_n = 1;
        reg VidEN_n = 1;
        always @(negedge clk7) begin
        always @(negedge clk7) begin
                if (hc[3])
                if (hc[3])
                        VidEN_n <= !Border_n;
                        VidEN_n <= !Border_n;
        end
        end
 
 
        // DataLatch generation (posedge to capture data from memory)
        // DataLatch generation (posedge to capture data from memory)
        reg DataLatch_n = 1;
        reg DataLatch_n = 1;
        always @(negedge clk7) begin
        always @(negedge clk7) begin
                if (hc[0] & !hc[1] & Border_n & hc[3])
                if (hc[0] & !hc[1] & Border_n & hc[3])
                        DataLatch_n <= 0;
                        DataLatch_n <= 0;
                else
                else
                        DataLatch_n <= 1;
                        DataLatch_n <= 1;
        end
        end
 
 
        // AttrLatch generation (posedge to capture data from memory)
        // AttrLatch generation (posedge to capture data from memory)
        reg AttrLatch_n = 1;
        reg AttrLatch_n = 1;
        always @(negedge clk7) begin
        always @(negedge clk7) begin
                if (hc[0] & hc[1] & Border_n & hc[3])
                if (hc[0] & hc[1] & Border_n & hc[3])
                        AttrLatch_n <= 0;
                        AttrLatch_n <= 0;
                else
                else
                        AttrLatch_n <= 1;
                        AttrLatch_n <= 1;
        end
        end
 
 
        // SLoad generation (negedge to load shift register)
        // SLoad generation (negedge to load shift register)
        reg SLoad = 0;
        reg SLoad = 0;
        always @(negedge clk7) begin
        always @(negedge clk7) begin
                if (!hc[0] & !hc[1] & hc[2] & !VidEN_n)
                if (!hc[0] & !hc[1] & hc[2] & !VidEN_n)
                        SLoad <= 1;
                        SLoad <= 1;
                else
                else
                        SLoad <= 0;
                        SLoad <= 0;
        end
        end
 
 
        // AOLatch generation (negedge to update attr output latch)
        // AOLatch generation (negedge to update attr output latch)
        reg AOLatch_n = 1;
        reg AOLatch_n = 1;
        always @(negedge clk7) begin
        always @(negedge clk7) begin
                if (hc[0] & !hc[1] & hc[2])
                if (hc[0] & !hc[1] & hc[2])
                        AOLatch_n <= 0;
                        AOLatch_n <= 0;
                else
                else
                        AOLatch_n <= 1;
                        AOLatch_n <= 1;
        end
        end
 
 
        // First buffer for bitmap
        // First buffer for bitmap
        reg [7:0] BitmapReg = 0;
        reg [7:0] BitmapReg = 0;
        always @(negedge DataLatch_n) begin
        always @(negedge DataLatch_n) begin
                BitmapReg <= vramdout;
                BitmapReg <= vramdout;
        end
        end
 
 
        // Shift register (second bitmap register)
        // Shift register (second bitmap register)
        reg [7:0] SRegister = 0;
        reg [7:0] SRegister = 0;
        always @(negedge clk7) begin
        always @(negedge clk7) begin
                if (SLoad)
                if (SLoad)
                        SRegister <= BitmapReg;
                        SRegister <= BitmapReg;
                else
                else
                        SRegister <= {SRegister[6:0],1'b0};
                        SRegister <= {SRegister[6:0],1'b0};
        end
        end
 
 
        // First buffer for attribute
        // First buffer for attribute
        reg [7:0] AttrReg = 0;
        reg [7:0] AttrReg = 0;
        always @(negedge AttrLatch_n) begin
        always @(negedge AttrLatch_n) begin
                AttrReg <= vramdout;
                AttrReg <= vramdout;
        end
        end
 
 
        // Second buffer for attribute
        // Second buffer for attribute
        reg [7:0] AttrOut = 0;
        reg [7:0] AttrOut = 0;
        always @(negedge AOLatch_n) begin
        always @(negedge AOLatch_n) begin
                if (!VidEN_n)
                if (!VidEN_n)
                        AttrOut <= AttrReg;
                        AttrOut <= AttrReg;
                else
                else
                        AttrOut <= {2'b00,BorderColor,BorderColor};
                        AttrOut <= {2'b00,BorderColor,BorderColor};
        end
        end
 
 
        // Flash counter and pixel generation
        // Flash counter and pixel generation
        reg [4:0] FlashCnt = 0;
        reg [4:0] FlashCnt = 0;
        always @(negedge VSync_n) begin
        always @(negedge VSync_n) begin
                FlashCnt <= FlashCnt + 1;
                FlashCnt <= FlashCnt + 1;
        end
        end
        wire Pixel = SRegister[7] ^ (AttrOut[7] & FlashCnt[4]);
        wire Pixel = SRegister[7] ^ (AttrOut[7] & FlashCnt[4]);
 
 
        // RGB generation
        // RGB generation
        reg rI,rG,rR,rB;
        reg rI,rG,rR,rB;
        assign r = rR;
        assign r = rR;
        assign g = rG;
        assign g = rG;
        assign b = rB;
        assign b = rB;
        assign i = rI;
        assign i = rI;
        always @(*) begin
        always @(*) begin
                if (HBlank_n && VBlank_n)
                if (HBlank_n && VBlank_n)
                        {rI,rG,rR,rB} = (Pixel)? {AttrOut[6],AttrOut[2:0]} : {AttrOut[6],AttrOut[5:3]};
                        {rI,rG,rR,rB} = (Pixel)? {AttrOut[6],AttrOut[2:0]} : {AttrOut[6],AttrOut[5:3]};
                else
                else
                        {rI,rG,rR,rB} = 4'b0000;
                        {rI,rG,rR,rB} = 4'b0000;
        end
        end
 
 
        //CSync generation
        //CSync generation
        assign csync = HSync_n & VSync_n;
        assign csync = HSync_n & VSync_n;
 
 
        // VRAM address and control line generation
        // VRAM address and control line generation
        reg [13:0] rVA = 0;
        reg [13:0] rVA = 0;
        reg rVCS = 0;
        reg rVCS = 0;
        reg rVOE = 0;
        reg rVOE = 0;
        reg rVWE = 0;
        reg rVWE = 0;
        assign va = rVA;
        assign va = rVA;
        assign vramcs = rVCS;
        assign vramcs = rVCS;
        assign vramoe = rVOE;
        assign vramoe = rVOE;
        assign vramwe = rVWE;
        assign vramwe = rVWE;
        // Latches to hold delayed versions of V and H counters
        // Latches to hold delayed versions of V and H counters
        reg [8:0] v = 0;
        reg [8:0] v = 0;
        reg [8:0] c = 0;
        reg [8:0] c = 0;
        // Address and control line multiplexor ULA/CPU
        // Address and control line multiplexor ULA/CPU
        always @(negedge clk7) begin
        always @(negedge clk7) begin
                if (Border_n && (hc[3:0]==4'b0111 || hc[3:0]==4'b1011)) begin     // cycles 7 and 11: load V and C from VC and HC
                if (Border_n && (hc[3:0]==4'b0111 || hc[3:0]==4'b1011)) begin     // cycles 7 and 11: load V and C from VC and HC
                        c <= hc;
                        c <= hc;
                        v <= vc;
                        v <= vc;
                end
                end
        end
        end
        // Address and control line multiplexor ULA/CPU
        // Address and control line multiplexor ULA/CPU
        always @(*) begin
        always @(*) begin
                if (Border_n && (hc[3:0]==4'b1000 || hc[3:0]==4'b1001 || hc[3:0]==4'b1100 || hc[3:0]==4'b1101)) begin       // cycles 8 and 12: present display address to VRAM 
                if (Border_n && (hc[3:0]==4'b1000 || hc[3:0]==4'b1001 || hc[3:0]==4'b1100 || hc[3:0]==4'b1101)) begin       // cycles 8 and 12: present display address to VRAM 
                        rVA = {1'b0,v[7:6],v[2:0],v[5:3],c[7:3]};                                                // (cycles 9 and 13 load display byte)
                        rVA = {1'b0,v[7:6],v[2:0],v[5:3],c[7:3]};                                                // (cycles 9 and 13 load display byte)
                        rVCS = 1;
                        rVCS = 1;
                        rVOE = 1;
                        rVOE = !hc[0];
                        rVWE = 0;
                        rVWE = 0;
                end
                end
                else if (Border_n && (hc[3:0]==4'b1010 || hc[3:0]==4'b1011 || hc[3:0]==4'b1110 || hc[3:0]==4'b1111)) begin  // cycles 10 and 14: present attribute address to VRAM
                else if (Border_n && (hc[3:0]==4'b1010 || hc[3:0]==4'b1011 || hc[3:0]==4'b1110 || hc[3:0]==4'b1111)) begin  // cycles 10 and 14: present attribute address to VRAM
                        rVA = {4'b0110,v[7:3],c[7:3]};                                                                          // (cycles 11 and 15 load attr byte)
                        rVA = {4'b0110,v[7:3],c[7:3]};                                                                          // (cycles 11 and 15 load attr byte)
                        rVCS = 1;
                        rVCS = 1;
                        rVOE = 1;
                        rVOE = !hc[0];
 
                        rVWE = 0;
 
                end
 
                else if (Border_n && hc[3:0]==4'b0000) begin
 
                        rVA = a[13:0];
 
                        rVCS = 0;
 
                        rVOE = 0;
                        rVWE = 0;
                        rVWE = 0;
                end
                end
                else begin      // when VRAM is not in use by ULA, give it to CPU
                else begin      // when VRAM is not in use by ULA, give it to CPU
                        rVA = a[13:0];
                        rVA = a[13:0];
                        rVCS = !a[15] & a[14] & !mreq_n;
                        rVCS = !a[15] & a[14] & !mreq_n;
                        rVOE = !rd_n;
                        rVOE = !rd_n;
                        rVWE = !wr_n;
                        rVWE = !wr_n;
                end
                end
        end
        end
 
 
        // CPU contention
        // CPU contention
        reg CPUClk = 0;
        reg CPUClk = 0;
        assign clkcpu = CPUClk;
        assign clkcpu = CPUClk;
        reg ioreqtw3 = 0;
        reg ioreqtw3 = 0;
        reg mreqt23 = 0;
        reg mreqt23 = 0;
        wire ioreq_n = a[0] | iorq_n;
        wire ioreq_n = a[0] | iorq_n;
        wire Nor1 = (~(a[14] | ~ioreq_n)) |
        wire Nor1 = (~(a[14] | ~ioreq_n)) |
                    (~(~a[15] | ~ioreq_n)) |
                    (~(~a[15] | ~ioreq_n)) |
                                        (~(hc[2] | hc[3])) |
                                        (~(hc[2] | hc[3])) |
                                        (~Border_n | ~ioreqtw3 | ~CPUClk | ~mreqt23);
                                        (~Border_n | ~ioreqtw3 | ~CPUClk | ~mreqt23);
        wire Nor2 = (~(hc[2] | hc[3])) |
        wire Nor2 = (~(hc[2] | hc[3])) |
                    ~Border_n |
                    ~Border_n |
                                        ~CPUClk |
                                        ~CPUClk |
                                        ioreq_n |
                                        ioreq_n |
                                        ~ioreqtw3;
                                        ~ioreqtw3;
        wire CLKContention = ~Nor1 | ~Nor2;
        wire CLKContention = ~Nor1 | ~Nor2;
        always @(posedge clk7) begin    // change clk7 by clk14 for 7MHz CPU clock operation
        always @(posedge clk7) begin    // change clk7 by clk14 for 7MHz CPU clock operation
                if (CPUClk && !CLKContention)   // if there's no contention, the clock can go low
                if (CPUClk && !CLKContention)   // if there's no contention, the clock can go low
                        CPUClk <= 0;
                        CPUClk <= 0;
                else
                else
                        CPUClk <= 1;
                        CPUClk <= 1;
        end
        end
        always @(posedge CPUClk) begin
        always @(posedge CPUClk) begin
                ioreqtw3 <= ioreq_n;
                ioreqtw3 <= ioreq_n;
                mreqt23 <= mreq_n;
                mreqt23 <= mreq_n;
        end
        end
 
 
        // ULA-CPU interface
        // ULA-CPU interface
        assign dout = (!a[15] & a[14] & !mreq_n)?         vramdout : // CPU reads VRAM through ULA as in the +3, not directly
        assign dout = (!a[15] & a[14] & !mreq_n)? vramdout : // CPU reads VRAM through ULA as in the +3, not directly
                      (!iorq_n & !a[0])?                  {1'b1,ear,1'b1,kbcolumns} :    // CPU reads keyboard and EAR state
                      (!iorq_n & !a[0])?                  {1'b1,ear,1'b1,kbcolumns} :    // CPU reads keyboard and EAR state
                                          (Border_n)?                         vramdout :  // to emulate
                                          (Border_n)?                  AttrReg :  // to emulate
                                                                              8'hFF;     // port FF
                                                                              8'hFF;     // port FF
        assign vramdin = din;           // The CPU doesn't need to share the memory input data bus with the ULA
        assign vramdin = din;           // The CPU doesn't need to share the memory input data bus with the ULA
        assign kbrows = {a[11]? 1'bz : 0,        // high impedance or 0, as if diodes were been placed in between
        assign kbrows = {a[11]? 1'bz : 1'b0,    // high impedance or 0, as if diodes were been placed in between
                                                  a[10]? 1'bz : 0,       // if the keyboard matrix is to be implemented within the FPGA, then
                                                  a[10]? 1'bz : 1'b0,   // if the keyboard matrix is to be implemented within the FPGA, then
                                                  a[9]?  1'bz : 0,       // there's no need to do this.
                                                  a[9]?  1'bz : 1'b0,   // there's no need to do this.
                                                  a[12]? 1'bz : 0,
                                                  a[12]? 1'bz : 1'b0,
                                                  a[13]? 1'bz : 0,
                                                  a[13]? 1'bz : 1'b0,
                                                  a[8]?  1'bz : 0,
                                                  a[8]?  1'bz : 1'b0,
                                                  a[14]? 1'bz : 0,
                                                  a[14]? 1'bz : 1'b0,
                                                  a[15]? 1'bz : 0 };
                                                  a[15]? 1'bz : 1'b0 };
 
//      assign kbrows = {a[8]? 1'bz : 1'b0,     // high impedance or 0, as if diodes were been placed in between
 
//                                                a[9]? 1'bz : 1'b0,    // if the keyboard matrix is to be implemented within the FPGA, then
 
//                                                a[10]?  1'bz : 1'b0,  // there's no need to do this.
 
//                                                a[11]? 1'bz : 1'b0,
 
//                                                a[12]? 1'bz : 1'b0,
 
//                                                a[13]?  1'bz : 1'b0,
 
//                                                a[14]? 1'bz : 1'b0,
 
//                                                a[15]? 1'bz : 1'b0 };
        reg rMic = 0;
        reg rMic = 0;
        reg rSpk = 0;
        reg rSpk = 0;
        assign mic = rMic;
        assign mic = rMic;
        assign spk = rSpk;
        assign spk = rSpk;
        always @(negedge clk7) begin
        always @(negedge clk7) begin
                if (!iorq_n & !a[0] & !wr_n)
                if (!iorq_n & !a[0] & !wr_n)
                        {rSpk,rMic,BorderColor} <= din[5:0];
                        {rSpk,rMic,BorderColor} <= din[5:0];
        end
        end
endmodule
endmodule
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.