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

Subversion Repositories aoocs

[/] [aoocs/] [trunk/] [rtl/] [ocs_control.v] - Rev 2

Compare with Previous | Blame | View Log

/*
 * Copyright 2010, Aleksander Osman, alfik@poczta.fm. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are
 * permitted provided that the following conditions are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice, this list of
 *     conditions and the following disclaimer.
 *
 *  2. 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 AUTHOR ``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 AUTHOR 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.
 */
 
/*! \file
 * \brief OCS system control implementation with WISHBONE slave interface.
 */
 
/*! \brief \copybrief ocs_control.v
 
List of system control registers:
\verbatim
Implemented:
     [DDFSTOP      094  W   A     Display bitplane data fetch stop              
                                  (horiz. position)                             write not implemented here]
    DMACON       096  W   ADP     DMA control write (clear or set)              write not implemented here
 
    DMACONR     *002  R   AP      DMA control (and blitter status) read
    VPOSR       *004  R   A( E )  Read vert most signif. bit (and frame flop)
    VHPOSR      *006  R   A       Read vert and horiz. position of beam
 
    ADKCON       09E  W   P       Audio, disk, UART control
 
    ADKCONR     *010  R   P       Audio, disk control register read
     [POT0DAT   *012  R   P( E )  Pot counter pair 0 data (vert,horiz)          read implemented here]
 
    INTENAR     *01C  R   P       Interrupt enable bits read
    INTREQR     *01E  R   P       Interrupt request bits read
 
     [CLXCON     098  W   D       Collision control                             write not implemented here]
    INTENA       09A  W   P       Interrupt enable bits (clear or set bits)     write not implemented here
    INTREQ       09C  W   P       Interrupt request bits (clear or set bits)
 
Not implemented:
    REFPTR    & *028  W   A       Refresh pointer                               
    VPOSW       *02A  W   A       Write vert most signif. bit (and frame flop)  
    VHPOSW      *02C  W   A       Write vert and horiz position of beam
 
    STREQU    & *038  S   D       Strobe for horiz sync with VB and EQU
    STRVBL    & *03A  S   D       Strobe for horiz sync with VB (vert. blank)
    STRHOR    & *03C  S   DP      Strobe for horiz sync
    STRLONG   & *03E  S   D( E )  Strobe for identification of long horiz. line.
 
    RESERVED     1110X
    RESERVED     1111X
    NO-OP(NULL)  1FE
\endverbatim
*/
module ocs_control(
    //% \name Clock and reset
    //% @{
    input               clk_30,
    input               reset_n,
    //% @}
 
    //% \name WISHBONE slave
    //% @{
    input               CYC_I,
    input               STB_I,
    input               WE_I,
    input [8:2]         ADR_I,
    input [3:0]         SEL_I,
    input [31:0]        slave_DAT_I,
    output reg [31:0]   slave_DAT_O,
    output reg          ACK_O,
    //% @}
 
    //% \name Not aligned register access on a 32-bit WISHBONE bus
    //% @{
        // INTENA write not implemented here
    input               na_int_ena_write,
    input [15:0]        na_int_ena,
    input [1:0]         na_int_ena_sel,
        // DMACON write not implemented here
    input               na_dma_con_write,
    input [15:0]        na_dma_con,
    input [1:0]         na_dma_con_sel,
        // POT0DAT read implemented here
    output              na_pot0dat_read,
    input [15:0]        na_pot0dat,
    //% @}
 
    //% \name Internal OCS ports: beam counters
    //% @{
    output reg          line_start,
    output reg          line_pre_start,
    output reg [8:0]    line_number,
    output reg [8:0]    column_number,
    //% @}
 
    //% \name Internal OCS ports: clock pulses for CIA and audio
    //% @{
    output reg          pulse_709379_hz,
    output              pulse_color,
    //% @}
 
    //% \name Internal OCS ports: global registers and blitter signals
    //% @{
    output reg [10:0]   dma_con,
    output reg [14:0]   adk_con,
 
    input               blitter_busy,
    input               blitter_zero,
    //% @}
 
    //% \name Internal OCS ports: interrupts
    //% @{
    input               blitter_irq,
    input               cia_a_irq,
    input               cia_b_irq,
    input               floppy_syn_irq,
    input               floppy_blk_irq,
    input               serial_rbf_irq,
    input               serial_tbe_irq,
    input [3:0]         audio_irq,
 
    output [2:0]        interrupt
    //% @}
);
 
assign interrupt =
    (int_ena[14] == 1'b0)? 3'd0 :
    (int_ena[13] == 1'b1 && int_req[13] == 1'b1) ? 3'd6 :
    (int_ena[12] == 1'b1 && int_req[12] == 1'b1) ? 3'd5 :
    (int_ena[11] == 1'b1 && int_req[11] == 1'b1) ? 3'd5 :
    (int_ena[10] == 1'b1 && int_req[10] == 1'b1) ? 3'd4 :
    (int_ena[9] == 1'b1 && int_req[9] == 1'b1) ? 3'd4 :
    (int_ena[8] == 1'b1 && int_req[8] == 1'b1) ? 3'd4 :
    (int_ena[7] == 1'b1 && int_req[7] == 1'b1) ? 3'd4 :
    (int_ena[6] == 1'b1 && int_req[6] == 1'b1) ? 3'd3 :
    (int_ena[5] == 1'b1 && int_req[5] == 1'b1) ? 3'd3 :
    (int_ena[4] == 1'b1 && int_req[4] == 1'b1) ? 3'd3 :
    (int_ena[3] == 1'b1 && int_req[3] == 1'b1) ? 3'd2 :
    (int_ena[2] == 1'b1 && int_req[2] == 1'b1) ? 3'd1 :
    (int_ena[1] == 1'b1 && int_req[1] == 1'b1) ? 3'd1 :
    (int_ena[0] == 1'b1 && int_req[0] == 1'b1) ? 3'd1 :
    3'd0;
 
wire [14:0] new_int_req;
assign new_int_req = {
    1'b0,
    cia_b_irq,
    floppy_syn_irq,
    serial_rbf_irq,
    audio_irq[3:0],
    blitter_irq,
    (line_start == 1'b1 && line_number == 9'd0),
    1'b0,
    cia_a_irq,
    1'b0,
    floppy_blk_irq,
    serial_tbe_irq
};
 
reg [14:0] int_ena;
reg [14:0] int_req;
reg [10:0] column_counter;
reg long_frame;
 
assign na_pot0dat_read = (CYC_I == 1'b1 && STB_I == 1'b1 && ACK_O == 1'b0 && WE_I == 1'b0 && { ADR_I, 2'b0 } == 9'h010 && SEL_I[1:0] != 2'b00);
 
always @(posedge clk_30 or negedge reset_n) begin
    if(reset_n == 1'b0) begin
        slave_DAT_O <= 32'd0;
        ACK_O <= 1'b0;
 
        line_start <= 1'b0;
        line_pre_start <= 1'b0;
        line_number <= 9'd0;
        column_number <= 9'd0;
 
        dma_con <= 11'd0;
        int_req <= 15'd0;
        int_ena <= 15'd0;
        adk_con <= 15'd0;
        column_counter <= 11'd0;
        long_frame <= 1'b0;
    end
    else begin
        if(na_dma_con_write == 1'b1 && na_dma_con_sel[1:0] == 2'b11) begin
            if(na_dma_con[15] == 1'b1)  dma_con <= dma_con | na_dma_con[10:0];
            else                        dma_con <= dma_con & (~na_dma_con[10:0]);
        end
 
        if(na_int_ena_write == 1'b1 && na_int_ena_sel[1:0] == 2'b11) begin
            if(na_int_ena[15] == 1'b1)  int_ena <= int_ena | na_int_ena[14:0];
            else                        int_ena <= int_ena & (~na_int_ena[14:0]);
        end
 
        if(column_counter == 11'd1919)  column_counter <= 11'd0;
        else                            column_counter <= column_counter + 11'd1;
 
        if(column_counter == 11'd1918)  line_pre_start <= 1'b1;
        else                            line_pre_start <= 1'b0;
 
        if(column_counter == 11'd1919)  line_start <= 1'b1;
        else                            line_start <= 1'b0;
 
        if(column_counter == 11'd1919) begin
            column_number <= 9'd0;
 
            if(line_number == 9'd311 && long_frame == 1'b0) begin
                line_number <= 9'd0;
                long_frame <= 1'b1;
            end
            else if(line_number == 9'd312 && long_frame == 1'b1) begin
                line_number <= 9'd0;
                long_frame <= 1'b0;
            end
            else line_number <= line_number + 9'd1;
        end
        else if(column_counter > 11'd600 /*time for 6 bitplain*/) begin
            if(column_counter[0] == 1'b1 && column_number < 9'd452 /*226*2*/)  column_number <= column_number + 9'd1;
        end
 
        if(ACK_O == 1'b1) ACK_O <= 1'b0;
 
        if(CYC_I == 1'b1 && STB_I == 1'b1 && ACK_O == 1'b0) begin
            ACK_O <= 1'b1;
 
            // BLTDDAT not used, DMACONR
            if(WE_I == 1'b0 && { ADR_I, 2'b0 } == 9'h000)       slave_DAT_O <= { 16'd0, 1'b0, blitter_busy, blitter_zero, 2'b00, dma_con[10:0] };
            // VPOSR, VHPOSR
            else if(WE_I == 1'b0 && { ADR_I, 2'b0 } == 9'h004)  slave_DAT_O <= { long_frame, 14'd0, line_number[8:0], column_number[8:1] };
            // INTENAR, INTREQR
            else if(WE_I == 1'b0 && { ADR_I, 2'b0 } == 9'h01C)  slave_DAT_O <= { 1'b0, int_ena[14:0], 1'b0, int_req[14:0] };
            // ADKCONR, POT0DAT read implemented here
            else if(WE_I == 1'b0 && { ADR_I, 2'b0 } == 9'h010)  slave_DAT_O <= { 1'b0, adk_con[14:0], na_pot0dat };
            // INTREQ, ADKCON
            else if(WE_I == 1'b1 && { ADR_I, 2'b0 } == 9'h09C) begin
                if(SEL_I[1:0] == 2'b11) begin
                    if(slave_DAT_I[15] == 1'b1) adk_con <= adk_con | slave_DAT_I[14:0];
                    else                        adk_con <= adk_con & (~slave_DAT_I[14:0]);
                end
            end
        end
 
        if(CYC_I == 1'b1 && STB_I == 1'b1 && ACK_O == 1'b0 && WE_I == 1'b1 && { ADR_I, 2'b0 } == 9'h09C && SEL_I[3:2] == 2'b11) begin
            if(slave_DAT_I[31] == 1'b1) int_req <= (int_req | (new_int_req /*& int_ena*/)) | slave_DAT_I[30:16];
            else                        int_req <= (int_req | (new_int_req /*& int_ena*/)) & (~slave_DAT_I[30:16]);
        end
        else                            int_req <= (int_req | (new_int_req /*& int_ena*/));
 
    end
end
 
 
 
 
// 1/10 fCPU == 1/20 color clock
reg [2:0] counter_709379_hz;
always @(posedge clk_30 or negedge reset_n) begin
    if(reset_n == 1'b0) begin
        counter_709379_hz <= 3'd0;
        pulse_709379_hz <= 1'b0;
    end
    else if(pulse_color == 1'b1) begin
        if(counter_709379_hz == 3'd4) begin
            pulse_709379_hz <= 1'b1;
            counter_709379_hz <= 3'd0;
        end
        else begin
            pulse_709379_hz <= 1'b0;
            counter_709379_hz <= counter_709379_hz + 3'd1;
        end
    end
    else begin
        pulse_709379_hz <= 1'b0;
    end
end
 
// 1/2 fCPU = 1 color clock
// 3.546875MHz
assign pulse_color = (pulse_cpu == 1'b1) && (pulse_counter == 1'b1);
 
reg pulse_counter;
always @(posedge clk_30 or negedge reset_n) begin
    if(reset_n == 1'b0)         pulse_counter <= 1'b0;
    else if(pulse_cpu == 1'b1)  pulse_counter <= ~pulse_counter;
end
 
// fCPU
// in: 30MHz, out: 7.09375MHz -> 960 - 227
reg [10:0] counter_cpu;
reg pulse_cpu;
always @(posedge clk_30 or negedge reset_n) begin
    if(reset_n == 1'b0) begin
        counter_cpu <= 11'd960;
        pulse_cpu <= 1'b0;
    end
    else if(counter_cpu <= 11'd114) begin
        counter_cpu <= counter_cpu - 11'd227 + 11'd960;
        pulse_cpu <= 1'b1;
    end
    else if(counter_cpu < 11'd227) begin
        counter_cpu <= counter_cpu + 11'd960;
        pulse_cpu <= 1'b0;
    end
    else if(counter_cpu > 11'd960) begin
        counter_cpu <= counter_cpu - 11'd227 - 11'd227;
        pulse_cpu <= 1'b1;
    end
    else begin
        counter_cpu <= counter_cpu - 11'd227;
        pulse_cpu <= 1'b0;
    end
end
 
endmodule
 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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