mirror of
https://github.com/mist-devel/mist-board.git
synced 2026-02-11 02:09:48 +00:00
189 lines
5.0 KiB
Verilog
189 lines
5.0 KiB
Verilog
`timescale 1ns / 1ps
|
|
//////////////////////////////////////////////////////////////////////////////////
|
|
// Copyright 2013-2016 Istvan Hegedus
|
|
//
|
|
// FPGATED is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// FPGATED 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 General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
//
|
|
// Create Date: 16:36:31 12/10/2014
|
|
// Module Name: mos8501
|
|
// Project Name: FPGATED
|
|
// Target Devices: Xilinx Spartan 3E
|
|
//
|
|
// Description:
|
|
//
|
|
// Dependencies:
|
|
// This module contains an instance of Peter Wendrich's 6502 CPU core from FPGA64 project.
|
|
// The CPU core is used and included with Peter's permission and not developed by me.
|
|
// The mos8501 shell around the CPU core is written by me, but inspired by fpga64 6510 CPU
|
|
// shell. It might shows certain similarities.
|
|
//
|
|
// Revision history:
|
|
// 0.1 first release using incorrect 6502 core from fpga64 project
|
|
// 1.0 CPU core replaced to cpu65xx_fast.vhd from fpga64 project
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////////
|
|
module mos8501(
|
|
input clk,
|
|
input reset,
|
|
input enable,
|
|
input irq_n,
|
|
input [7:0] data_in,
|
|
output wire [7:0] data_out,
|
|
output [15:0] address,
|
|
input gate_in,
|
|
output rw,
|
|
input [7:0] port_in,
|
|
output [7:0] port_out,
|
|
input rdy,
|
|
input aec
|
|
);
|
|
|
|
wire we,enable_cpu;
|
|
wire [15:0] core_address;
|
|
wire [7:0] core_data_out;
|
|
wire port_access;
|
|
reg [7:0] data_out_reg,core_data_in,port_io;
|
|
reg [7:0] port_dir=8'b0;
|
|
reg [7:0] port_data=8'b0;
|
|
reg rw_reg,aec_reg;
|
|
|
|
// 6502 CPU core
|
|
|
|
wire we_n;
|
|
assign we = ~we_n;
|
|
|
|
T65 cpu_core(
|
|
|
|
.Mode (2'b00),
|
|
.Res_n (~reset),
|
|
.Enable(enable_cpu),
|
|
.Clk(clk),
|
|
.Rdy(enable_cpu),
|
|
.Abort_n(1),
|
|
.IRQ_n(irq_n),
|
|
.NMI_n(1),
|
|
.SO_n(1),
|
|
.R_w_n(we_n),
|
|
.A(core_address),
|
|
.DI(we_n ? core_data_in : core_data_out),
|
|
.DO(core_data_out)
|
|
);
|
|
|
|
assign address=(aec)?core_address:16'hffff; // address tri state emulated for easy bus signal combining
|
|
|
|
always @(posedge clk)
|
|
begin
|
|
if(gate_in)
|
|
begin
|
|
if(port_access==1'b1 && we==1'b1)
|
|
if(address[0]==1'b0) // when port direction register is written, data on bus is last read byte which is 0x00
|
|
data_out_reg<=8'h00;
|
|
else // when port register is written, data on bus is last read byte which is 0x01
|
|
data_out_reg<=8'h01;
|
|
else
|
|
data_out_reg<=core_data_out; // when mux is high, data out register is updated
|
|
end
|
|
else
|
|
begin
|
|
data_out_reg<=data_out_reg; // hold off data out during write cycle
|
|
end
|
|
end
|
|
|
|
always @(posedge clk)
|
|
begin
|
|
if(gate_in)
|
|
rw_reg<=~we;
|
|
end
|
|
|
|
always @(posedge clk) // registering aec for 1 clk cycle delay
|
|
begin
|
|
aec_reg<=aec;
|
|
end
|
|
|
|
assign rw=(~aec_reg)?1'b1:rw_reg;
|
|
|
|
assign data_out=(~aec_reg | gate_in | rw)?8'hff:data_out_reg; // when mux is low data out register is allowed to outside
|
|
assign port_access=(address[15:1]==0)?1'b1:1'b0;
|
|
|
|
// IO port part of cpu
|
|
|
|
always @(posedge clk) //writing port registers
|
|
begin
|
|
if(reset)
|
|
begin
|
|
port_dir<=0;
|
|
port_data<=0;
|
|
end
|
|
else if (enable)
|
|
if(port_access & we)
|
|
if(address[0]==0)
|
|
port_dir<=core_data_out;
|
|
else
|
|
port_data<=core_data_out;
|
|
end
|
|
|
|
always @* // reading port registers
|
|
begin
|
|
core_data_in=data_in;
|
|
if (port_access & ~we)
|
|
if(address[0]==0)
|
|
core_data_in=port_dir;
|
|
else
|
|
core_data_in=port_io;
|
|
end
|
|
|
|
// if direction bit is 0 then data is from chip's port
|
|
// if direction bit is 1 then data is from data port register filled earlier by CPU
|
|
|
|
always @*
|
|
begin
|
|
if(port_dir[0]==1'b0)
|
|
port_io[0]=port_in[0];
|
|
else
|
|
port_io[0]=port_data[0];
|
|
if(port_dir[1]==1'b0)
|
|
port_io[1]=port_in[1];
|
|
else
|
|
port_io[1]=port_data[1];
|
|
if(port_dir[2]==1'b0)
|
|
port_io[2]=port_in[2];
|
|
else
|
|
port_io[2]=port_data[2];
|
|
if(port_dir[3]==1'b0)
|
|
port_io[3]=port_in[3];
|
|
else
|
|
port_io[3]=port_data[3];
|
|
if(port_dir[4]==1'b0)
|
|
port_io[4]=port_in[4];
|
|
else
|
|
port_io[4]=port_data[4];
|
|
if(port_dir[5]==1'b0)
|
|
port_io[5]=port_in[5];
|
|
else
|
|
port_io[5]=port_data[5];
|
|
if(port_dir[6]==1'b0)
|
|
port_io[6]=port_in[6];
|
|
else
|
|
port_io[6]=port_data[6];
|
|
if(port_dir[7]==1'b0)
|
|
port_io[7]=port_in[7];
|
|
else
|
|
port_io[7]=port_data[7];
|
|
end
|
|
|
|
assign port_out=port_data;
|
|
assign enable_cpu=(~rdy & ~we)?1'b0:enable; // When RDY is low and cpu would do a read, halt cpu
|
|
|
|
endmodule
|