mirror of
https://github.com/sehugg/mango_one.git
synced 2024-06-16 22:29:30 +00:00
155 lines
4.2 KiB
Coq
155 lines
4.2 KiB
Coq
|
|
||
|
`include "hvsync_generator.v"
|
||
|
`include "cpu6502.v"
|
||
|
`include "font_cp437_8x8.v"
|
||
|
|
||
|
// https://www.applefritter.com/replica/chapter7
|
||
|
// https://github.com/mamedev/mame/blob/master/src/mame/drivers/apple1.cpp
|
||
|
// https://github.com/jefftranter/6502/blob/master/asm/wozmon/wozmon.s
|
||
|
// https://www.applefritter.com/files/signetics2513.pdf
|
||
|
// http://retro.hansotten.nl/uploads/6502docs/signetics2504.pdf
|
||
|
// http://retro.hansotten.nl/uploads/6502docs/signetics2519.pdf
|
||
|
|
||
|
module signetics_term(clk, reset, hpos, vpos, tready, dot, te, ti);
|
||
|
|
||
|
input clk,reset;
|
||
|
input [8:0] hpos;
|
||
|
input [8:0] vpos;
|
||
|
input te; // input enable
|
||
|
input [7:0] ti; // input data
|
||
|
output tready; // terminal ready
|
||
|
output dot; // terminal video output
|
||
|
|
||
|
reg [7:0] dshift[1024]; // frame buffer offset
|
||
|
reg [9:0] dofs; // current offset to write
|
||
|
reg [9:0] scroll; // scroll offset
|
||
|
reg [9:0] scnt; // row clear counter when scrolling
|
||
|
|
||
|
always @(posedge clk or posedge reset)
|
||
|
if (reset) begin
|
||
|
scnt <= 0;
|
||
|
scroll <= 0;
|
||
|
dofs <= 28*32;
|
||
|
scroll <= 0;
|
||
|
end else if (scnt > 0) begin
|
||
|
dshift[scroll] <= 0; // clear row when scrolling
|
||
|
scroll <= scroll + 1;
|
||
|
scnt <= scnt - 1;
|
||
|
end else if (te) begin
|
||
|
if (ti == 13) begin // CR, next row
|
||
|
scnt <= 32;
|
||
|
dofs <= ((dofs + 32) & ~31);
|
||
|
end else if (ti >= 32) begin // display char
|
||
|
dshift[dofs] <= ti;
|
||
|
if ((dofs & 31) == 31) scnt <= 32; // wrap around
|
||
|
dofs <= dofs + 1;
|
||
|
end
|
||
|
end
|
||
|
|
||
|
// character generator from ROM
|
||
|
font_cp437_8x8 tile_rom(
|
||
|
.addr(char_addr),
|
||
|
.data(char_data)
|
||
|
);
|
||
|
wire [9:0] nt_addr = {vpos[7:3], hpos[7:3]};
|
||
|
wire [7:0] cur_char = dshift[nt_addr + scroll];
|
||
|
wire [10:0] char_addr = {cur_char, vpos[2:0]};
|
||
|
wire [7:0] char_data;
|
||
|
wire dot = char_data[~hpos[2:0]]; // video output
|
||
|
|
||
|
// terminal ready output
|
||
|
// only possible at end of line, if not scrolling
|
||
|
assign tready = !reset && !te && scnt == 0 && hpos == 256;
|
||
|
|
||
|
initial begin
|
||
|
integer i;
|
||
|
for (i=0; i<1024; i=i+1) dshift[i] = 0; // clear buffer
|
||
|
end
|
||
|
|
||
|
endmodule
|
||
|
|
||
|
module apple1_top(clk, reset, hsync, vsync, rgb, keycode, keystrobe);
|
||
|
|
||
|
input clk, reset;
|
||
|
input [7:0] keycode;
|
||
|
output reg keystrobe;
|
||
|
output hsync, vsync;
|
||
|
output [2:0] rgb;
|
||
|
wire display_on;
|
||
|
wire [8:0] hpos;
|
||
|
wire [8:0] vpos;
|
||
|
|
||
|
wire [15:0] AB; // address bus
|
||
|
wire [7:0] DI; // data in, read bus
|
||
|
wire [7:0] DO; // data out, write bus
|
||
|
wire WE; // write enable
|
||
|
wire IRQ=0; // interrupt request
|
||
|
wire NMI=0; // non-maskable interrupt request
|
||
|
wire RDY=1; // Ready signal. Pauses CPU when RDY=0
|
||
|
|
||
|
cpu6502 cpu( clk, reset, AB, DI, DO, WE, IRQ, NMI, RDY );
|
||
|
|
||
|
always @(posedge clk)
|
||
|
begin
|
||
|
casez (AB)
|
||
|
16'h0zzz: DI <= ram[AB[11:0]];
|
||
|
16'hd010: begin
|
||
|
if (keycode >= 97+128 && keycode <= 122+128)
|
||
|
DI <= keycode - 32; // convert to uppercase
|
||
|
else
|
||
|
DI <= keycode; // keyboard data
|
||
|
keystrobe <= (keycode & 8'h80) != 0; // clear kbd buffer
|
||
|
end
|
||
|
16'hd011: begin
|
||
|
DI <= keycode & 8'h80; // keyboard status
|
||
|
keystrobe <= 0;
|
||
|
end
|
||
|
16'hd012: begin
|
||
|
DI <= {!tready, 7'b0}; // display status
|
||
|
end
|
||
|
16'hffzz: DI <= monitor_rom[AB[7:0]];
|
||
|
endcase
|
||
|
end
|
||
|
|
||
|
always @(posedge clk)
|
||
|
if (WE) begin
|
||
|
casez (AB)
|
||
|
16'hd010: begin end //
|
||
|
16'hd011: begin end //
|
||
|
16'hd012: begin end // handled by terminal module
|
||
|
16'hd013: begin end //
|
||
|
16'h0zzz: ram[AB[11:0]] <= DO; // write RAM
|
||
|
endcase
|
||
|
end
|
||
|
|
||
|
reg [7:0] ram[4096]; // 1K of RAM
|
||
|
reg [7:0] monitor_rom[256]; // WozMon ROM
|
||
|
|
||
|
initial begin
|
||
|
$readmemh("mango1.hex", monitor_rom);
|
||
|
end
|
||
|
|
||
|
hvsync_generator hvsync_gen(
|
||
|
.clk(clk),
|
||
|
.reset(reset),
|
||
|
.hsync(hsync),
|
||
|
.vsync(vsync),
|
||
|
.display_on(display_on),
|
||
|
.hpos(hpos),
|
||
|
.vpos(vpos)
|
||
|
);
|
||
|
|
||
|
wire tready; // terminal ready
|
||
|
wire dot; // dot output
|
||
|
wire te = WE && AB == 16'hd012; // terminal enable (write)
|
||
|
signetics_term terminal(clk, reset, hpos, vpos,
|
||
|
tready, dot,
|
||
|
te, .ti(DO & 8'h7f));
|
||
|
|
||
|
wire r = display_on && 0;
|
||
|
wire g = display_on && dot;
|
||
|
wire b = display_on && 0;
|
||
|
assign rgb = {b,g,r};
|
||
|
|
||
|
endmodule
|