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

Subversion Repositories vg_z80_sbc

[/] [vg_z80_sbc/] [trunk/] [rtl/] [wb_vhdfd.v] - Rev 36

Go to most recent revision | Compare with Previous | Blame | View Log

//////////////////////////////////////////////////////////////////////
////                                                              ////
////  $Id: wb_vhdfd.v,v 1.4 2008-12-13 21:12:01 hharte Exp $      ////
////  wb_vhdfd.v - Vector Graphic HD/FD Disk Controller with      ////
////               Wishbone Slave interface.                      ////
////                                                              ////
////  This file is part of the Vector Graphic Z80 SBC Project     ////
////  http://www.opencores.org/projects/vg_z80_sbc/               ////
////                                                              ////
////  Author:                                                     ////
////      - Howard M. Harte (hharte@opencores.org)                ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
////                                                              ////
//// Copyright (C) 2008 Howard M. Harte                           ////
////                                                              ////
//// This source file may be used and distributed without         ////
//// restriction provided that this copyright statement is not    ////
//// removed from the file and that any derivative work contains  ////
//// the original copyright notice and the associated disclaimer. ////
////                                                              ////
//// This source file is free software; you can redistribute it   ////
//// and/or modify it under the terms of the GNU Lesser General   ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any   ////
//// later version.                                               ////
////                                                              ////
//// This source is distributed in the hope that it will be       ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
//// PURPOSE.  See the GNU Lesser General Public License for more ////
//// details.                                                     ////
////                                                              ////
//// You should have received a copy of the GNU Lesser General    ////
//// Public License along with this source; if not, download it   ////
//// from http://www.opencores.org/lgpl.shtml                     ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
 
//| Write           Read
//| C0 - CTRL0      STATUS0
//| C1 - CTRL1      STATUS1
//| C2 - DATA_PORT  DATA_PORT
//| C3 - START      RESET
 
`define CTRL0       4'b0001
`define CTRL1       4'b0010
`define DATA_PORT   4'b0100
`define START_CMD   4'b1000
 
`define STATUS0     4'b0001
`define STATUS1     4'b0010
`define RESET       4'b1000
 
module wb_vhdfd (clk_i, nrst_i, wbs_adr_i, wbs_dat_o, wbs_dat_i, wbs_sel_i, wbs_we_i,
				 wbs_stb_i, wbs_cyc_i, wbs_ack_o,
                 flash_adr_o,flash_dat_o, flash_dat_i, flash_oe, flash_ce, flash_we
                 );
 
    input             clk_i;
    input             nrst_i;
    input       [2:0] wbs_adr_i;
    output reg  [7:0] wbs_dat_o;
  	input 	    [7:0] wbs_dat_i;
    input 	    [3:0] wbs_sel_i;
  	input 	          wbs_we_i;
    input 	          wbs_stb_i;
    input 	          wbs_cyc_i;
    output reg        wbs_ack_o;
 
    // FLASH Interface
    output     [23:0] flash_adr_o;
    output      [7:0] flash_dat_o;
    input       [7:0] flash_dat_i;
    output            flash_oe;
    output            flash_ce;
    output            flash_we;
 
    reg         [7:0] ctrl0;
    reg         [7:0] ctrl1;
    reg               start_cmd;
 
    reg        [10:0] curr_track[0:3];
    reg         [8:0] sector_ram_ptr;
 
    // CTRL0 bits
    wire        [1:0] ds = ctrl0[1:0];    
    wire        [2:0] hds = ctrl0[4:2];
    wire              step_track = ctrl0[5];
    wire              step_dir = ctrl0[6];
 
    // CTRL1 bits
    wire        [4:0] sector = ctrl1[4:0];
    wire              disk_read = ctrl1[5];
 
    // STATUS0 bits
    wire     wp = 1'b0;     // Write protected, controller can't write to FLASH
    wire     track0 = (curr_track[ds] == 11'h0);
 
    // STATUS1 bits
    wire     fd_sel = (ds != 2'b00);  // Bit 0, floppy disk selected
    wire     ctrl_busy;     // Bit 1, Controller is busy.
    wire     motor_on = fd_sel;  // Bit 2, Motor On
    wire     hd_type = 1'b1; // Bit 3, Hard Disk Type, 1=10MB, 0=5MB
 
 
    wire  [7:0] sector_ram_dat_o;
 
    wire  [8:0] disk_adr;
    wire  [7:0] disk_dat_o;
    wire  [7:0] disk_dat_i;
    wire        disk_ram_wr;
 
    // generate wishbone register bank writes
    wire wbs_acc = wbs_cyc_i & wbs_stb_i;    // WISHBONE access
    wire wbs_wr  = wbs_acc & wbs_we_i & !wbs_ack_o;       // WISHBONE write access
    wire wbs_rd  = wbs_acc & !wbs_we_i & !wbs_ack_o;      // WISHBONE read access
 
    wire sector_ram_wr = (wbs_wr & (wbs_adr_i == 3'h2));
 
	always @(posedge clk_i or negedge nrst_i)
		if (~nrst_i)				// reset registers
			begin
                sector_ram_ptr <= 9'h0;
                start_cmd <= 1'b0;
                curr_track[0] <= 11'h010;
                curr_track[1] <= 11'h020;
                curr_track[2] <= 11'h030;
                curr_track[3] <= 11'h040;
			end
		else begin
            if(ctrl_busy == 1'b1) begin
                start_cmd <= 1'b0;
            end
            if(wbs_wr)          // wishbone write cycle
                case(wbs_adr_i)
                    3'h0: begin   // CTRL0
                        ctrl0 <= wbs_dat_i;
                        if(wbs_dat_i[5] == 1'b1) begin  // STEP
                            if(wbs_dat_i[6] == 1'b1) begin // Step In
                                curr_track[ds] <= curr_track[ds] + 11'h1;
                            end 
                            else begin  // Step Out
                                curr_track[ds] <= curr_track[ds] - 11'h1;
                            end
                        end
                    end
                    3'h1: begin   // CTRL1
                        ctrl1 <= wbs_dat_i;
                    end
                    3'h2: begin   // DATA_PORT
                        sector_ram_ptr <= sector_ram_ptr + 9'h001;
                    end
                    3'h3: begin   // START
                        start_cmd <= 1'b1;
                    end
			    endcase
            if(wbs_rd) begin
                case(wbs_adr_i) // Wishbone Read, decode byte enables to determine register offset.
                    3'h0: begin   // STATUS0 Register
                        wbs_dat_o <= {2'b11, 3'b000, track0, 1'b0,wp };
                    end
                    3'h1: begin   // STATUS1 Register
                        wbs_dat_o <= {4'hF, hd_type, motor_on, ctrl_busy, fd_sel };
                    end
                    3'h2: begin   // DATA_PORT
                        wbs_dat_o <= sector_ram_dat_o;
                        sector_ram_ptr <= sector_ram_ptr + 9'h001;
                    end
                    3'h3: begin   // RESET
                        wbs_dat_o <= 8'h0F;
                        sector_ram_ptr <= 9'h0;
                        start_cmd <= 1'b0;
                    end
                    3'h4: begin   // DIAG0
                        wbs_dat_o <= sector_ram_ptr[7:0];
                    end
                    3'h5: begin   // DIAG1
                        wbs_dat_o <= disk_adr[7:0];
                    end
                    3'h6: begin   // DIAG2
                        wbs_dat_o <= { 6'h00, start_cmd, ds };
                    end
                    3'h7: begin   // DIAG3
                        wbs_dat_o <= { curr_track[ds][7:0] };
                    end
 
                endcase
            end
        end
 
    //
    // generate ack_o
    always @(posedge clk_i)
        wbs_ack_o <= wbs_acc & !wbs_ack_o;
 
// Instantiate the module
vhdfd_disk disks (
    .clk_i(clk_i), 
    .nrst_i(nrst_i), 
    .ds(ds), 
    .hds(hds), 
    .curr_track(curr_track[ds]), 
    .sector(sector), 
    .start_cmd(start_cmd), 
    .disk_read(disk_read), 
    .ctrl_busy(ctrl_busy),
    .disk_adr(disk_adr),
    .disk_dat_o(disk_dat_o),
    .disk_dat_i(disk_dat_i),
    .disk_ram_wr(disk_ram_wr),
    .flash_adr_o(flash_adr_o),
    .flash_dat_o(flash_dat_o),
    .flash_dat_i(flash_dat_i),
    .flash_oe(flash_oe),
    .flash_ce(flash_ce),
    .flash_we(flash_we));
 
// Instantiate the Sector RAM (512 bytes)
// synthesis attribute ram_style of sector_ram is block
vga_dpram #(
    .mem_file_name("../mon43/sector0.mem"),
    .adr_width(9),
    .dat_width(8)
) sector_ram (
    .clk1(clk_i),
    .clk2(clk_i),
    //
    .adr0(sector_ram_ptr),
    .dout0(sector_ram_dat_o),
    .din0(wbs_dat_i),  
    .we0(sector_ram_wr),
    //
    .adr1(disk_adr),
    .dout1(disk_dat_i),
    .din1(disk_dat_o),  
    .we1(disk_ram_wr)
);
 
endmodule
 
module vhdfd_disk (clk_i, nrst_i, ds, hds, curr_track, sector, start_cmd, disk_read, ctrl_busy,
                   disk_adr, disk_dat_o, disk_dat_i, disk_ram_wr,
                   flash_adr_o,flash_dat_o, flash_dat_i, flash_oe, flash_ce, flash_we
                   );
 
	input		      clk_i;
	input 	          nrst_i;
	input 	    [1:0] ds;
    input       [2:0] hds;
    input      [10:0] curr_track;
    input       [4:0] sector;
    input             start_cmd;
    input             disk_read;
    output reg        ctrl_busy;
 
    output reg  [8:0] disk_adr;
    output reg  [7:0] disk_dat_o;
    input       [7:0] disk_dat_i;
    output reg        disk_ram_wr;
 
    // FLASH Interface
    output     [23:0] flash_adr_o;
    output      [7:0] flash_dat_o;
    input       [7:0] flash_dat_i;
    output            flash_oe;
    output            flash_ce;
    output            flash_we;
    reg         [3:0] waitstate;
 
    reg         [13:0] state;
 
    wire        [23:0] sector_flash_adr;
 
assign sector_flash_adr = { 3'b000, hds[0], curr_track[6:0], sector[3:0], 9'h0 };
 
`define DISK_ST_IDLE            14'h000          // Disk Idle
`define DISK_ST_READ_SECTOR     14'h001          // Disk Read Sector
`define DISK_ST_WRITE_SECTOR    14'h002          // Disk Write Sector
`define DISK_ST_READ_WAIT       14'h004          // Disk Waitstate for FLASH read
`define DISK_ST_READ_WAIT2      14'h008          // Disk Waitstate for FLASH read
`define DISK_ST_READ_WAIT3      14'h010          // Disk Waitstate for FLASH read
`define DISK_ST_READ_WAIT4      14'h020          // Disk Waitstate for FLASH read
 
	always @(posedge clk_i or negedge nrst_i)
		if (~nrst_i)				// reset registers
			begin
                ctrl_busy <= 1'b0;
                disk_adr <= 9'h000;
                state <= `DISK_ST_IDLE;
			end
		else begin
            case(state)
                `DISK_ST_IDLE:
                    begin
                        if(start_cmd & disk_read) begin    // Wishbone access starts LPC transaction
                            state <= `DISK_ST_READ_SECTOR;
                            ctrl_busy <= 1'b1;
                        end
                        else if(start_cmd & !disk_read) begin
                            state <= `DISK_ST_WRITE_SECTOR;
                            ctrl_busy <= 1'b1;
                        end
                        else begin
                            state <= `DISK_ST_IDLE;
                            ctrl_busy <= 1'b0;
                            disk_adr <= 9'h000;
                        end
                    end
                `DISK_ST_READ_SECTOR:
                    begin
                        if(disk_adr != 9'h1FF) begin
                            disk_ram_wr <= 1'b1;
                            disk_adr <= disk_adr + 9'h001;
                            state <= `DISK_ST_READ_WAIT;
                        end
                        else begin
                            disk_ram_wr <= 1'b0;
                            state <= `DISK_ST_IDLE;
                        end
                    end
                `DISK_ST_READ_WAIT:
                    begin
                        state <= `DISK_ST_READ_WAIT2;
                    end
                `DISK_ST_READ_WAIT2:
                    begin
                        state <= `DISK_ST_READ_WAIT3;
                    end
                `DISK_ST_READ_WAIT3:
                    begin
                        state <= `DISK_ST_READ_WAIT4;
                    end
                `DISK_ST_READ_WAIT4:
                    begin
                        if(disk_adr > 9'h10E)
                            disk_dat_o <= 8'h00;
                        else
                            disk_dat_o <= flash_dat_i;
                        state <= `DISK_ST_READ_SECTOR;
                    end
                `DISK_ST_WRITE_SECTOR:
                    begin
                        if(disk_adr != 9'h1FF) begin
                            disk_ram_wr <= 1'b0;
                            disk_adr <= disk_adr + 9'h001;
                        end
                        else begin
                            state <= `DISK_ST_IDLE;
                        end
                    end
            endcase
        end
 
assign flash_adr_o = { sector_flash_adr[23:9], disk_adr[8:0] };
assign flash_oe = 1'b0;
assign flash_we = 1'b1;
assign flash_ce = 1'b0;
assign flash_dat_o = 8'hAA;
 
endmodule 
 

Go to most recent revision | 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.