verilog-apple-one/basic.v

265 lines
7.9 KiB
Coq
Raw Normal View History

2018-01-01 13:33:20 +00:00
module top(
input clk12,
input uart_rx,
output uart_tx,
output uart_cts,
output tm_cs,
output tm_clk,
inout tm_dio,
output reg [7:0] led
);
//////////////////////////////////////////////////////////////////////////
// CLK DIVIDER
wire clk;
clk_div u_clk_div(
.clk (clk12),
.clk_out (clk)
);
//////////////////////////////////////////////////////////////////////////
// 6502 reset
reg [7:0] start;
always @(posedge clk)
if (~start[7]) start <= start + 1;
assign res = start[7];
//////////////////////////////////////////////////////////////////////////
// 6502 phi0 clock
reg [3:0] div;
always @(posedge clk)
div <= div + 1;
assign phi0 = div[3];
wire clk_phi;
SB_GB bg_phi (
.USER_SIGNAL_TO_GLOBAL_BUFFER(phi0),
.GLOBAL_BUFFER_OUTPUT(clk_phi)
);
//////////////////////////////////////////////////////////////////////////
// 6502
wire rw, res, irq, nmi, phi0;
wire [15:0] ab;
wire [7:0] dbo;
reg [7:0] dbi;
chip_6502 chip_6502 (
.clk (clk),
.phi (phi0),
.res (res),
.so (1'b0),
.rdy (1'b1),
.nmi (nmi),
.irq (irq),
.rw (rw),
.dbi (dbi),
.dbo (dbo),
.sync (),
.ab (ab)
);
//////////////////////////////////////////////////////////////////////////
// USB UART
wire received, is_receiving, rx_error, is_transmitting, transmit;
reg [7:0] tx_byte;
wire [7:0] rx_byte;
uart #(.CLOCK_DIVIDE( 625 )) my_uart (
clk12, // master clock for this component
~res, // synchronous reset line (resets if high)
uart_rx, // receive data on this line
uart_tx, // transmit data on this line
transmit, // signal to indicate that the UART should start a transmission
tx_byte, // 8-bit bus with byte to be transmitted when transmit is raised high
received, // output flag raised high for one cycle of clk when a byte is received
rx_byte, // byte which has just been received when received is raise
is_receiving, // indicates that we are currently receiving data on the rx lin
is_transmitting, // indicates that we are currently sending data on the tx line
rx_error // rx packet corrupt
);
// sync the TX latch to the clk12 domain
reg apple_tx;
Flag_CrossDomain tx_flag (
.clkA(clk_phi),
.FlagIn_clkA(apple_tx),
.clkB(clk12),
.FlagOut_clkB(transmit)
);
// sync the RX flag, using flag and ack
reg [6:0] apple_rx_buf;
reg apple_rx_ack;
reg apple_rx_flag;
always @(posedge clk12)
begin
if (received && !apple_rx_flag && !apple_rx_ack) begin
apple_rx_flag <= 1;
apple_rx_buf <= rx_byte[6:0];
end
if (apple_rx_flag && apple_rx_ack)
apple_rx_flag <= 0;
end
// implement basic hardware flow control so 6502 can catch up
assign uart_cts = is_receiving || apple_rx_flag;
//////////////////////////////////////////////////////////////////////////
// TM1638 Display
reg [3:0] display;
reg [7:0] digits[7:0];
reg [7:0] leds;
wire [7:0] keys;
ledAndKey my_led_and_keys (
.clk (clk12),
.rst (~res),
.display (display),
.digit1 (digits[0]),
.digit2 (digits[1]),
.digit3 (digits[2]),
.digit4 (digits[3]),
.digit5 (digits[4]),
.digit6 (digits[5]),
.digit7 (digits[6]),
.digit8 (digits[7]),
.leds (leds),
.keys (keys),
.tm_cs (tm_cs),
.tm_clk (tm_clk),
.tm_dio (tm_dio)
);
//////////////////////////////////////////////////////////////////////////
// I/O locations
localparam UART_RX = 16'hD010; // PIA.A register on Apple 1 - RX byte
localparam UART_RXCR = 16'hD011; // PIA.A register on Apple 1 - RX control
localparam UART_TX = 16'hD012; // PIA.B register on Apple 1 - TX byte
localparam LED_KEYS = 16'hD020; // Start address of the Led&Keys module
localparam LED = 16'hD000; // Breakout board LEDs
/*
0x77 - A
0X73 - P
0X73 - P
0X38 - L
0X79 - E
0X40 - -
0X06 - 1
*/
//////////////////////////////////////////////////////////////////////////
// RAM and ROM
reg [7:0] ram[0:8191];
initial begin
$readmemh("../ram.hex", ram, 0, 8191);
$readmemh("../rom.hex", ram, 8192-256, 8191);
end
always @(posedge clk_phi)
begin
// clear the UART RX ack if set
if (apple_rx_ack)
apple_rx_ack <= 0;
// clear the UART TX latch if set
if (apple_tx)
apple_tx <= 0;
if (res)
begin
case(ab)
// UART TX control and TX register
UART_TX:
begin
if (rw)
dbi <= {is_transmitting, 7'd0};
else
begin
// Apple 1 terminal only uses 7 bits, MSB indicates
// terminal has ack'd RX
tx_byte <= {1'b0, dbo[6:0]};
apple_tx <= 1;
end
end
// UART RX control register
UART_RXCR:
begin
if (rw)
dbi <= {apple_rx_flag, 7'b0};
end
// UART RX register
UART_RX:
begin
if (rw)
begin
// Apple 1 terminal only uses 7 bits, MSB tied high
// Wozmon checks for MSB being high
dbi <= apple_rx_flag ? {1'b1, apple_rx_buf} : 8'b0;
apple_rx_ack <= 1;
end
end
// LED&KEYS registers
LED_KEYS: if (rw) dbi <= {4'b0, display}; else display <= dbo[3:0];
LED_KEYS + 1: if (rw) dbi <= digits[0]; else digits[0] <= dbo;
LED_KEYS + 2: if (rw) dbi <= digits[1]; else digits[1] <= dbo;
LED_KEYS + 3: if (rw) dbi <= digits[2]; else digits[2] <= dbo;
LED_KEYS + 4: if (rw) dbi <= digits[3]; else digits[3] <= dbo;
LED_KEYS + 5: if (rw) dbi <= digits[4]; else digits[4] <= dbo;
LED_KEYS + 6: if (rw) dbi <= digits[5]; else digits[5] <= dbo;
LED_KEYS + 7: if (rw) dbi <= digits[6]; else digits[6] <= dbo;
LED_KEYS + 8: if (rw) dbi <= digits[7]; else digits[7] <= dbo;
LED_KEYS + 9: if (rw) dbi <= leds; else leds <= dbo;
LED_KEYS + 10: if (rw) dbi <= keys;
// breakout board LED registers
LED: if (rw) dbi <= led; else led <= dbo;
default:
begin
// RAM 0x0000 -> 0x1FFF, ROM 0xFF00 -> 0xFFFF
//
// !!!! ROM also at 0x1F00 -> 0x1FFF but writeable!!!!
//
// All other addresses return zero.
//
if (ab[15:13] == 3'b0 || ab[15:8] == 8'b11111111)
begin
// handle RAM/ROM address
dbi <= ram[ab[12:0]];
if (~rw && ~ab[15]) ram[ab[12:0]] <= dbo;
end
else
// unknown address return zero
dbi <= 8'b0;
end
endcase
end
end
// set irq and nmi high. for later use
assign irq = 1;
assign nmi = 1;
endmodule