mirror of
https://github.com/alangarf/apple-one.git
synced 2024-11-19 21:31:08 +00:00
231 lines
5.9 KiB
Verilog
231 lines
5.9 KiB
Verilog
//
|
|
// FIXME:
|
|
// there defines must be enabled in the project
|
|
// settings to avoid conflicts with different
|
|
// development platforms
|
|
//
|
|
//`define ICE40
|
|
//
|
|
|
|
module top(
|
|
input clk25, // 25 MHz master clock
|
|
input rst_n, // active low synchronous reset (needed for simulation)
|
|
|
|
input uart_rx,
|
|
output uart_tx,
|
|
output uart_cts,
|
|
|
|
output [7:0] led, // what do these do?
|
|
output [7:0] ledx // what do these do?
|
|
);
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Registers and Wires
|
|
|
|
reg [15:0] ab;
|
|
wire [7:0] dbi;
|
|
reg [7:0] dbo;
|
|
reg we;
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Clocks
|
|
reg cpu_clken;
|
|
|
|
// FIXME:
|
|
// the clocks here should come from higher up
|
|
// the hierarchy, i.e. generated at the board
|
|
// level.
|
|
//
|
|
// if cpu_clken is a simple block,
|
|
// keep it here but make it generic.
|
|
|
|
`ifdef ICE40
|
|
clocks my_clocks(
|
|
.clk(clk),
|
|
.clk25(clk25),
|
|
.cpu_clken(cpu_clken)
|
|
);
|
|
`endif
|
|
|
|
// generate clock enable once every
|
|
// 25 clocks. This will (hopefully) make
|
|
// the 6502 run at 1 MHz or 1Hz
|
|
//
|
|
// the clock division counter is synchronously
|
|
// reset using rst_n to avoid undefined signals
|
|
// in simulation
|
|
//
|
|
|
|
reg [4:0] clk_div;
|
|
always @(posedge clk25)
|
|
begin
|
|
// note: clk_div should be compared to
|
|
// N-1, where N is the clock divisor
|
|
if ((clk_div == 24) || (rst_n == 1'b0))
|
|
clk_div <= 0;
|
|
else
|
|
clk_div <= clk_div + 1'b1;
|
|
|
|
cpu_clken <= (clk_div[4:0] == 0);
|
|
end
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Reset
|
|
wire reset;
|
|
reg hard_reset;
|
|
reg [5:0] reset_cnt;
|
|
wire pwr_up_reset = &reset_cnt;
|
|
|
|
always @(posedge clk25)
|
|
begin
|
|
if (rst_n == 1'b0)
|
|
begin
|
|
reset_cnt <= 6'b0;
|
|
//hard_reset <= 1'b0; we should init hard_reset here too..
|
|
end
|
|
else if (cpu_clken)
|
|
begin
|
|
if (!pwr_up_reset)
|
|
reset_cnt <= reset_cnt + 1;
|
|
|
|
hard_reset <= pwr_up_reset;
|
|
end
|
|
end
|
|
|
|
assign reset = ~hard_reset;
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// 6502
|
|
wire [7:0] dbo_c;
|
|
wire [15:0] ab_c;
|
|
wire we_c;
|
|
reg [7:0] dbi_c;
|
|
|
|
cpu my_cpu (
|
|
.clk (clk25),
|
|
.reset (reset),
|
|
.AB (ab_c),
|
|
.DI (dbi_c),
|
|
.DO (dbo_c),
|
|
.WE (we_c),
|
|
.IRQ (1'b0),
|
|
.NMI (1'b0),
|
|
.RDY (cpu_clken)
|
|
);
|
|
|
|
always @(posedge clk25)
|
|
begin
|
|
if (cpu_clken)
|
|
begin
|
|
ab <= ab_c;
|
|
dbo <= dbo_c;
|
|
dbi_c <= dbi;
|
|
we <= we_c;
|
|
end
|
|
end
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// RAM and ROM
|
|
|
|
wire ram_cs = (ab[15:13] == 3'b000); // 0x0000 -> 0x1FFF
|
|
wire uart_cs = (ab[15:2] == 14'b11010000000100); // 0xD010 -> 0xD013
|
|
wire basic_cs = (ab[15:12] == 4'b1110); // 0xE000 -> 0xEFFF
|
|
wire rom_cs = (ab[15:8] == 8'b11111111); // 0xFF00 -> 0xFFFF
|
|
|
|
// RAM
|
|
wire [7:0] ram_dout;
|
|
ram my_ram (
|
|
.clk(clk25),
|
|
.address(ab[12:0]),
|
|
.w_en(we & ram_cs),
|
|
.din(dbo),
|
|
.dout(ram_dout)
|
|
);
|
|
|
|
// WozMon ROM
|
|
wire [7:0] rom_dout;
|
|
rom_wozmon my_rom_wozmon (
|
|
.clk(clk25),
|
|
.address(ab[7:0]),
|
|
.dout(rom_dout)
|
|
);
|
|
|
|
// UART
|
|
wire [7:0] uart_dout;
|
|
uart my_uart (
|
|
.clk(clk25),
|
|
|
|
.uart_rx(uart_rx),
|
|
.uart_tx(uart_tx),
|
|
.uart_cts(uart_cts),
|
|
|
|
.enable(uart_cs & cpu_clken),
|
|
.address(ab[1:0]),
|
|
.w_en(we & uart_cs),
|
|
.din(dbo),
|
|
.dout(uart_dout),
|
|
.led(led)
|
|
);
|
|
|
|
// link up chip selected device to cpu input
|
|
assign dbi = ram_cs ? ram_dout :
|
|
rom_cs ? rom_dout :
|
|
uart_cs ? uart_dout :
|
|
8'hFF;
|
|
|
|
assign ledx = ab[7:0];
|
|
|
|
// always @(posedge clk25)
|
|
// begin
|
|
// if (cpu_clken)
|
|
// begin
|
|
// led <= ab[7:0];
|
|
// ledx <= ~ab[15:8];
|
|
// end
|
|
// end
|
|
|
|
// reg [7:0] ram[0:8191] /* synthesis syn_ramstyle = "block_ram" */;
|
|
// reg [7:0] rom[0:255] /* synthesis syn_ramstyle = "block_ram" */;
|
|
// reg [7:0] basic[0:4095] /* synthesis syn_ramstyle = "block_ram" */;
|
|
//
|
|
// initial begin
|
|
// $readmemh("../roms/ram.hex", ram, 0, 8191);
|
|
// $readmemh("../roms/rom.hex", rom, 0, 255);
|
|
// $readmemh("../roms/basic.hex", basic, 0, 4095);
|
|
// end
|
|
//
|
|
// always @(posedge clk_25)
|
|
// begin
|
|
// if (phi_clk_en)
|
|
// begin
|
|
// if (res)
|
|
// begin
|
|
// case(ab)
|
|
// default:
|
|
// begin
|
|
// if (ab[15:12] == 4'b0000 || ab[15:12] == 4'b0001)
|
|
// begin
|
|
// // 0x0000 -> 0x1FFF - RAM
|
|
// dbi <= ram[ab[12:0]];
|
|
// if (~rw) ram[ab[12:0]] <= dbo;
|
|
// end
|
|
// else if (ab[15:12] == 4'b1110)
|
|
// begin
|
|
// // 0xE000 -> 0xEFFF - BASIC
|
|
// dbi <= basic[ab[11:0]];
|
|
// end
|
|
// else if (ab[15:8] == 8'b11111111)
|
|
// begin
|
|
// // 0xFF00 -> 0xFFFF - ROM
|
|
// dbi <= rom[ab[7:0]];
|
|
// end
|
|
// else
|
|
// // unknown address return zero
|
|
// dbi <= 8'h0;
|
|
// end
|
|
//
|
|
// endcase
|
|
// end
|
|
// end
|
|
// end
|
|
endmodule
|