1
0
mirror of https://github.com/Gehstock/Mist_FPGA.git synced 2026-01-30 05:23:54 +00:00
Files
Gehstock.Mist_FPGA/Computer_MiST/Acorn - System1/rtl/System1.v
2019-08-18 22:38:49 +02:00

328 lines
8.5 KiB
Verilog

// =======================================================================
//
//
// An Acorn System1 implementation for the Mister
//
// Copyright (C) 2019 Dave Wood
//
// This program 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.
//
// This program 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/.
// =======================================================================
module System1(
input clk25,
input reset,
output reg[8:0]ch0,ch1,ch2,ch3,ch4,ch5,ch6,ch7,
input sw0,sw1,sw2,sw3,sw4,sw5,sw6,sw7,sw8,sw9,swa,swb,swc,swd,swe,swf,swrst,swm,swl,swg,swr,swp,swU,sws,swD,
// Cassette / Sound
input cas_in,
output cas_out
);
wire rom_cs;
wire [7:0] rom_dout;
acrnsys1 MONROM(
.clk(clk25 & rom_cs),
.addr(address[8:0]),
.data(rom_dout)
);
wire ram_cs;
wire ram_wr = (!rnw & ram_cs);
wire [7:0] ram_dout;
gen_ram #(
.dWidth(8),
.aWidth(10))
MRAM (
.clk(clk25 & ram_cs),
.we(ram_wr),
.addr(address[9:0]),
.d(cpu_dout),
.q(ram_dout)
);
// ===============================================================
// Wires/Reg definitions
// TODO: reorganize so all defined here
// ===============================================================
reg rnw;
reg [15:0] address;
reg [7:0] cpu_dout;
wire [7:0] via_dout;
wire via_irq_n;
wire [1:0] turbo = 2'b00;
reg lock;
reg [2:0] phase = 3'b000;
reg [2:0] scan = 3'b111;
wire [7:0] PA_out;
reg [7:0] PA_tmp = 8'b00000000;
// ===============================================================
// Clock Enable Generation
// ===============================================================
reg cpu_clken;
reg via1_clken;
reg via4_clken;
reg [4:0] clkdiv = 5'b00000; // divider, from 25MHz down to 1, 2, 4 or 8MHz
always @(posedge clk25) begin
if (clkdiv == 24)
clkdiv <= 0;
else
clkdiv <= clkdiv + 1;
case (turbo)
2'b00: // 1MHz
begin
cpu_clken <= (clkdiv[3:0] == 0) & (clkdiv[4] == 0);
via1_clken <= (clkdiv[3:0] == 0) & (clkdiv[4] == 0);
via4_clken <= (clkdiv[1:0] == 0) & (clkdiv[4] == 0);
end
2'b01: // 2MHz
begin
cpu_clken <= (clkdiv[2:0] == 0) & (clkdiv[4] == 0);
via1_clken <= (clkdiv[2:0] == 0) & (clkdiv[4] == 0);
via4_clken <= (clkdiv[0] == 0) & (clkdiv[4] == 0);
end
default: // 4MHz
begin
cpu_clken <= (clkdiv[1:0] == 0) & (clkdiv[4] == 0);
via1_clken <= (clkdiv[1:0] == 0) & (clkdiv[4] == 0);
via4_clken <= (clkdiv[4] == 0);
end
endcase
end
// ===============================================================
// Cassette
// ===============================================================
// The Atom drives cas_tone from 4MHz / 16 / 13 / 8
// 208 = 16 * 13, and start with 1MHz and toggle
// so it's basically the same
reg cas_tone = 1'b0;
reg [7:0] cas_div = 0;
always @(posedge clk25) begin
if (cpu_clken)
begin
if (cas_div == 207)
begin
cas_div <= 0;
cas_tone <= !cas_tone;
end
else
cas_div <= cas_div + 1;
end
end
// this is a direct translation of the logic in the atom
// (two NAND gates and an inverter)
// assign cas_out = !(!(!cas_tone & pia_pc[1]) & pia_pc[0]);
// assign PB_in[7] = cas_in;
// ===============================================================
// 6502 CPU
// ===============================================================
wire [7:0] cpu_din;
wire [7:0] cpu_dout_c;
wire [15:0] address_c;
wire rnw_c;
// Arlet's 6502 core is one of the smallest available
cpu CPU
(
.clk(clk25),
.reset(swrst | reset),
.AB(address_c),
.DI(cpu_din),
.DO(cpu_dout_c),
.WE(rnw_c),
.IRQ(1'b0), //(!via_irq_n),
.NMI(1'b0),
.RDY(cpu_clken)
);
// The outputs of Arlets's 6502 core need registing
always @(posedge clk25)
begin
if (cpu_clken)
begin
address <= address_c;
cpu_dout <= cpu_dout_c;
rnw <= !rnw_c;
end
end
// ===============================================================
// Address decoding logic and data in multiplexor
// ===============================================================
// 0000-3FFF RAM
// 0Exx-0Fxx 6522 VIA
// FExx-FFxx Monitor Prom
assign rom_cs = (address[15:9] == 7'b1111111); //FE00 - FFFF
wire via_cs = (address[15:9] == 7'b0000111); //0Exx
assign ram_cs = (address[15:10] == 6'b000000); //0000 - 003F
assign cpu_din = via_cs ? via_dout :
ram_cs ? ram_dout :
rom_cs ? rom_dout :
8'b11111111;
// ===============================================================
// 6522 VIA at 0x0Exx
// ===============================================================
wire [7:0] PB_out;
wire [7:0] PB_oe,PA_oe;
reg [7:0] PB_in;
wire pressed = (~sw0 & ~sw1 & ~sw2 & ~sw3 & ~sw4 & ~sw5 & ~sw6 & ~sw7 & ~sw8 & ~sw9 & ~swa & ~swb & ~swc & ~swd & ~swe & ~swf & ~swm & ~swl & ~swg & ~swr & ~swp & ~swU & ~sws & ~swD);
always @(posedge via1_clken) begin
if (pressed) PB_in <= 8'b00111111;
if (phase == 3'b000 && PB_out[2:0] == 3'b111) begin
ch0 <= PA_out;
phase = 3'b001;
if (sw7) PB_in <= 8'b00011111;
if (swD) PB_in <= 8'b00101111;
if (swf) PB_in <= 8'b00110111;
end
if (phase == 3'b001 && PB_out[2:0] == 3'b110) begin
ch1 <= PA_out;
phase = 3'b010;
if (sw6) PB_in <= 8'b00011111;
if (swU) PB_in <= 8'b00101111;
if (swe) PB_in <= 8'b00110111;
end
if (phase == 3'b010 && PB_out[2:0] == 3'b101) begin
ch2 <= PA_out;
phase = 3'b011;
if (sw5) PB_in <= 8'b00011111;
if (swr) PB_in <= 8'b00101111;
if (swd) PB_in <= 8'b00110111;
end
if (phase == 3'b011 && PB_out[2:0] == 3'b100) begin
ch3 <= PA_out;
phase = 3'b100;
if (sw4) PB_in <= 8'b00011111;
if (swl) PB_in <= 8'b00101111;
if (swc) PB_in <= 8'b00110111;
end
if (phase == 3'b100 && PB_out[2:0] == 3'b011) begin
ch4 <= PA_out;
phase = 3'b101;
if (sw3) PB_in <= 8'b00011111;
if (sws) PB_in <= 8'b00101111;
if (swb) PB_in <= 8'b00110111;
end
if (phase == 3'b101 && PB_out[2:0] == 3'b010) begin
ch5 <= PA_out;
phase = 3'b110;
if (sw2) PB_in <= 8'b00011111;
if (swp) PB_in <= 8'b00101111;
if (swa) PB_in <= 8'b00110111;
end
if (phase == 3'b110 && PB_out[2:0] == 3'b001) begin
ch6 <= PA_out;
phase = 3'b111;
if (sw1) PB_in <= 8'b00011111;
if (swg) PB_in <= 8'b00101111;
if (sw9) PB_in <= 8'b00110111;
end
if (phase == 3'b111 && PB_out[2:0] == 3'b000) begin
ch7 <= PA_out;
phase = 3'b000;
if (sw0) PB_in <= 8'b00011111;
if (swm) PB_in <= 8'b00101111;
if (sw8) PB_in <= 8'b00110111;
end
end
m6522 VIA
(
.I_RS(address[3:0]),
.I_DATA(cpu_dout),
.O_DATA(via_dout),
.O_DATA_OE_L(),
.I_RW_L(rnw),
.I_CS1(via_cs),
.I_CS2_L(1'b0),
.O_IRQ_L(via_irq_n),
.I_CA1(1'b0),
.I_CA2(1'b0),
.O_CA2(),
.O_CA2_OE_L(),
.I_PA(8'b0),
.O_PA(PA_out),
.O_PA_OE_L(PA_oe),
.I_CB1(1'b0),
.O_CB1(),
.O_CB1_OE_L(),
.I_CB2(1'b0),
.O_CB2(),
.O_CB2_OE_L(),
.I_PB(PB_in),
.O_PB(PB_out),
.O_PB_OE_L(PB_oe),
.I_P2_H(via1_clken),
.RESET_L(!reset),
.ENA_4(via4_clken),
.CLK(clk25)
);
/*
wire [7:0] digit_0 = 8'h3F;
wire [7:0] digit_1 = 8'h06;
wire [7:0] digit_2 = 8'h5B;
wire [7:0] digit_3 = 8'h4F;
wire [7:0] digit_4 = 8'h66;
wire [7:0] digit_5 = 8'h6D;
wire [7:0] digit_6 = 8'h7D;
wire [7:0] digit_7 = 8'h07;
wire [7:0] digit_8 = 8'h7F;
wire [7:0] digit_9 = 8'h6F;
wire [7:0] digit_A = 8'h77;
wire [7:0] digit_B = 8'h7C;
wire [7:0] digit_C = 8'h58;
wire [7:0] digit_D = 8'h5E;
wire [7:0] digit_E = 8'h79;
wire [7:0] digit_F = 8'h71;
*/
endmodule