Made core neater and trying to get naming better

This commit is contained in:
Alan Garfield 2018-01-29 21:00:38 +11:00
parent 2717184e71
commit 474cabbab0
9 changed files with 221 additions and 120 deletions

View File

@ -39,6 +39,8 @@ report: dir apple1.rpt
$(BUILDDIR)/apple1.bin: $(BUILDDIR)/apple1.asc
$(BUILDDIR)/apple1.asc: $(BUILDDIR)/apple1.blif
$(BUILDDIR)/apple1.blif: $(SOURCEDIR)/apple1.v \
$(SOURCEDIR)/clock.v \
$(SOURCEDIR)/pwr_reset.v \
$(SOURCEDIR)/ram.v \
$(SOURCEDIR)/rom_wozmon.v \
$(SOURCEDIR)/rom_basic.v \

View File

@ -1,16 +1,42 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Description: Apple1 hardware core
//
// Author.....: Alan Garfield
// Niels A. Moseley
// Date.......: 26-1-2018
//
module apple1(
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,
// I/O interface to computer
input uart_rx, // asynchronous serial data input from computer
output uart_tx, // asynchronous serial data output to computer
output uart_cts, // clear to send flag to computer
// I/O interface to keyboard
input ps2_clk, // PS/2 keyboard serial clock input
input ps2_din, // PS/2 keyboard serial data input
output [15:0] pc_monitor, // spy for program counter / debugging
input reset_button // allow a physical reset button
// Debugging ports
output [15:0] pc_monitor // spy for program counter / debugging
);
//////////////////////////////////////////////////////////////////////////
// Registers and Wires
@ -23,77 +49,31 @@ module apple1(
//////////////////////////////////////////////////////////////////////////
// Clocks
// 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
//
//`define SLOWCPU
`ifdef SLOWCPU
reg [25:0] clk_div;
reg cpu_clken;
always @(posedge clk25)
begin
// note: clk_div should be compared to
// N-1, where N is the clock divisor
if ((clk_div == 24999999) || (rst_n == 1'b0))
clk_div <= 0;
else
clk_div <= clk_div + 1'b1;
cpu_clken <= (clk_div[25:0] == 0);
end
`else
reg [4:0] clk_div;
reg cpu_clken;
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
`endif
wire cpu_clken;
clock my_clock(
.clk25(clk25),
.rst_n(rst_n),
.cpu_clken(cpu_clken)
);
//////////////////////////////////////////////////////////////////////////
// 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;
end
else if (cpu_clken)
begin
if (!pwr_up_reset)
reset_cnt <= reset_cnt + 6'b1;
hard_reset <= pwr_up_reset;
end
end
assign reset = ~(hard_reset && reset_button);
wire rst;
pwr_reset my_reset(
.clk25(clk25),
.rst_n(rst_n),
.enable(cpu_clken),
.rst(rst)
);
//////////////////////////////////////////////////////////////////////////
// 6502
arlet_6502 my_cpu(
.clk (clk25),
.enable (cpu_clken),
.reset (reset),
.rst (rst),
.ab (ab),
.dbi (dbi),
.dbo (dbo),
@ -105,7 +85,7 @@ module apple1(
);
//////////////////////////////////////////////////////////////////////////
// RAM and ROM
// Address Decoding
wire ram_cs = (ab[15:13] == 3'b000); // 0x0000 -> 0x1FFF
wire uart_cs = (ab[15:2] == 14'b11010000000100); // 0xD010 -> 0xD013
@ -115,6 +95,9 @@ module apple1(
wire basic_cs = (ab[15:12] == 4'b1110); // 0xE000 -> 0xEFFF
wire rom_cs = (ab[15:8] == 8'b11111111); // 0xFF00 -> 0xFFFF
//////////////////////////////////////////////////////////////////////////
// RAM and ROM
// RAM
wire [7:0] ram_dout;
ram my_ram(
@ -141,6 +124,9 @@ module apple1(
.dout(basic_dout)
);
//////////////////////////////////////////////////////////////////////////
// Peripherals
// UART
wire [7:0] uart_dout;
uart #(
@ -151,7 +137,7 @@ module apple1(
`endif
) my_uart(
.clk(clk25),
.reset(reset),
.rst(rst),
.uart_rx(uart_rx),
.uart_tx(uart_tx),
@ -169,7 +155,7 @@ module apple1(
wire [7:0] ps2_dout;
ps2keyboard keyboard(
.clk25(clk25),
.reset(reset),
.rst(rst),
.key_clk(ps2_clk),
.key_din(ps2_din),
.cs(ps2kb_cs),
@ -177,6 +163,9 @@ module apple1(
.dout(ps2_dout)
);
//////////////////////////////////////////////////////////////////////////
// CPU Data In MUX
// link up chip selected device to cpu input
assign dbi = ram_cs ? ram_dout :
rom_cs ? rom_dout :

View File

@ -13,7 +13,6 @@ module apple1_top(
// 12MHz up to 25MHz
clock_pll clock_pll_inst(
.REFERENCECLK(clk),
.PLLOUTCORE(),
.PLLOUTGLOBAL(clk25),
.RESET(1'b1)
);
@ -22,15 +21,16 @@ module apple1_top(
assign led[7:0] = pc_monitor[7:0];
assign led[15:8] = ~pc_monitor[15:8];
// TODO: debounce buttons
// apple one main system
apple1 my_apple1(
.clk25(clk25),
.rst_n(1'b1),
.rst_n(button[0]),
.uart_rx(uart_rx),
.uart_tx(uart_tx),
.uart_cts(uart_cts),
.pc_monitor(pc_monitor),
.reset_button(button[0])
.pc_monitor(pc_monitor)
);
endmodule

72
rtl/clock.v Normal file
View File

@ -0,0 +1,72 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Description: Clock divider to provide clock enables for
// devices.
//
// Author.....: Alan Garfield
// Niels A. Moseley
// Date.......: 29-1-2018
//
module clock(
input clk25, // 25MHz clock
input rst_n, // active low synchronous reset
// Clock enables
output reg cpu_clken // 1MHz clock enable for the CPU and devices
);
// 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
//
//`define SLOWCPU
`ifdef SLOWCPU
reg [25: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 == 24999999) || (rst_n == 1'b0))
clk_div <= 0;
else
clk_div <= clk_div + 1'b1;
cpu_clken <= (clk_div[25:0] == 0);
end
`else
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
`endif
endmodule

View File

@ -1,7 +1,7 @@
module arlet_6502(
input clk, // clock signal
input enable, // clock enable strobe
input reset, // active high reset signal
input rst, // active high reset signal
output reg [15:0] ab, // address bus
input [7:0] dbi, // 8-bit data bus (input)
output reg [7:0] dbo, // 8-bit data bus (output)
@ -18,7 +18,7 @@ module arlet_6502(
cpu arlet_cpu (
.clk(clk),
.reset(reset),
.reset(rst),
.AB(ab_c),
.DI(dbi),
.DO(dbo_c),
@ -29,9 +29,9 @@ module arlet_6502(
.PC_MONITOR(pc_monitor)
);
always @(posedge clk or posedge reset)
always @(posedge clk or posedge rst)
begin
if (reset)
if (rst)
begin
ab <= 16'd0;
dbo <= 8'd0;

View File

@ -19,20 +19,20 @@
//
// Author.....: Niels A. Moseley
// Date.......: 28-1-2018
//
//
module ps2keyboard (
input clk25, // 25MHz clock
input reset, // active high reset
input clk25, // 25MHz clock
input rst, // active high reset
// I/O interface to keyboard
input key_clk, // clock input from keyboard / device
input key_din, // data input from keyboard / device
input key_clk, // clock input from keyboard / device
input key_din, // data input from keyboard / device
// I/O interface to computer
input cs, // chip select, active high
input address, // =0 RX buffer, =1 RX status
output reg [7:0] dout // 8-bit output bus.
input cs, // chip select, active high
input address, // =0 RX buffer, =1 RX status
output reg [7:0] dout // 8-bit output bus.
);
// signals in the slow PS/2 clock domain
@ -52,16 +52,16 @@ module ps2keyboard (
reg shift; // state of the shift key
reg [2:0] cur_state;
reg [2:0] next_state;
//
// PS/2 data from a device changes when the clock
// is low, so we latch when the clock transitions
// to a high state
//
always @(posedge key_clk or posedge reset)
always @(posedge key_clk or posedge rst)
begin
if (reset == 1'b1)
if (rst == 1'b1)
begin
// reset the serial buffer
rxshiftbuf <= 11'b0;
@ -112,9 +112,9 @@ localparam S_KEYF0 = 3'b001; // regular key release state
localparam S_KEYE0 = 3'b010; // extended key state
localparam S_KEYE0F0 = 3'b011; // extended release state
always @(posedge clk25 or posedge reset)
always @(posedge clk25 or posedge rst)
begin
if (reset)
if (rst)
begin
rxflag_ff <= 0;
rx <= 0;
@ -135,7 +135,7 @@ begin
rx <= rxshiftbuf[8:1];
rx_rdy <= 1;
end
// handle I/O from CPU
if (cs == 1'b1)
begin
@ -208,7 +208,7 @@ begin
8'h4E: ascii <= "-";
8'h55: ascii <= "=";
8'h5D: ascii <= "\\ ";
8'h5D: ascii <= "\\";
8'h66: ascii <= 8'd8; // backspace
8'h29: ascii <= " ";
@ -219,9 +219,10 @@ begin
8'h52: ascii <= "'";
8'h41: ascii <= ",";
8'h49: ascii <= ".";
8'h4A: ascii <= "/";
8'h4A: ascii <= "/";
8'h59: shift <= 1'b1; // right shfit
8'h12: shift <= 1'b1; // left shift
default: ascii <= ".";
endcase
else
case(rx)
@ -279,6 +280,8 @@ begin
8'h4A: ascii <= "?";
8'h59: shift <= 1'b1; // right shfit
8'h12: shift <= 1'b1; // left shift
default: ascii <= ".";
endcase
end
end
@ -301,6 +304,10 @@ begin
begin
next_state = S_KEYNORMAL;
end
default:
begin
next_state = S_KEYNORMAL;
end
endcase;
end
else

31
rtl/pwr_reset.v Normal file
View File

@ -0,0 +1,31 @@
module pwr_reset(
input clk25,
input rst_n,
input enable,
output rst
);
wire rst;
reg hard_reset;
reg [5:0] reset_cnt;
wire pwr_up_flag = &reset_cnt;
always @(posedge clk25)
begin
if (rst_n == 1'b0)
begin
reset_cnt <= 6'b0;
hard_reset <= 1'b0;
end
else if (enable)
begin
if (!pwr_up_flag)
reset_cnt <= reset_cnt + 6'b1;
hard_reset <= pwr_up_flag;
end
end
assign rst = ~hard_reset;
endmodule

View File

@ -9,7 +9,7 @@
////////////////////////////////////////////////////////
module async_transmitter(
input clk,
input reset,
input rst,
input TxD_start,
input [7:0] TxD_data,
output TxD,
@ -24,7 +24,7 @@ module async_transmitter(
////////////////////////////////
wire BitTick;
BaudTickGen #(ClkFrequency, Baud) tickgen(.clk(clk), .reset(reset), .enable(TxD_busy), .tick(BitTick));
BaudTickGen #(ClkFrequency, Baud) tickgen(.clk(clk), .rst(rst), .enable(TxD_busy), .tick(BitTick));
reg [3:0] TxD_state;
reg [7:0] TxD_shift;
@ -32,9 +32,9 @@ module async_transmitter(
wire TxD_ready = (TxD_state==0);
assign TxD_busy = ~TxD_ready;
always @(posedge clk or posedge reset)
always @(posedge clk or posedge rst)
begin
if (reset)
if (rst)
begin
TxD_state <= 0;
TxD_shift <= 0;
@ -72,7 +72,7 @@ endmodule
////////////////////////////////////////////////////////
module async_receiver(
input clk,
input reset,
input rst,
input RxD,
output reg RxD_data_ready,
output reg [7:0] RxD_data, // data received, valid only (for one clock cycle) when RxD_data_ready is asserted
@ -95,13 +95,13 @@ module async_receiver(
reg [3:0] RxD_state;
wire OversamplingTick;
BaudTickGen #(ClkFrequency, Baud, Oversampling) tickgen(.clk(clk), .reset(reset), .enable(1'b1), .tick(OversamplingTick));
BaudTickGen #(ClkFrequency, Baud, Oversampling) tickgen(.clk(clk), .rst(rst), .enable(1'b1), .tick(OversamplingTick));
// synchronize RxD to our clk domain
reg [1:0] RxD_sync; // 2'b11
always @(posedge clk or posedge reset)
always @(posedge clk or posedge rst)
begin
if (reset)
if (rst)
RxD_sync <= 2'b11;
else
if(OversamplingTick) RxD_sync <= {RxD_sync[0], RxD};
@ -110,9 +110,9 @@ module async_receiver(
// and filter it
reg [1:0] Filter_cnt; // 2'b11
reg RxD_bit; // 1'b1
always @(posedge clk or posedge reset)
always @(posedge clk or posedge rst)
begin
if (reset)
if (rst)
begin
Filter_cnt <= 2'b11;
RxD_bit <= 1'b1;
@ -146,9 +146,9 @@ module async_receiver(
wire sampleNow = OversamplingTick && (OversamplingCnt==Oversampling/2-1);
// now we can accumulate the RxD bits in a shift-register
always @(posedge clk or posedge reset)
always @(posedge clk or posedge rst)
begin
if (reset)
if (rst)
RxD_state <= 0;
else
case(RxD_state)
@ -167,26 +167,26 @@ module async_receiver(
endcase
end
always @(posedge clk or posedge reset)
always @(posedge clk or posedge rst)
begin
if (reset)
if (rst)
RxD_data <= 0;
else
if (sampleNow && RxD_state[3]) RxD_data <= {RxD_bit, RxD_data[7:1]};
end
always @(posedge clk or posedge reset)
always @(posedge clk or posedge rst)
begin
if (reset)
if (rst)
RxD_data_ready <= 0;
else
RxD_data_ready <= (sampleNow && RxD_state==4'b0010 && RxD_bit); // make sure a stop bit is received
end
reg [l2o+1:0] GapCnt;
always @(posedge clk or posedge reset)
always @(posedge clk or posedge rst)
begin
if (reset)
if (rst)
GapCnt <= 0;
else
if (RxD_state!=0) GapCnt<=0; else if(OversamplingTick & ~GapCnt[log2(Oversampling)+1]) GapCnt <= GapCnt + 1'h1;
@ -200,7 +200,7 @@ endmodule
////////////////////////////////////////////////////////
module BaudTickGen(
input clk, reset, enable,
input clk, rst, enable,
output tick // generate a tick at the specified baud rate * oversampling
);
@ -217,7 +217,7 @@ module BaudTickGen(
always @(posedge clk)
begin
if (reset)
if (rst)
Acc <= 0;
else
if(enable) Acc <= Acc[AccWidth-1:0] + Inc[AccWidth:0]; else Acc <= Inc[AccWidth:0];

View File

@ -6,7 +6,7 @@
module uart(
input clk,
input reset,
input rst,
input enable,
input [1:0] address,
@ -29,7 +29,7 @@ module uart(
async_transmitter #(ClkFrequency, Baud) my_tx (
.clk(clk),
.reset(reset),
.rst(rst),
.TxD_start(uart_tx_stb),
.TxD_data(uart_tx_byte),
.TxD(uart_tx),
@ -43,7 +43,7 @@ module uart(
async_receiver #(ClkFrequency, Baud, Oversampling) my_rx(
.clk(clk),
.reset(reset),
.rst(rst),
.RxD(uart_rx),
.RxD_data_ready(uart_rx_stb),
.RxD_data(rx_data),
@ -51,9 +51,9 @@ module uart(
.RxD_endofpacket(rx_end)
);
always @(posedge clk or posedge reset)
always @(posedge clk or posedge rst)
begin
if (reset)
if (rst)
begin
uart_rx_status <= 'b0;
uart_rx_byte <= 8'd0;
@ -81,9 +81,9 @@ module uart(
localparam UART_TX = 2'b10;
// Handle Register
always @(posedge clk or posedge reset)
always @(posedge clk or posedge rst)
begin
if (reset)
if (rst)
begin
dout <= 8'd0;