Merge pull request #47 from alangarf/tang_primer_25k

Added tang primer 25k with ukp usb keyboard
This commit is contained in:
Alan Garfield authored and GitHub committed 2025-09-22 15:29:10 +10:00
commit 0f15ef6d62
28 files changed
+2950 -892

No files matched your search

+3
View File
@@ -8,3 +8,6 @@ synlog.tcl
*_tb
*.vcd
build
gwsynthesis
pnr
temp
+34
View File
@@ -0,0 +1,34 @@
<?xml version="1" encoding="UTF-8"?>
<!DOCTYPE gowin-fpga-project>
<Project>
<Template>FPGA</Template>
<Version>5</Version>
<Device name="GW5A-25A" pn="GW5A-LV25MG121NES">gw5a25a-000</Device>
<FileList>
<File path="../../rtl/apple1.v" type="file.verilog" enable="1"/>
<File path="../../rtl/clock.v" type="file.verilog" enable="1"/>
<File path="../../rtl/cpu/arlet/ALU.v" type="file.verilog" enable="1"/>
<File path="../../rtl/cpu/arlet/cpu.v" type="file.verilog" enable="1"/>
<File path="../../rtl/cpu/arlet_6502.v" type="file.verilog" enable="1"/>
<File path="../../rtl/ps2keyboard/debounce.v" type="file.verilog" enable="1"/>
<File path="../../rtl/ps2keyboard/ps2keyboard.v" type="file.verilog" enable="1"/>
<File path="../../rtl/pwr_reset.v" type="file.verilog" enable="1"/>
<File path="../../rtl/ram.v" type="file.verilog" enable="1"/>
<File path="../../rtl/rom_basic.v" type="file.verilog" enable="1"/>
<File path="../../rtl/rom_wozmon.v" type="file.verilog" enable="1"/>
<File path="../../rtl/uart/async_tx_rx.v" type="file.verilog" enable="1"/>
<File path="../../rtl/uart/uart.v" type="file.verilog" enable="1"/>
<File path="../../rtl/usbkeyboard/usb_hid_host.v" type="file.verilog" enable="1"/>
<File path="../../rtl/usbkeyboard/usb_keyboard.v" type="file.verilog" enable="1"/>
<File path="../../rtl/usbkeyboard/usb_hid_host_rom.v" type="file.verilog" enable="1"/>
<File path="../../rtl/vga/font_rom.v" type="file.verilog" enable="1"/>
<File path="../../rtl/vga/vga.v" type="file.verilog" enable="1"/>
<File path="../../rtl/vga/vram.v" type="file.verilog" enable="1"/>
<File path="../../rtl/boards/tang_primer_25k/apple1_primer.v" type="file.verilog" enable="1"/>
<File path="../../rtl/boards/tang_primer_25k/pll/gowin_pll.v" type="file.verilog" enable="1"/>
<File path="../../rtl/boards/tang_primer_25k/pll/pll_init.v" type="file.verilog" enable="1"/>
<File path="../../rtl/boards/tang_primer_25k/pll/gowin_pll_mod.v" type="file.verilog" enable="1"/>
<File path="../../rtl/boards/tang_primer_25k/apple1.cst" type="file.cst" enable="1"/>
<File path="../../rtl/boards/tang_primer_25k/apple1.sdc" type="file.sdc" enable="1"/>
</FileList>
</Project>
@@ -0,0 +1,27 @@
<?xml version="1" encoding="UTF-8"?>
<!DOCTYPE ProjectUserData>
<UserConfig>
<Version>1.0</Version>
<FlowState>
<Process ID="Synthesis" State="2"/>
<Process ID="Pnr" State="2"/>
<Process ID="Gao" State="2"/>
<Process ID="Rtl_Gao" State="2"/>
<Process ID="Gvio" State="0"/>
<Process ID="Place" State="2"/>
</FlowState>
<ResultFileList>
<ResultFile ResultFileType="RES.netlist" ResultFilePath="impl/gwsynthesis/apple-one.vg"/>
<ResultFile ResultFileType="RES.pnr.bitstream" ResultFilePath="impl/pnr/apple-one.fs"/>
<ResultFile ResultFileType="RES.pnr.pin.rpt" ResultFilePath="impl/pnr/apple-one.pin.html"/>
<ResultFile ResultFileType="RES.pnr.posp.bin" ResultFilePath="impl/pnr/apple-one.db"/>
<ResultFile ResultFileType="RES.pnr.pwr.rpt" ResultFilePath="impl/pnr/apple-one.power.html"/>
<ResultFile ResultFileType="RES.pnr.report" ResultFilePath="impl/pnr/apple-one.rpt.html"/>
<ResultFile ResultFileType="RES.pnr.timing.paths" ResultFilePath="impl/pnr/apple-one.timing_paths"/>
<ResultFile ResultFileType="RES.pnr.timing.rpt" ResultFilePath="impl/pnr/apple-one.tr.html"/>
<ResultFile ResultFileType="RES.syn.report" ResultFilePath="impl/gwsynthesis/apple-one_syn.rpt.html"/>
<ResultFile ResultFileType="RES.syn.resource" ResultFilePath="impl/gwsynthesis/apple-one_syn_rsc.xml"/>
</ResultFileList>
<Ui></Ui>
<FpUi>312e30313131000000ff00000000fd000000020000000000000100000000b5fc0200000001fc0000003f000000b5000000a40100001efa000000010200000002fb0000001c0044006f0063006b00650072002e00530075006d006d0061007200790100000000ffffffff0000008500fffffffb0000001c0044006f0063006b00650072002e004e00650074006c0069007300740100000000ffffffff0000005b00ffffff0000000300000500000002c6fc0100000001fc00000000000005000000007b00fffffffa00000002010000000bfb0000001c0044006f0063006b00650072002e004d0065007300730061006700650100000000ffffffff0000005800fffffffb0000002c0044006f0063006b00650072002e0049002f004f002e0043006f006e00730074007200610069006e007400730100000000ffffffff0000004600fffffffb000000380044006f0063006b00650072002e005000720069006d00690074006900760065002e0043006f006e00730074007200610069006e007400730100000000ffffffff0000004600fffffffb000000300044006f0063006b00650072002e00470072006f00750070002e0043006f006e00730074007200610069006e007400730100000000ffffffff0000004600fffffffb000000360044006f0063006b00650072002e005200650073006f0075007200630065002e005200650073006500720076006100740069006f006e0100000000ffffffff0000004600fffffffb000000380044006f0063006b00650072002e0043006c006f0063006b002e004e00650074002e0043006f006e00730074007200610069006e007400730100000000ffffffff0000004600fffffffb000000420044006f0063006b00650072002e00470043004c004b002e005000720069006d00690074006900760065002e0043006f006e00730074007200610069006e007400730100000000ffffffff0000004600fffffffb000000420044006f0063006b00650072002e00480043004c004b002e005000720069006d00690074006900760065002e0043006f006e00730074007200610069006e007400730000000000ffffffff0000004600fffffffb000000440044006f0063006b00650072002e00470043004c004b0032002e005000720069006d00690074006900760065002e0043006f006e00730074007200610069006e007400730000000000ffffffff0000004600fffffffb000000460044006f0063006b00650072002e00480043004c004b00350041002e005000720069006d00690074006900760065002e0043006f006e00730074007200610069006e007400730100000000ffffffff0000004600fffffffb0000002e0044006f0063006b00650072002e0056007200650066002e0043006f006e00730074007200610069006e007400730100000000ffffffff0000004600ffffff000003fa000000b500000004000000040000000800000008fc000000010000000200000001000000180054006f006f006c004200610072002e00460069006c00650100000000ffffffff0000000000000000</FpUi>
</UserConfig>
+4
View File
@@ -0,0 +1,4 @@
open_project "apple-one.gprj"
# The "all" target will run synthesis, place-and-route, and bitstream generation
run all
@@ -0,0 +1,93 @@
{
"BACKGROUND_PROGRAMMING" : "off",
"COMPRESS" : false,
"CPU" : true,
"CRC_CHECK" : true,
"Clock_Route_Order" : 0,
"Convert_SDP32_36_to_SDP16_18" : true,
"Correct_Hold_Violation" : true,
"DONE" : true,
"DOWNLOAD_SPEED" : "default",
"Disable_Insert_Pad" : false,
"ENABLE_CTP" : false,
"ENABLE_MERGE_MODE" : false,
"ENCRYPTION_KEY" : false,
"ENCRYPTION_KEY_TEXT" : "00000000000000000000000000000000",
"ERROR_DECTION_AND_CORRECTION" : false,
"ERROR_DECTION_ONLY" : false,
"ERROR_INJECTION" : false,
"EXTERNAL_MASTER_CONFIG_CLOCK" : false,
"Enable_DSRM" : false,
"FORMAT" : "binary",
"FREQUENCY_DIVIDER" : "1",
"Generate_Constraint_File_of_Ports" : false,
"Generate_IBIS_File" : false,
"Generate_Plain_Text_Timing_Report" : false,
"Generate_Post_PNR_Simulation_Model_File" : false,
"Generate_Post_Place_File" : false,
"Generate_SDF_File" : false,
"Generate_VHDL_Post_PNR_Simulation_Model_File" : false,
"Global_Freq" : "default",
"GwSyn_Loop_Limit" : 2000,
"HOTBOOT" : false,
"I2C" : false,
"I2C_SLAVE_ADDR" : "00",
"INCREMENTAL_PLACE_AND_ROUTING" : "0",
"INCREMENTAL_PLACE_ONLY" : "0",
"IncludePath" : [
],
"Incremental_Compile" : "",
"Initialize_Primitives" : false,
"JTAG" : false,
"MODE_IO" : false,
"MSPI" : false,
"MSPI_JUMP" : false,
"MULTIBOOT_ADDRESS_WIDTH" : "24",
"MULTIBOOT_MODE" : "Single",
"MULTIBOOT_SPI_FLASH_ADDRESS" : "000000",
"MULTIJUMP_ADDRESS_WIDTH" : "24",
"MULTIJUMP_MODE" : "Single",
"MULTIJUMP_SPI_FLASH_ADDRESS" : "000000",
"Multi_Boot" : false,
"OUTPUT_BASE_NAME" : "apple-one",
"POWER_ON_RESET_MONITOR" : true,
"PRINT_BSRAM_VALUE" : true,
"PROGRAM_DONE_BYPASS" : false,
"PlaceInRegToIob" : true,
"PlaceIoRegToIob" : true,
"PlaceOutRegToIob" : true,
"Place_Option" : "0",
"Process_Configuration_Verion" : "1.0",
"Promote_Physical_Constraint_Warning_to_Error" : true,
"READY" : true,
"RECONFIG_N" : false,
"Ram_RW_Check" : false,
"Replicate_Resources" : false,
"Report_Auto-Placed_Io_Information" : false,
"Route_Maxfan" : "23",
"Route_Option" : "0",
"Run_Timing_Driven" : true,
"SECURE_MODE" : false,
"SECURITY_BIT" : true,
"SEU_HANDLER" : false,
"SEU_HANDLER_CHECKSUM" : false,
"SEU_HANDLER_MODE" : "auto",
"SSPI" : true,
"STOP_SEU_HANDLER" : false,
"SerDes_retiming" : false,
"Show_All_Warnings" : false,
"Synthesize_tool" : "GowinSyn",
"TclPre" : "",
"TopModule" : "apple1_primer",
"USERCODE" : "default",
"Unused_Pin" : "As_input_tri_stated_with_pull_up",
"VCC" : "0.9",
"VCCAUX" : "3.3",
"VCCX" : "3.3",
"VHDL_Standard" : "VHDL_Std_1993",
"Verilog_Standard" : "Vlg_Std_Sysv2017",
"WAKE_UP" : "0",
"show_all_warnings" : false,
"turn_off_bg" : false
}
+266 -225
View File
@@ -23,258 +23,299 @@
//
module apple1 #(
parameter BASIC_FILENAME = "../../../roms/basic.hex",
parameter FONT_ROM_FILENAME = "../../../roms/vga_font_bitreversed.hex",
parameter RAM_FILENAME = "../../../roms/ram.hex",
parameter VRAM_FILENAME = "../../../roms/vga_vram.bin",
parameter WOZMON_ROM_FILENAME = "../../../roms/wozmon.hex"
parameter string BASIC_FILENAME = "../../../roms/basic.hex",
parameter string FONT_ROM_FILENAME = "../../../roms/vga_font_bitreversed.hex",
parameter string RAM_FILENAME = "../../../roms/ram.hex",
parameter string VRAM_FILENAME = "../../../roms/vga_vram.bin",
parameter string WOZMON_ROM_FILENAME = "../../../roms/wozmon.hex"
) (
input clk25, // 25 MHz master clock
input rst_n, // active low synchronous reset (needed for simulation)
input clk25, // 25 MHz master clock
input rst_n, // active low synchronous reset (needed for simulation)
// 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
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
input ps2_select, // Input to select the PS/2 keyboard instead of the UART
// I/O interface to PS/2 keyboard
input ps2_clk, // PS/2 keyboard serial clock input
input ps2_din, // PS/2 keyboard serial data input
// I/O interface to USB keyboard
input usb_clk, // 12MHz USB clock
inout usb_dm, // USB data minus signal
inout usb_dp, // USB data plus signal
output usb_led_err, // USB connection error LED
output usb_led_act, // USB activity LED
input [1:0] key_select, // Select the Apple 1 keyboard input
// 2'b00 - UART RX
// 2'b01 - USB Keyboard
// 2'b10 - P/S Keyboard
// 2'b11 - None / Other
// Outputs to VGA display
output vga_h_sync, // hozizontal VGA sync pulse
output vga_v_sync, // vertical VGA sync pulse
output vga_red, // red VGA signal
output vga_grn, // green VGA signal
output vga_blu, // blue VGA signal
input vga_cls, // clear screen button
output vga_de, // display enable
output vga_h_sync, // hozizontal VGA sync pulse
output vga_v_sync, // vertical VGA sync pulse
output vga_red, // red VGA signal
output vga_grn, // green VGA signal
output vga_blu, // blue VGA signal
input vga_cls, // clear screen button
output vga_de, // display enable
// Debugging ports
output [15:0] pc_monitor // spy for program counter / debugging
output [15:0] pc_monitor // spy for program counter / debugging
);
//////////////////////////////////////////////////////////////////////////
// Registers and Wires
//////////////////////////////////////////////////////////////////////////
// Registers and Wires
wire [15:0] ab;
wire [7:0] dbi;
wire [7:0] dbo;
wire we;
wire [15:0] ab;
wire [7:0] dbi;
wire [7:0] dbo;
wire we;
//////////////////////////////////////////////////////////////////////////
// Clocks
//////////////////////////////////////////////////////////////////////////
// Clocks
wire cpu_clken;
clock my_clock(
.clk25(clk25),
.rst_n(rst_n),
.cpu_clken(cpu_clken)
);
wire cpu_clken;
clock my_clock (
.clk25(clk25),
.rst_n(rst_n),
.cpu_clken(cpu_clken)
);
//////////////////////////////////////////////////////////////////////////
// Reset
//////////////////////////////////////////////////////////////////////////
// Reset
wire rst;
pwr_reset my_reset(
.clk25(clk25),
.rst_n(rst_n),
.enable(cpu_clken),
.rst(rst)
);
wire rst;
pwr_reset my_reset (
.clk25(clk25),
.rst_n(rst_n),
.enable(cpu_clken),
.rst(rst)
);
//////////////////////////////////////////////////////////////////////////
// 6502
//////////////////////////////////////////////////////////////////////////
// 6502
arlet_6502 my_cpu(
.clk (clk25),
.enable (cpu_clken),
.rst (rst),
.ab (ab),
.dbi (dbi),
.dbo (dbo),
.we (we),
.irq_n (1'b1),
.nmi_n (1'b1),
.ready (cpu_clken),
.pc_monitor (pc_monitor)
);
arlet_6502 my_cpu (
.clk (clk25),
.enable (cpu_clken),
.rst (rst),
.ab (ab),
.dbi (dbi),
.dbo (dbo),
.we (we),
.irq_n (1'b1),
.nmi_n (1'b1),
.ready (cpu_clken),
.pc_monitor(pc_monitor)
);
//////////////////////////////////////////////////////////////////////////
// Address Decoding
//////////////////////////////////////////////////////////////////////////
// Address Decoding
wire ram_cs = (ab[15:13] == 3'b000); // 0x0000 -> 0x1FFF
reg ram_cs, vga_cs, vga_mode_cs, rx_cs, tx_cs, uart_cs, usb_cs, ps2kb_cs, basic_cs, rom_cs;
// font mode, background and foreground colour
wire vga_mode_cs = (ab[15:2] == 14'b11000000000000); // 0xC000 -> 0xC003
always @(posedge clk25 or posedge rst) begin
if (rst) begin
ram_cs <= 1'd0;
vga_mode_cs <= 1'd0;
rx_cs <= 1'd0;
tx_cs <= 1'd0;
uart_cs <= 1'd0;
usb_cs <= 1'd0;
ps2kb_cs <= 1'd0;
basic_cs <= 1'd0;
rom_cs <= 1'd0;
end else begin
// RAM selection
ram_cs <= (ab[15:13] == 3'b000); // 0x0000 -> 0x1FFF
// RX: Either keyboard or UART input
// TX: Always VGA and UART output
wire rx_cs = (ab[15:1] == 15'b110100000001000); // 0xD010 -> 0xD011
wire tx_cs = (ab[15:1] == 15'b110100000001001); // 0xD012 -> 0xD013
// font mode, background and foreground colour
vga_mode_cs <= (ab[15:2] == 14'b11000000000000); // 0xC000 -> 0xC003
// select UART on transmit but only receive when PS/2 is not selected.
wire uart_cs = tx_cs | ((~ps2_select) & rx_cs);
// RX: Either keyboard or UART input
// TX: Always VGA and UART output
rx_cs <= (ab[15:1] == 15'b110100000001000); // 0xD010 -> 0xD011
tx_cs <= (ab[15:1] == 15'b110100000001001); // 0xD012 -> 0xD013
// select PS/2 keyboard input when selected.
wire ps2kb_cs = ps2_select & rx_cs;
// select UART on transmit and only receive if key_select is UART
uart_cs <= tx_cs | (rx_cs & (key_select == 2'b00));
// VGA always get characters when they are sent.
wire vga_cs = tx_cs;
// select USB keyboard input when selected.
usb_cs <= rx_cs & (key_select == 2'b01);
wire basic_cs = (ab[15:12] == 4'b1110); // 0xE000 -> 0xEFFF
wire rom_cs = (ab[15:8] == 8'b11111111); // 0xFF00 -> 0xFFFF
// select PS/2 keyboard input when selected.
ps2kb_cs <= rx_cs & (key_select == 2'b10);
//////////////////////////////////////////////////////////////////////////
// RAM and ROM
// VGA always get characters when they are sent.
vga_cs <= tx_cs;
// RAM
wire [7:0] ram_dout;
ram #(
.RAM_FILENAME (RAM_FILENAME)
) 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 #(
.WOZMON_ROM_FILENAME (WOZMON_ROM_FILENAME)
) my_rom_wozmon(
.clk(clk25),
.address(ab[7:0]),
.dout(rom_dout)
);
// Basic ROM
wire [7:0] basic_dout;
rom_basic #(
.BASIC_FILENAME (BASIC_FILENAME)
) my_rom_basic(
.clk(clk25),
.address(ab[11:0]),
.dout(basic_dout)
);
//////////////////////////////////////////////////////////////////////////
// Peripherals
// UART
wire [7:0] uart_dout;
uart #(
`ifdef SIM
100, 10, 2 // for simulation don't need real baud rates
`else
25000000, 115200, 8 // 25MHz, 115200 baud, 8 times RX oversampling
`endif
) my_uart(
.clk(clk25),
.enable(uart_cs & cpu_clken),
.rst(rst),
.uart_rx(uart_rx),
.uart_tx(uart_tx),
.uart_cts(uart_cts),
.address(ab[1:0]), // for uart
.w_en(we & uart_cs),
.din(dbo),
.dout(uart_dout)
);
// PS/2 keyboard interface
wire [7:0] ps2_dout;
ps2keyboard keyboard(
.clk25(clk25),
.rst(rst),
.key_clk(ps2_clk),
.key_din(ps2_din),
.cs(ps2kb_cs),
.address(ab[0]),
.dout(ps2_dout)
);
// VGA Display interface
reg [2:0] fg_colour;
reg [2:0] bg_colour;
reg [1:0] font_mode;
reg [7:0] vga_mode_dout;
vga #(
.VRAM_FILENAME (VRAM_FILENAME),
.FONT_ROM_FILENAME (FONT_ROM_FILENAME)
) my_vga(
.clk25(clk25),
.enable(vga_cs & cpu_clken),
.rst(rst),
.vga_h_sync(vga_h_sync),
.vga_v_sync(vga_v_sync),
.vga_red(vga_red),
.vga_grn(vga_grn),
.vga_blu(vga_blu),
.vga_de(vga_de),
.address(ab[0]),
.w_en(we & vga_cs),
.din(dbo),
.mode(font_mode),
.fg_colour(fg_colour),
.bg_colour(bg_colour),
.clr_screen(vga_cls)
);
// Handle font mode and foreground and background
// colours. This so isn't Apple One authentic, but
// it can't hurt to have some fun. :D
always @(posedge clk25 or posedge rst)
begin
if (rst)
begin
font_mode <= 2'b0;
fg_colour <= 3'd7;
bg_colour <= 3'd0;
end
else
begin
case (ab[1:0])
2'b00:
begin
vga_mode_dout = {6'b0, font_mode};
if (vga_mode_cs & we & cpu_clken)
font_mode <= dbo[1:0];
end
2'b01:
begin
vga_mode_dout = {5'b0, fg_colour};
if (vga_mode_cs & we & cpu_clken)
fg_colour <= dbo[2:0];
end
2'b10:
begin
vga_mode_dout = {5'b0, bg_colour};
if (vga_mode_cs & we & cpu_clken)
bg_colour <= dbo[2:0];
end
default:
vga_mode_dout = 8'b0;
endcase
end
// ROM selection
basic_cs <= (ab[15:12] == 4'b1110); // 0xE000 -> 0xEFFF
rom_cs <= (ab[15:8] == 8'b11111111); // 0xFF00 -> 0xFFFF
end
end
//////////////////////////////////////////////////////////////////////////
// CPU Data In MUX
//////////////////////////////////////////////////////////////////////////
// RAM and ROM
// link up chip selected device to cpu input
assign dbi = ram_cs ? ram_dout :
rom_cs ? rom_dout :
basic_cs ? basic_dout :
uart_cs ? uart_dout :
ps2kb_cs ? ps2_dout :
vga_mode_cs ? vga_mode_dout :
8'hFF;
// RAM
wire [7:0] ram_dout;
ram #(
.RAM_FILENAME(RAM_FILENAME)
) 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 #(
.WOZMON_ROM_FILENAME(WOZMON_ROM_FILENAME)
) my_rom_wozmon (
.clk(clk25),
.address(ab[7:0]),
.dout(rom_dout)
);
// Basic ROM
wire [7:0] basic_dout;
rom_basic #(
.BASIC_FILENAME(BASIC_FILENAME)
) my_rom_basic (
.clk(clk25),
.address(ab[11:0]),
.dout(basic_dout)
);
//////////////////////////////////////////////////////////////////////////
// Peripherals
// UART
wire [7:0] uart_dout;
uart #(
`ifdef SIM
.ClkFrequency(100),
.Baud(10),
.Oversampling(2) // for simulation don't need real baud rates
`else
.ClkFrequency(25000000),
.Baud(115200),
.Oversampling(8) // 25MHz, 115200 baud, 8 times RX oversampling
`endif
) my_uart (
.clk(clk25),
.enable(uart_cs & cpu_clken),
.rst(rst),
.uart_rx (uart_rx),
.uart_tx (uart_tx),
.uart_cts(uart_cts),
.address(ab[1:0]), // for uart
.w_en (we & uart_cs),
.din (dbo),
.dout (uart_dout)
);
// USB Keyboard
wire [7:0] usb_dout;
usb_keyboard my_usb_keyboard (
.usb_clk(usb_clk),
.rst(rst),
.usb_dm(usb_dm),
.usb_dp(usb_dp),
.cs(usb_cs),
.address(ab[0]),
.dout(usb_dout),
.led_connerr(usb_led_err),
.led_activity(usb_led_act)
);
// PS/2 keyboard interface
wire [7:0] ps2_dout;
ps2keyboard my_ps2_keyboard (
.clk25(clk25),
.rst(rst),
.key_clk(ps2_clk),
.key_din(ps2_din),
.cs(ps2kb_cs),
.address(ab[0]),
.dout(ps2_dout)
);
// VGA Display interface
reg [2:0] fg_colour;
reg [2:0] bg_colour;
reg [1:0] font_mode;
reg [7:0] vga_mode_dout;
vga #(
.VRAM_FILENAME(VRAM_FILENAME),
.FONT_ROM_FILENAME(FONT_ROM_FILENAME)
) my_vga (
.clk25(clk25),
.enable(vga_cs & cpu_clken),
.rst(rst),
.vga_h_sync(vga_h_sync),
.vga_v_sync(vga_v_sync),
.vga_red(vga_red),
.vga_grn(vga_grn),
.vga_blu(vga_blu),
.vga_de(vga_de),
.address(ab[0]),
.w_en(we & vga_cs),
.din(dbo),
.mode(font_mode),
.fg_colour(fg_colour),
.bg_colour(bg_colour),
.clr_screen(vga_cls)
);
// Handle font mode and foreground and background
// colours. This so isn't Apple One authentic, but
// it can't hurt to have some fun. :D
always @(posedge clk25 or posedge rst) begin
if (rst) begin
font_mode <= 2'b0;
fg_colour <= 3'd7;
bg_colour <= 3'd0;
end else begin
case (ab[1:0])
2'b00: begin
vga_mode_dout = {6'b0, font_mode};
if (vga_mode_cs & we & cpu_clken) font_mode <= dbo[1:0];
end
2'b01: begin
vga_mode_dout = {5'b0, fg_colour};
if (vga_mode_cs & we & cpu_clken) fg_colour <= dbo[2:0];
end
2'b10: begin
vga_mode_dout = {5'b0, bg_colour};
if (vga_mode_cs & we & cpu_clken) bg_colour <= dbo[2:0];
end
default: vga_mode_dout = 8'b0;
endcase
end
end
//////////////////////////////////////////////////////////////////////////
// CPU Data In MUX
// link up chip selected device to cpu input
assign dbi = ram_cs ? ram_dout :
rom_cs ? rom_dout :
basic_cs ? basic_dout :
uart_cs ? uart_dout :
ps2kb_cs ? ps2_dout :
usb_cs ? usb_dout :
vga_mode_cs ? vga_mode_dout :
8'hFF;
endmodule
+71 -71
View File
@@ -28,99 +28,99 @@ module apple1_top #(
parameter VRAM_FILENAME = "../../../roms/vga_vram.bin",
parameter WOZMON_ROM_FILENAME = "../../../roms/wozmon.hex"
) (
input clk, // 100 MHz board clock
input clk, // 100 MHz board clock
// 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 - not used
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 - not used
// I/O interface to keyboard
input ps2_clk, // PS/2 keyboard serial clock input
input ps2_din, // PS/2 keyboard serial data input
input ps2_clk, // PS/2 keyboard serial clock input
input ps2_din, // PS/2 keyboard serial data input
// Outputs to VGA display
output vga_h_sync, // hozizontal VGA sync pulse
output vga_v_sync, // vertical VGA sync pulse
output vga_h_sync, // hozizontal VGA sync pulse
output vga_v_sync, // vertical VGA sync pulse
output [3:0] vga_r, // red VGA signal
output [3:0] vga_g, // green VGA signal
output [3:0] vga_b, // blue VGA signal
output [3:0] vga_r, // red VGA signal
output [3:0] vga_g, // green VGA signal
output [3:0] vga_b, // blue VGA signal
// Debugging ports
output [3:0] led,
input [1:0] button // 2 buttons on board
input [1:0] button // 2 buttons on board
);
assign led[0] = 1;
assign led[1] = reset_n;
assign led[2] = clr_screen_n;
assign led[3] = 0;
assign led[0] = 1;
assign led[1] = reset_n;
assign led[2] = clr_screen_n;
assign led[3] = 0;
wire clk25;
wire clk25;
// ===============================================================
// System Clock generation (25MHz)
// ===============================================================
// ===============================================================
// System Clock generation (25MHz)
// ===============================================================
reg [1:0] clkpre = 2'b00; // prescaler, from 100MHz to 25MHz
reg [1:0] clkpre = 2'b00; // prescaler, from 100MHz to 25MHz
always @(posedge clk)
begin
clkpre <= clkpre + 1;
end
wire clk25 = clkpre[1];
always @(posedge clk) begin
clkpre <= clkpre + 1;
end
wire clk25 = clkpre[1];
wire vga_bit;
wire vga_bit;
// set the monochrome base colour here..
assign vga_r[3:0] = vga_bit ? 4'b1000 : 4'b0000;
assign vga_g[3:0] = vga_bit ? 4'b1111 : 4'b0000;
assign vga_b[3:0] = vga_bit ? 4'b1000 : 4'b0000;
// set the monochrome base colour here..
assign vga_r[3:0] = vga_bit ? 4'b1000 : 4'b0000;
assign vga_g[3:0] = vga_bit ? 4'b1111 : 4'b0000;
assign vga_b[3:0] = vga_bit ? 4'b1000 : 4'b0000;
// debounce reset button
wire reset_n;
debounce reset_button (
.clk25(clk25),
.rst(1'b0),
.sig_in(button[0]),
.sig_out(reset_n)
);
// debounce reset button
wire reset_n;
debounce reset_button (
.clk25(clk25),
.rst(1'b0),
.sig_in(button[0]),
.sig_out(reset_n)
);
// debounce clear screen button
wire clr_screen_n;
debounce clr_button (
.clk25(clk25),
.rst(~reset_n),
.sig_in(button[1]),
.sig_out(clr_screen_n)
);
// debounce clear screen button
wire clr_screen_n;
debounce clr_button (
.clk25(clk25),
.rst(~reset_n),
.sig_in(button[1]),
.sig_out(clr_screen_n)
);
// apple one main system
apple1 #(
.BASIC_FILENAME (BASIC_FILENAME),
.FONT_ROM_FILENAME (FONT_ROM_FILENAME),
.RAM_FILENAME (RAM_FILENAME),
.VRAM_FILENAME (VRAM_FILENAME),
.WOZMON_ROM_FILENAME (WOZMON_ROM_FILENAME)
) my_apple1(
.clk25(clk25),
.rst_n(reset_n),
// apple one main system
apple1 #(
.BASIC_FILENAME(BASIC_FILENAME),
.FONT_ROM_FILENAME(FONT_ROM_FILENAME),
.RAM_FILENAME(RAM_FILENAME),
.VRAM_FILENAME(VRAM_FILENAME),
.WOZMON_ROM_FILENAME(WOZMON_ROM_FILENAME)
) my_apple1 (
.clk25(clk25),
.rst_n(reset_n),
.uart_rx(uart_rx),
.uart_tx(uart_tx),
.uart_cts(uart_cts),
.uart_rx (uart_rx),
.uart_tx (uart_tx),
.uart_cts(uart_cts),
.ps2_clk(ps2_clk),
.ps2_din(ps2_din),
.ps2_select(1'b1), // PS/2 enabled, UART TX disabled
//.ps2_select(1'b0), // PS/2 disabled, UART TX enabled
.ps2_clk(ps2_clk),
.ps2_din(ps2_din),
.vga_h_sync(vga_h_sync),
.vga_v_sync(vga_v_sync),
.vga_red(vga_bit),
//.vga_grn(vga_bit),
//.vga_blu(vga_bit),
.vga_cls(~clr_screen_n),
);
// .key_select(2'b00), // UART enabled
.key_select(2'b10), // PS/2 keyboard enabled
.vga_h_sync(vga_h_sync),
.vga_v_sync(vga_v_sync),
.vga_red(vga_bit),
//.vga_grn(vga_bit),
//.vga_blu(vga_bit),
.vga_cls(~clr_screen_n),
);
endmodule
+103 -104
View File
@@ -23,135 +23,134 @@
//
module apple1_top #(
parameter BASIC_FILENAME = "../../../roms/basic.hex",
parameter FONT_ROM_FILENAME = "../../../roms/vga_font_bitreversed.hex",
parameter RAM_FILENAME = "../../../roms/ram.hex",
parameter VRAM_FILENAME = "../../../roms/vga_vram.bin",
parameter WOZMON_ROM_FILENAME = "../../../roms/wozmon.hex"
parameter string BASIC_FILENAME = "../../../roms/basic.hex",
parameter string FONT_ROM_FILENAME = "../../../roms/vga_font_bitreversed.hex",
parameter string RAM_FILENAME = "../../../roms/ram.hex",
parameter string VRAM_FILENAME = "../../../roms/vga_vram.bin",
parameter string WOZMON_ROM_FILENAME = "../../../roms/wozmon.hex"
) (
input clk, // 12 MHz board clock
input clk, // 12 MHz board clock
// 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
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
input ps2_clk, // PS/2 keyboard serial clock input
input ps2_din, // PS/2 keyboard serial data input
// Outputs to VGA display
output vga_h_sync, // hozizontal VGA sync pulse
output vga_v_sync, // vertical VGA sync pulse
output vga_h_sync, // hozizontal VGA sync pulse
output vga_v_sync, // vertical VGA sync pulse
output reg vga_red, // red VGA signal
output reg vga_grn, // green VGA signal
output reg vga_blu, // blue VGA signal
// Debugging ports
output [7:0] led, // 8 LEDs on the iCE40HX8K board
output [7:0] ledx, // 8 LEDs on optionally attached YL-4 board
input [3:0] button // 4 buttons on optionally attached YL-4 board
output [7:0] led, // 8 LEDs on the iCE40HX8K board
output [7:0] ledx, // 8 LEDs on optionally attached YL-4 board
input [3:0] button // 4 buttons on optionally attached YL-4 board
);
//////////////////////////////////////////////////////////////////////////
// Registers and Wires
wire clk25;
//////////////////////////////////////////////////////////////////////////
// Registers and Wires
wire clk25;
wire [15:0] pc_monitor;
assign led[7:0] = pc_monitor[7:0];
assign ledx[7:0] = ~pc_monitor[15:8];
wire [15:0] pc_monitor;
assign led[7:0] = pc_monitor[7:0];
assign ledx[7:0] = ~pc_monitor[15:8];
//////////////////////////////////////////////////////////////////////////
// Clocks
// 12MHz up to 25MHz
pll my_pll(
.clock_in(clk),
.clock_out(clk25)
);
//////////////////////////////////////////////////////////////////////////
// Clocks
// 12MHz up to 25MHz
pll my_pll (
.clock_in (clk),
.clock_out(clk25)
);
//////////////////////////////////////////////////////////////////////////
// PS/2 Keyboard
//////////////////////////////////////////////////////////////////////////
// PS/2 Keyboard
// PS2 Pullups
wire ps2__clk, ps2__din;
SB_IO #(
.PIN_TYPE(6'b000001),
.PULLUP(1'b1)
) my_ps2_clk (
.PACKAGE_PIN(ps2_clk),
.D_IN_0(ps2__clk),
);
// PS2 Pullups
wire ps2__clk, ps2__din;
SB_IO #(
.PIN_TYPE(6'b000001),
.PULLUP (1'b1)
) my_ps2_clk (
.PACKAGE_PIN(ps2_clk),
.D_IN_0(ps2__clk),
);
SB_IO #(
.PIN_TYPE(6'b000001),
.PULLUP(1'b1)
) my_ps2_din (
.PACKAGE_PIN(ps2_din),
.D_IN_0(ps2__din),
);
SB_IO #(
.PIN_TYPE(6'b000001),
.PULLUP (1'b1)
) my_ps2_din (
.PACKAGE_PIN(ps2_din),
.D_IN_0(ps2__din),
);
//////////////////////////////////////////////////////////////////////////
// Reset, Clear Screen and PS/2 mode selection toggle
//////////////////////////////////////////////////////////////////////////
// Reset, Clear Screen and PS/2 mode selection toggle
// debounce reset button
wire reset_n;
debounce reset_button (
.clk25(clk25),
.rst(1'b0),
.sig_in(button[0]),
.sig_out(reset_n)
);
// debounce reset button
wire reset_n;
debounce reset_button (
.clk25(clk25),
.rst(1'b0),
.sig_in(button[0]),
.sig_out(reset_n)
);
// debounce clear screen button
wire clr_screen_n;
debounce clr_button (
.clk25(clk25),
.rst(~reset_n),
.sig_in(button[1]),
.sig_out(clr_screen_n)
);
// debounce clear screen button
wire clr_screen_n;
debounce clr_button (
.clk25(clk25),
.rst(~reset_n),
.sig_in(button[1]),
.sig_out(clr_screen_n)
);
// debounce toggle button on PS2 select
wire ps2_toggle;
reg ps2_select;
debounce ps2_button (
.clk25(clk25),
.rst(~reset_n),
.sig_in(button[2]),
.sig_out(ps2_toggle)
);
// debounce toggle button on PS2 select
wire ps2_toggle;
reg ps2_select;
debounce ps2_button (
.clk25(clk25),
.rst(~reset_n),
.sig_in(button[2]),
.sig_out(ps2_toggle)
);
// defaults to PS2 mode, but can toggle between
// UART and PS2 per button press
always @(posedge ps2_toggle)
ps2_select <= ~ps2_select;
// defaults to PS2 mode, but can toggle between
// UART and PS2 per button press
always @(posedge ps2_toggle) ps2_select <= ~ps2_select;
//////////////////////////////////////////////////////////////////////////
// Core of system
//////////////////////////////////////////////////////////////////////////
// Core of system
// apple one main system
apple1 #(
.BASIC_FILENAME (BASIC_FILENAME),
.FONT_ROM_FILENAME (FONT_ROM_FILENAME),
.RAM_FILENAME (RAM_FILENAME),
.VRAM_FILENAME (VRAM_FILENAME),
.WOZMON_ROM_FILENAME (WOZMON_ROM_FILENAME)
) my_apple1(
.clk25(clk25),
.rst_n(reset_n),
.uart_rx(uart_rx),
.uart_tx(uart_tx),
.uart_cts(uart_cts),
.ps2_clk(ps2__clk),
.ps2_din(ps2__din),
.ps2_select(ps2_select),
.vga_h_sync(vga_h_sync),
.vga_v_sync(vga_v_sync),
.vga_red(vga_red),
.vga_grn(vga_grn),
.vga_blu(vga_blu),
.vga_cls(~clr_screen_n),
.pc_monitor(pc_monitor)
);
// apple one main system
apple1 #(
.BASIC_FILENAME(BASIC_FILENAME),
.FONT_ROM_FILENAME(FONT_ROM_FILENAME),
.RAM_FILENAME(RAM_FILENAME),
.VRAM_FILENAME(VRAM_FILENAME),
.WOZMON_ROM_FILENAME(WOZMON_ROM_FILENAME)
) my_apple1 (
.clk25(clk25),
.rst_n(reset_n),
.uart_rx(uart_rx),
.uart_tx(uart_tx),
.uart_cts(uart_cts),
.ps2_clk(ps2__clk),
.ps2_din(ps2__din),
.key_select(ps2_select ? 2'b10 : 2'b00), // switch between PS/2 or UART
.vga_h_sync(vga_h_sync),
.vga_v_sync(vga_v_sync),
.vga_red(vga_red),
.vga_grn(vga_grn),
.vga_blu(vga_blu),
.vga_cls(~clr_screen_n),
.pc_monitor(pc_monitor)
);
endmodule
@@ -28,93 +28,93 @@ module apple1_top #(
parameter VRAM_FILENAME = "../../../roms/vga_vram.bin",
parameter WOZMON_ROM_FILENAME = "../../../roms/wozmon.hex"
) (
input clk, // 50 MHz board clock
input clk, // 50 MHz board clock
// 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 - not used
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 - not used
// I/O interface to keyboard
input ps2_clk, // PS/2 keyboard serial clock input
input ps2_din, // PS/2 keyboard serial data input
input ps2_clk, // PS/2 keyboard serial clock input
input ps2_din, // PS/2 keyboard serial data input
// Outputs to VGA display
output vga_h_sync, // hozizontal VGA sync pulse
output vga_v_sync, // vertical VGA sync pulse
output vga_h_sync, // hozizontal VGA sync pulse
output vga_v_sync, // vertical VGA sync pulse
// Outputs to the ADV7123 RGB DAC IC
output vga_clk,
output vga_blank_n,
output [3:0] vga_r, // red VGA signal
output [3:0] vga_g, // green VGA signal
output [3:0] vga_b, // blue VGA signal
output [3:0] vga_r, // red VGA signal
output [3:0] vga_g, // green VGA signal
output [3:0] vga_b, // blue VGA signal
// Debugging ports
output [2:0] led,
input button, // 1 button on board
input button // 1 button on board
);
assign vga_clk = clk25;
assign vga_blank_n = 1;
assign vga_clk = clk25;
assign vga_blank_n = 1;
// Active low
assign led[0] = reset_n;
assign led[1] = 1;
assign led[2] = 1;
// Active low
assign led[0] = reset_n;
assign led[1] = 1;
assign led[2] = 1;
// ===============================================================
// System Clock generation (25MHz)
// ===============================================================
// ===============================================================
// System Clock generation (25MHz)
// ===============================================================
reg clk25 = 1;
reg clk25 = 1;
// generate 25MHz clock from 50MHz master clock
always @(posedge clk)
begin
clk25 <= ~clk25;
end
// generate 25MHz clock from 50MHz master clock
always @(posedge clk) begin
clk25 <= ~clk25;
end
wire vga_bit;
wire vga_bit;
// set the monochrome base colour here..
assign vga_r[3:0] = vga_bit ? 4'b1000 : 4'b0000;
assign vga_g[3:0] = vga_bit ? 4'b1111 : 4'b0000;
assign vga_b[3:0] = vga_bit ? 4'b1000 : 4'b0000;
// set the monochrome base colour here..
assign vga_r[3:0] = vga_bit ? 4'b1000 : 4'b0000;
assign vga_g[3:0] = vga_bit ? 4'b1111 : 4'b0000;
assign vga_b[3:0] = vga_bit ? 4'b1000 : 4'b0000;
// debounce reset button
wire reset_n;
debounce reset_button (
.clk25(clk25),
.rst(1'b0),
.sig_in(button),
.sig_out(reset_n)
);
// debounce reset button
wire reset_n;
debounce reset_button (
.clk25(clk25),
.rst(1'b0),
.sig_in(button),
.sig_out(reset_n)
);
// apple one main system
apple1 #(
.BASIC_FILENAME (BASIC_FILENAME),
.FONT_ROM_FILENAME (FONT_ROM_FILENAME),
.RAM_FILENAME (RAM_FILENAME),
.VRAM_FILENAME (VRAM_FILENAME),
.WOZMON_ROM_FILENAME (WOZMON_ROM_FILENAME)
) my_apple1(
.clk25(clk25),
.rst_n(reset_n),
// apple one main system
apple1 #(
.BASIC_FILENAME(BASIC_FILENAME),
.FONT_ROM_FILENAME(FONT_ROM_FILENAME),
.RAM_FILENAME(RAM_FILENAME),
.VRAM_FILENAME(VRAM_FILENAME),
.WOZMON_ROM_FILENAME(WOZMON_ROM_FILENAME)
) my_apple1 (
.clk25(clk25),
.rst_n(reset_n),
.uart_rx(uart_rx),
.uart_tx(uart_tx),
.uart_cts(uart_cts),
.uart_rx (uart_rx),
.uart_tx (uart_tx),
.uart_cts(uart_cts),
.ps2_clk(ps2_clk),
.ps2_din(ps2_din),
.ps2_select(1'b1), // PS/2 enabled, UART TX disabled
// .ps2_select(1'b0), // PS/2 disabled, UART TX enabled
.ps2_clk(ps2_clk),
.ps2_din(ps2_din),
.vga_h_sync(vga_h_sync),
.vga_v_sync(vga_v_sync),
.vga_red(vga_bit),
.vga_cls(~reset_n),
);
.key_select(2'b10), // PS/2 enabled, UART TX disabled
// .key_select(2'b00), // PS/2 disabled, UART TX enabled
.vga_h_sync(vga_h_sync),
.vga_v_sync(vga_v_sync),
.vga_red(vga_bit),
.vga_cls(~reset_n),
);
endmodule
+81 -65
View File
@@ -29,18 +29,18 @@ module apple1_top #(
parameter VRAM_FILENAME = "../../../roms/vga_vram.bin",
parameter WOZMON_ROM_FILENAME = "../../../roms/wozmon.hex"
) (
input clk, // 50 MHz board clock
input clk, // 50 MHz board clock
// I/O interface to computer
input usb_rx, // asynchronous serial data input from computer
output usb_tx, // asynchronous serial data output to computer
input usb_rx, // asynchronous serial data input from computer
output usb_tx, // asynchronous serial data output to computer
// I/O interface to keyboard
input [1:0] usb_dp, // PS/2 keyboard serial clock input
input [1:0] usb_dn, // PS/2 keyboard serial data input
input [1:0] usb_dp, // PS/2 keyboard serial clock input
input [1:0] usb_dn, // PS/2 keyboard serial data input
output [1:0] usb_pull_dp, // USB pullup/pulldown
output [1:0] usb_pull_dn, // USB pullup/pulldown
output [1:0] usb_pull_dp, // USB pullup/pulldown
output [1:0] usb_pull_dn, // USB pullup/pulldown
// DVI port
output [3:0] gpdi_dp,
@@ -49,75 +49,91 @@ module apple1_top #(
output [4:0] led,
input [1:0] button
);
wire uart_cts; // No CTS pin
wire uart_cts; // No CTS pin
wire clkp, clkt; // clkp: 25MHz, clkt: 250MHz
dvi_pll pll(clk, clkp, clkt, led[0]);
wire clkp, clkt; // clkp: 25MHz, clkt: 250MHz
dvi_pll pll (
clk,
clkp,
clkt,
led[0]
);
wire vsync, hsync, de;
wire [7:0] vga_r, vga_g, vga_b;
wire vsync, hsync, de;
wire [7:0] vga_r, vga_g, vga_b;
// Active low
assign led[1] = reset_n;
assign led[2] = hsync;
assign led[3] = 1'b1;
assign led[4] = 1'b0;
// Active low
assign led[1] = reset_n;
assign led[2] = hsync;
assign led[3] = 1'b1;
assign led[4] = 1'b0;
wire vga_bit;
wire vga_bit;
// set the monochrome base colour here..
assign vga_r = vga_bit ? 8'b10000000 : 4'b00000000;
assign vga_g = vga_bit ? 8'b11111111 : 4'b00000000;
assign vga_b = vga_bit ? 8'b10000000 : 4'b00000000;
// set the monochrome base colour here..
assign vga_r = vga_bit ? 8'b10000000 : 4'b00000000;
assign vga_g = vga_bit ? 8'b11111111 : 4'b00000000;
assign vga_b = vga_bit ? 8'b10000000 : 4'b00000000;
// debounce reset button
wire reset_n;
debounce reset_button (
.clk25(clkp),
.rst(1'b0),
.sig_in(button[0]),
.sig_out(reset_n)
);
// debounce reset button
wire reset_n;
debounce reset_button (
.clk25(clkp),
.rst(1'b0),
.sig_in(button[0]),
.sig_out(reset_n)
);
// debounce clear button
wire cls;
debounce cls_button (
.clk25(clkp),
.rst(1'b0),
.sig_in(~button[1]),
.sig_out(cls)
);
// debounce clear button
wire cls;
debounce cls_button (
.clk25(clkp),
.rst(1'b0),
.sig_in(~button[1]),
.sig_out(cls)
);
// apple one main system
apple1 #(
.BASIC_FILENAME (BASIC_FILENAME),
.FONT_ROM_FILENAME (FONT_ROM_FILENAME),
.RAM_FILENAME (RAM_FILENAME),
.VRAM_FILENAME (VRAM_FILENAME),
.WOZMON_ROM_FILENAME (WOZMON_ROM_FILENAME)
) my_apple1(
.clk25(clkp),
.rst_n(reset_n),
// apple one main system
apple1 #(
.BASIC_FILENAME(BASIC_FILENAME),
.FONT_ROM_FILENAME(FONT_ROM_FILENAME),
.RAM_FILENAME(RAM_FILENAME),
.VRAM_FILENAME(VRAM_FILENAME),
.WOZMON_ROM_FILENAME(WOZMON_ROM_FILENAME)
) my_apple1 (
.clk25(clkp),
.rst_n(reset_n),
.uart_rx(usb_rx),
.uart_tx(usb_tx),
.uart_cts(uart_cts),
.uart_rx (usb_rx),
.uart_tx (usb_tx),
.uart_cts(uart_cts),
.ps2_clk(usb_dp[0]),
.ps2_din(usb_dn[0]),
.ps2_select(1'b1), // PS/2 enabled, UART TX disabled
// .ps2_select(1'b0), // PS/2 disabled, UART TX enabled
.ps2_clk(usb_dp[0]),
.ps2_din(usb_dn[0]),
.vga_h_sync(hsync),
.vga_v_sync(vsync),
.vga_red(vga_bit),
.vga_cls(cls),
.vga_de(de)
);
.key_select(2'b10), // PS/2 enabled, UART TX disabled
// .key_select(2'b00), // PS/2 disabled, UART TX enabled
assign usb_pull_dn[0] = 1'b1; // PS/2 emulation mode
assign usb_pull_dp[0] = 1'b1;
.vga_h_sync(hsync),
.vga_v_sync(vsync),
.vga_red(vga_bit),
.vga_cls(cls),
.vga_de(de)
);
// Convert the signal to DVI and send over HDMI
vga2tmds tmds_generator(clkp, clkt, vsync, hsync, de, vga_r, vga_g, vga_b, gpdi_dp);
assign usb_pull_dn[0] = 1'b1; // PS/2 emulation mode
assign usb_pull_dp[0] = 1'b1;
// Convert the signal to DVI and send over HDMI
vga2tmds tmds_generator (
clkp,
clkt,
vsync,
hsync,
de,
vga_r,
vga_g,
vga_b,
gpdi_dp
);
endmodule
+54 -53
View File
@@ -28,78 +28,79 @@ module apple1_top #(
parameter VRAM_FILENAME = "../../../roms/vga_vram.bin",
parameter WOZMON_ROM_FILENAME = "../../../roms/wozmon.hex"
) (
input clk, // 100 MHz board clock
input clk, // 100 MHz board clock
// 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 - not used
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 - not used
// I/O interface to keyboard
input ps2_clk, // PS/2 keyboard serial clock input
input ps2_din, // PS/2 keyboard serial data input
input ps2_clk, // PS/2 keyboard serial clock input
input ps2_din, // PS/2 keyboard serial data input
// Outputs to VGA display
output vga_h_sync, // hozizontal VGA sync pulse
output vga_v_sync, // vertical VGA sync pulse
output vga_h_sync, // hozizontal VGA sync pulse
output vga_v_sync, // vertical VGA sync pulse
output [3:0] vga_r, // red VGA signal
output [3:0] vga_g, // green VGA signal
output [3:0] vga_b, // blue VGA signal
output [3:0] vga_r, // red VGA signal
output [3:0] vga_g, // green VGA signal
output [3:0] vga_b, // blue VGA signal
// Debugging ports
output [1:0] led,
input [1:0] button // 2 buttons on board
input [1:0] button // 2 buttons on board
);
assign led[0] = reset_n;
assign led[1] = clr_screen_n;
assign led[0] = reset_n;
assign led[1] = clr_screen_n;
wire clk25;
// 100MHz down to 25MHz
pll my_pll(
.clock_in(clk),
.clock_out(clk25)
);
wire clk25;
// 100MHz down to 25MHz
pll my_pll (
.clock_in (clk),
.clock_out(clk25)
);
wire vga_bit;
wire vga_bit;
// set the monochrome base colour here..
assign vga_r[3:0] = vga_bit ? 4'b1000 : 4'b0000;
assign vga_g[3:0] = vga_bit ? 4'b1111 : 4'b0000;
assign vga_b[3:0] = vga_bit ? 4'b1000 : 4'b0000;
// set the monochrome base colour here..
assign vga_r[3:0] = vga_bit ? 4'b1000 : 4'b0000;
assign vga_g[3:0] = vga_bit ? 4'b1111 : 4'b0000;
assign vga_b[3:0] = vga_bit ? 4'b1000 : 4'b0000;
wire reset_n;
assign reset_n = ~button[0];
wire reset_n;
assign reset_n = ~button[0];
wire clr_screen_n;
assign clr_screen_n = ~button[1];
wire clr_screen_n;
assign clr_screen_n = ~button[1];
// apple one main system
apple1 #(
.BASIC_FILENAME (BASIC_FILENAME),
.FONT_ROM_FILENAME (FONT_ROM_FILENAME),
.RAM_FILENAME (RAM_FILENAME),
.VRAM_FILENAME (VRAM_FILENAME),
.WOZMON_ROM_FILENAME (WOZMON_ROM_FILENAME)
) my_apple1(
.clk25(clk25),
.rst_n(reset_n),
// apple one main system
apple1 #(
.BASIC_FILENAME(BASIC_FILENAME),
.FONT_ROM_FILENAME(FONT_ROM_FILENAME),
.RAM_FILENAME(RAM_FILENAME),
.VRAM_FILENAME(VRAM_FILENAME),
.WOZMON_ROM_FILENAME(WOZMON_ROM_FILENAME)
) my_apple1 (
.clk25(clk25),
.rst_n(reset_n),
.uart_rx(uart_rx),
.uart_tx(uart_tx),
.uart_cts(uart_cts),
.uart_rx (uart_rx),
.uart_tx (uart_tx),
.uart_cts(uart_cts),
.ps2_clk(ps2_clk),
.ps2_din(ps2_din),
//.ps2_select(1'b1), // PS/2 not working, at the moment
.ps2_select(1'b0), // PS/2 disabled, UART TX enabled
.ps2_clk(ps2_clk),
.ps2_din(ps2_din),
.vga_h_sync(vga_h_sync),
.vga_v_sync(vga_v_sync),
.vga_red(vga_bit),
//.vga_grn(vga_bit),
//.vga_blu(vga_bit),
.vga_cls(~clr_screen_n),
);
// .key_select(2'b10), // PS/2 enabled, UART TX disabled
.key_select(2'b00), // PS/2 disabled, UART TX enabled
.vga_h_sync(vga_h_sync),
.vga_v_sync(vga_v_sync),
.vga_red(vga_bit),
//.vga_grn(vga_bit),
//.vga_blu(vga_bit),
.vga_cls(~clr_screen_n),
);
endmodule
+63 -62
View File
@@ -29,83 +29,84 @@ module apple1_top #(
parameter VRAM_FILENAME = "../../../roms/vga_vram.bin",
parameter WOZMON_ROM_FILENAME = "../../../roms/wozmon.hex"
) (
input clk, // 100 MHz board clock
input clk, // 100 MHz board clock
// 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
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
input ps2_clk, // PS/2 keyboard serial clock input
input ps2_din, // PS/2 keyboard serial data input
// Outputs to VGA display
output vga_h_sync, // hozizontal VGA sync pulse
output vga_v_sync, // vertical VGA sync pulse
output [2:0] vga_r, // red VGA signal
output [2:0] vga_g, // green VGA signal
output [2:0] vga_b, // blue VGA signal
output vga_h_sync, // hozizontal VGA sync pulse
output vga_v_sync, // vertical VGA sync pulse
output [2:0] vga_r, // red VGA signal
output [2:0] vga_g, // green VGA signal
output [2:0] vga_b, // blue VGA signal
input [1:0] button // 2 buttons on board
input [1:0] button // 2 buttons on board
);
wire clk25;
wire clk25;
// 100MHz to 25MHz
pll pll(
.clock_in(clk),
.clock_out(clk25),
);
// 100MHz to 25MHz
pll pll (
.clock_in (clk),
.clock_out(clk25),
);
wire vga_red, vga_green, vga_blue;
assign vga_r[2:0] = {vga_red, vga_red, vga_red};
assign vga_g[2:0] = {vga_green, vga_green, vga_green};
assign vga_b[2:0] = {vga_blue, vga_blue, vga_blue};
wire vga_red, vga_green, vga_blue;
assign vga_r[2:0] = {vga_red, vga_red, vga_red};
assign vga_g[2:0] = {vga_green, vga_green, vga_green};
assign vga_b[2:0] = {vga_blue, vga_blue, vga_blue};
// debounce reset button
wire reset_n;
debounce reset_button (
.clk25(clk25),
.rst(1'b0),
.sig_in(button[0]),
.sig_out(reset_n)
);
// debounce reset button
wire reset_n;
debounce reset_button (
.clk25(clk25),
.rst(1'b0),
.sig_in(button[0]),
.sig_out(reset_n)
);
// debounce clear screen button
wire clr_screen_n;
debounce clr_button (
.clk25(clk25),
.rst(~reset_n),
.sig_in(button[1]),
.sig_out(clr_screen_n)
);
// debounce clear screen button
wire clr_screen_n;
debounce clr_button (
.clk25(clk25),
.rst(~reset_n),
.sig_in(button[1]),
.sig_out(clr_screen_n)
);
// apple one main system
apple1 #(
.BASIC_FILENAME (BASIC_FILENAME),
.FONT_ROM_FILENAME (FONT_ROM_FILENAME),
.RAM_FILENAME (RAM_FILENAME),
.VRAM_FILENAME (VRAM_FILENAME),
.WOZMON_ROM_FILENAME (WOZMON_ROM_FILENAME)
) my_apple1(
.clk25(clk25),
.rst_n(reset_n),
// apple one main system
apple1 #(
.BASIC_FILENAME(BASIC_FILENAME),
.FONT_ROM_FILENAME(FONT_ROM_FILENAME),
.RAM_FILENAME(RAM_FILENAME),
.VRAM_FILENAME(VRAM_FILENAME),
.WOZMON_ROM_FILENAME(WOZMON_ROM_FILENAME)
) my_apple1 (
.clk25(clk25),
.rst_n(reset_n),
.uart_rx(uart_rx),
.uart_tx(uart_tx),
.uart_cts(uart_cts),
.uart_rx (uart_rx),
.uart_tx (uart_tx),
.uart_cts(uart_cts),
.ps2_clk(ps2_clk),
.ps2_din(ps2_din),
.ps2_select(1'b1), // PS/2 enabled, UART TX disabled
//.ps2_select(1'b0), // PS/2 disabled, UART TX enabled
.ps2_clk(ps2_clk),
.ps2_din(ps2_din),
.vga_h_sync(vga_h_sync),
.vga_v_sync(vga_v_sync),
.vga_red(vga_red),
.vga_grn(vga_green),
.vga_blu(vga_blue),
.vga_cls(~clr_screen_n),
);
.key_select(2'b10), // PS/2 enabled, UART TX disabled
// .key_select(2'b00), // PS/2 disabled, UART TX enabled
.vga_h_sync(vga_h_sync),
.vga_v_sync(vga_v_sync),
.vga_red(vga_red),
.vga_grn(vga_green),
.vga_blu(vga_blue),
.vga_cls(~clr_screen_n),
);
endmodule
@@ -20,7 +20,7 @@
//
// Author.....: Niels A. Moseley
// Date.......: 11-2-2018
//
//
module apple1_s3e_starterkit_top #(
@@ -29,64 +29,63 @@ module apple1_s3e_starterkit_top #(
parameter RAM_FILENAME = "../../../roms/ram.hex",
parameter VRAM_FILENAME = "../../../roms/vga_vram.bin",
parameter WOZMON_ROM_FILENAME = "../../../roms/wozmon.hex"
) (
input CLK_50MHZ, // the 50 MHz master clock
) (
input CLK_50MHZ, // the 50 MHz master clock
// UART I/O signals
output UART_TXD, // UART transmit pin on board
input UART_RXD, // UART receive pin on board
input PS2_KBCLK,
input PS2_KBDAT,
output UART_TXD, // UART transmit pin on board
input UART_RXD, // UART receive pin on board
input BUTTON, // Button for RESET
input SWITCH, // Switch between PS/2 input and UART
input PS2_KBCLK,
input PS2_KBDAT,
output VGA_R,
output VGA_G,
output VGA_B,
output VGA_HS,
output VGA_VS
input BUTTON, // Button for RESET
input SWITCH, // Switch between PS/2 input and UART
output VGA_R,
output VGA_G,
output VGA_B,
output VGA_HS,
output VGA_VS
);
//////////////////////////////////////////////////////////////////////////
// Registers and Wires
reg clk25;
wire [15:0] pc_monitor;
//////////////////////////////////////////////////////////////////////////
// Registers and Wires
reg clk25;
wire [15:0] pc_monitor;
wire rst_n;
assign rst_n = ~BUTTON;
wire rst_n;
assign rst_n = ~BUTTON;
// generate 25MHz clock from 50MHz master clock
always @(posedge CLK_50MHZ) begin
clk25 <= ~clk25;
end
//////////////////////////////////////////////////////////////////////////
// Core of system
apple1 #(
.BASIC_FILENAME(BASIC_FILENAME),
.FONT_ROM_FILENAME(FONT_ROM_FILENAME),
.RAM_FILENAME(RAM_FILENAME),
.VRAM_FILENAME(VRAM_FILENAME),
.WOZMON_ROM_FILENAME(WOZMON_ROM_FILENAME)
) apple1_top (
.clk25 (clk25),
.rst_n (rst_n), // we don't have any reset pulse..
.uart_rx (UART_RXD),
.uart_tx (UART_TXD),
//.uart_cts(UART_CTS), // there is no CTS on the board :(
.ps2_clk (PS2_KBCLK),
.ps2_din (PS2_KBDAT),
.key_select(SWITCH ? 2'b10 : 2'b00), // PS/2 or UART with switch
.vga_h_sync(VGA_HS),
.vga_v_sync(VGA_VS),
.vga_red (VGA_R),
.vga_grn (VGA_G),
.vga_blu (VGA_B),
.vga_cls (~rst_n),
.pc_monitor(pc_monitor)
);
// generate 25MHz clock from 50MHz master clock
always @(posedge CLK_50MHZ)
begin
clk25 <= ~clk25;
end
//////////////////////////////////////////////////////////////////////////
// Core of system
apple1 #(
.BASIC_FILENAME (BASIC_FILENAME),
.FONT_ROM_FILENAME (FONT_ROM_FILENAME),
.RAM_FILENAME (RAM_FILENAME),
.VRAM_FILENAME (VRAM_FILENAME),
.WOZMON_ROM_FILENAME (WOZMON_ROM_FILENAME)
) apple1_top(
.clk25(clk25),
.rst_n(rst_n), // we don't have any reset pulse..
.uart_rx(UART_RXD),
.uart_tx(UART_TXD),
//.uart_cts(UART_CTS), // there is no CTS on the board :(
.ps2_clk(PS2_KBCLK),
.ps2_din(PS2_KBDAT),
.ps2_select(SWITCH),
.vga_h_sync(VGA_HS),
.vga_v_sync(VGA_VS),
.vga_red(VGA_R),
.vga_grn(VGA_G),
.vga_blu(VGA_B),
.vga_cls(~rst_n),
.pc_monitor(pc_monitor)
);
endmodule
+38
View File
@@ -0,0 +1,38 @@
IO_LOC "clk" E2;
IO_PORT "clk" IO_TYPE=LVCMOS33 PULL_MODE=NONE BANK_VCCIO=3.3;
IO_LOC "rst" H11;
IO_PORT "rst" IO_TYPE=LVCMOS33 PULL_MODE=DOWN BANK_VCCIO=3.3;
// UART
IO_LOC "uart_tx" C3;
IO_PORT "uart_tx" IO_TYPE=LVCMOS33 PULL_MODE=NONE DRIVE=8 BANK_VCCIO=3.3;
IO_LOC "uart_rx" B3;
IO_PORT "uart_rx" IO_TYPE=LVCMOS33 PULL_MODE=NONE BANK_VCCIO=3.3;
// USB port
IO_LOC "usb_dp" L6; // D+
IO_PORT "usb_dp" PULL_MODE=NONE IO_TYPE=LVCMOS33;
IO_LOC "usb_dm" K6; // D-
IO_PORT "usb_dm" PULL_MODE=NONE IO_TYPE=LVCMOS33;
IO_LOC "usb_led_act" D7; // USB activity LED
IO_PORT "usb_led_act" IO_TYPE=LVCMOS33 PULL_MODE=NONE DRIVE=8;
IO_LOC "usb_led_err" E8; // USB connection error LED
IO_PORT "usb_led_err" IO_TYPE=LVCMOS33 PULL_MODE=NONE DRIVE=8;
// VGA
IO_LOC "vga_red" C10;
IO_PORT "vga_red" IO_TYPE=LVCMOS33 PULL_MODE=NONE DRIVE=8;
IO_LOC "vga_grn" B10;
IO_PORT "vga_grn" IO_TYPE=LVCMOS33 PULL_MODE=NONE DRIVE=8;
IO_LOC "vga_blu" D10;
IO_PORT "vga_blu" IO_TYPE=LVCMOS33 PULL_MODE=NONE DRIVE=8;
IO_LOC "vga_h_sync" C11;
IO_PORT "vga_h_sync" IO_TYPE=LVCMOS33 PULL_MODE=NONE DRIVE=8;
IO_LOC "vga_v_sync" B11;
IO_PORT "vga_v_sync" IO_TYPE=LVCMOS33 PULL_MODE=NONE DRIVE=8;
IO_LOC "vga_de" D11;
IO_PORT "vga_de" IO_TYPE=LVCMOS33 PULL_MODE=NONE DRIVE=8;
IO_LOC "vga_cls" H10;
IO_PORT "vga_cls" IO_TYPE=LVCMOS33 PULL_MODE=DOWN BANK_VCCIO=3.3;
+1
View File
@@ -0,0 +1 @@
create_clock -name {clk} -period 20 [get_ports {clk}]
+100
View File
@@ -0,0 +1,100 @@
// 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 implementation for the Tang Primer 25k
//
// Author.....: Alan Garfield
// Date.......: 20/09/2025
//
module apple1_primer #(
parameter string BASIC_FILENAME = "../../../roms/basic.hex",
parameter string FONT_ROM_FILENAME = "../../../roms/vga_font_bitreversed.hex",
parameter string RAM_FILENAME = "../../../roms/ram.hex",
parameter string VRAM_FILENAME = "../../../roms/vga_vram.bin",
parameter string WOZMON_ROM_FILENAME = "../../../roms/wozmon.hex"
) (
input clk,
input rst,
input uart_rx,
output uart_tx,
inout usb_dm,
inout usb_dp,
output usb_led_err,
output usb_led_act,
output vga_h_sync,
output vga_v_sync,
output vga_red,
output vga_grn,
output vga_blu,
input vga_cls,
output vga_de
);
//////////////////////////////////////////////////////////////////////////
// Registers and Wires
wire uart_cts; // No CTS pin
wire clk25;
wire usb_clk;
Gowin_PLL your_instance_name (
.clkin (clk),
.clkout0(clk25),
.clkout1(usb_clk),
.mdclk (1'd0)
);
apple1 #(
.BASIC_FILENAME(BASIC_FILENAME),
.FONT_ROM_FILENAME(FONT_ROM_FILENAME),
.RAM_FILENAME(RAM_FILENAME),
.VRAM_FILENAME(VRAM_FILENAME),
.WOZMON_ROM_FILENAME(WOZMON_ROM_FILENAME)
) my_apple1 (
.clk25(clk25),
.rst_n(!rst),
.uart_rx (uart_rx),
.uart_tx (uart_tx),
.uart_cts(uart_cts),
.key_select(2'b00), // USB keyboard selected
.ps2_clk(1'b0),
.ps2_din(1'b0),
.usb_clk(usb_clk),
.usb_dm(usb_dm),
.usb_dp(usb_dp),
.usb_led_err(usb_led_err),
.usb_led_act(usb_led_act),
.vga_h_sync(vga_h_sync),
.vga_v_sync(vga_v_sync),
.vga_red(vga_red),
.vga_grn(vga_grn),
.vga_blu(vga_blu),
.vga_cls(vga_cls),
.vga_de(vga_de),
.pc_monitor()
);
endmodule
@@ -0,0 +1,57 @@
module Gowin_PLL(
clkin,
clkout0,
clkout1,
mdclk
);
input clkin;
output clkout0;
output clkout1;
input mdclk;
wire [7:0] mdrdo;
wire lock;
wire [1:0] wMdOpc;
wire wMdAInc;
wire [7:0] wMdDIn;
wire [7:0] wMdQOut;
wire pll_lock;
wire pll_rst;
Gowin_PLL_MOD u_pll(
.clkout1(clkout1),
.clkout0(clkout0),
.lock(pll_lock),
.mdrdo(wMdQOut),
.clkin(clkin),
.reset(pll_rst),
.mdclk(mdclk),
.mdopc(wMdOpc),
.mdainc(wMdAInc),
.mdwdi(wMdDIn)
);
PLL_INIT u_pll_init(
.I_RST(1'b0),
.O_RST(pll_rst),
.I_LOCK(pll_lock),
.O_LOCK(lock),
.I_MD_CLK(mdclk),
.O_MD_INC(wMdAInc),
.O_MD_OPC(wMdOpc),
.O_MD_WR_DATA(wMdDIn),
.I_MD_RD_DATA(wMdQOut),
.PLL_INIT_BYPASS(1'b0),
.MDRDO(mdrdo),
.MDOPC(2'b00),
.MDAINC(1'b0),
.MDWDI(8'h0)
);
defparam u_pll_init.CLK_PERIOD = 20;
defparam u_pll_init.MULTI_FAC = 18;
endmodule
@@ -0,0 +1,142 @@
//Copyright (C)2014-2025 Gowin Semiconductor Corporation.
//All rights reserved.
//File Title: IP file
//Tool Version: V1.9.12
//Part Number: GW5A-LV25MG121NES
//Device: GW5A-25
//Device Version: A
//Created Time: Sat Sep 20 23:20:21 2025
module Gowin_PLL_MOD (lock, clkout0, clkout1, mdrdo, clkin, reset, mdclk, mdopc, mdainc, mdwdi);
output lock;
output clkout0;
output clkout1;
output [7:0] mdrdo;
input clkin;
input reset;
input mdclk;
input [1:0] mdopc;
input mdainc;
input [7:0] mdwdi;
wire clkout2;
wire clkout3;
wire clkout4;
wire clkout5;
wire clkout6;
wire clkfbout;
wire gw_gnd;
assign gw_gnd = 1'b0;
PLLA PLLA_inst (
.LOCK(lock),
.CLKOUT0(clkout0),
.CLKOUT1(clkout1),
.CLKOUT2(clkout2),
.CLKOUT3(clkout3),
.CLKOUT4(clkout4),
.CLKOUT5(clkout5),
.CLKOUT6(clkout6),
.CLKFBOUT(clkfbout),
.MDRDO(mdrdo),
.CLKIN(clkin),
.CLKFB(gw_gnd),
.RESET(reset),
.PLLPWD(gw_gnd),
.RESET_I(gw_gnd),
.RESET_O(gw_gnd),
.PSSEL({gw_gnd,gw_gnd,gw_gnd}),
.PSDIR(gw_gnd),
.PSPULSE(gw_gnd),
.SSCPOL(gw_gnd),
.SSCON(gw_gnd),
.SSCMDSEL({gw_gnd,gw_gnd,gw_gnd,gw_gnd,gw_gnd,gw_gnd,gw_gnd}),
.SSCMDSEL_FRAC({gw_gnd,gw_gnd,gw_gnd}),
.MDCLK(mdclk),
.MDOPC(mdopc),
.MDAINC(mdainc),
.MDWDI(mdwdi)
);
defparam PLLA_inst.FCLKIN = "50";
defparam PLLA_inst.IDIV_SEL = 1;
defparam PLLA_inst.FBDIV_SEL = 1;
defparam PLLA_inst.ODIV0_SEL = 36;
defparam PLLA_inst.ODIV1_SEL = 75;
defparam PLLA_inst.ODIV2_SEL = 8;
defparam PLLA_inst.ODIV3_SEL = 8;
defparam PLLA_inst.ODIV4_SEL = 8;
defparam PLLA_inst.ODIV5_SEL = 8;
defparam PLLA_inst.ODIV6_SEL = 8;
defparam PLLA_inst.MDIV_SEL = 18;
defparam PLLA_inst.MDIV_FRAC_SEL = 0;
defparam PLLA_inst.ODIV0_FRAC_SEL = 0;
defparam PLLA_inst.CLKOUT0_EN = "TRUE";
defparam PLLA_inst.CLKOUT1_EN = "TRUE";
defparam PLLA_inst.CLKOUT2_EN = "FALSE";
defparam PLLA_inst.CLKOUT3_EN = "FALSE";
defparam PLLA_inst.CLKOUT4_EN = "FALSE";
defparam PLLA_inst.CLKOUT5_EN = "FALSE";
defparam PLLA_inst.CLKOUT6_EN = "FALSE";
defparam PLLA_inst.CLKFB_SEL = "INTERNAL";
defparam PLLA_inst.CLKOUT0_DT_DIR = 1'b1;
defparam PLLA_inst.CLKOUT1_DT_DIR = 1'b1;
defparam PLLA_inst.CLKOUT2_DT_DIR = 1'b1;
defparam PLLA_inst.CLKOUT3_DT_DIR = 1'b1;
defparam PLLA_inst.CLKOUT0_DT_STEP = 0;
defparam PLLA_inst.CLKOUT1_DT_STEP = 0;
defparam PLLA_inst.CLKOUT2_DT_STEP = 0;
defparam PLLA_inst.CLKOUT3_DT_STEP = 0;
defparam PLLA_inst.CLK0_IN_SEL = 1'b0;
defparam PLLA_inst.CLK0_OUT_SEL = 1'b0;
defparam PLLA_inst.CLK1_IN_SEL = 1'b0;
defparam PLLA_inst.CLK1_OUT_SEL = 1'b0;
defparam PLLA_inst.CLK2_IN_SEL = 1'b0;
defparam PLLA_inst.CLK2_OUT_SEL = 1'b0;
defparam PLLA_inst.CLK3_IN_SEL = 1'b0;
defparam PLLA_inst.CLK3_OUT_SEL = 1'b0;
defparam PLLA_inst.CLK4_IN_SEL = 2'b00;
defparam PLLA_inst.CLK4_OUT_SEL = 1'b0;
defparam PLLA_inst.CLK5_IN_SEL = 1'b0;
defparam PLLA_inst.CLK5_OUT_SEL = 1'b0;
defparam PLLA_inst.CLK6_IN_SEL = 1'b0;
defparam PLLA_inst.CLK6_OUT_SEL = 1'b0;
defparam PLLA_inst.DYN_DPA_EN = "FALSE";
defparam PLLA_inst.CLKOUT0_PE_COARSE = 0;
defparam PLLA_inst.CLKOUT0_PE_FINE = 0;
defparam PLLA_inst.CLKOUT1_PE_COARSE = 0;
defparam PLLA_inst.CLKOUT1_PE_FINE = 0;
defparam PLLA_inst.CLKOUT2_PE_COARSE = 0;
defparam PLLA_inst.CLKOUT2_PE_FINE = 0;
defparam PLLA_inst.CLKOUT3_PE_COARSE = 0;
defparam PLLA_inst.CLKOUT3_PE_FINE = 0;
defparam PLLA_inst.CLKOUT4_PE_COARSE = 0;
defparam PLLA_inst.CLKOUT4_PE_FINE = 0;
defparam PLLA_inst.CLKOUT5_PE_COARSE = 0;
defparam PLLA_inst.CLKOUT5_PE_FINE = 0;
defparam PLLA_inst.CLKOUT6_PE_COARSE = 0;
defparam PLLA_inst.CLKOUT6_PE_FINE = 0;
defparam PLLA_inst.DYN_PE0_SEL = "FALSE";
defparam PLLA_inst.DYN_PE1_SEL = "FALSE";
defparam PLLA_inst.DYN_PE2_SEL = "FALSE";
defparam PLLA_inst.DYN_PE3_SEL = "FALSE";
defparam PLLA_inst.DYN_PE4_SEL = "FALSE";
defparam PLLA_inst.DYN_PE5_SEL = "FALSE";
defparam PLLA_inst.DYN_PE6_SEL = "FALSE";
defparam PLLA_inst.DE0_EN = "FALSE";
defparam PLLA_inst.DE1_EN = "FALSE";
defparam PLLA_inst.DE2_EN = "FALSE";
defparam PLLA_inst.DE3_EN = "FALSE";
defparam PLLA_inst.DE4_EN = "FALSE";
defparam PLLA_inst.DE5_EN = "FALSE";
defparam PLLA_inst.DE6_EN = "FALSE";
defparam PLLA_inst.RESET_I_EN = "FALSE";
defparam PLLA_inst.RESET_O_EN = "FALSE";
defparam PLLA_inst.ICP_SEL = 6'bXXXXXX;
defparam PLLA_inst.LPF_RES = 3'bXXX;
defparam PLLA_inst.LPF_CAP = 2'b00;
defparam PLLA_inst.SSC_EN = "FALSE";
endmodule //Gowin_PLL_MOD
+398
View File
@@ -0,0 +1,398 @@
`timescale 1ns/1ns
module PLL_INIT #
( parameter CLK_PERIOD = 20
, parameter MULTI_FAC = 24
)
( input I_RST
, input I_MD_CLK
, output O_RST
, output O_MD_INC
, output [1:0] O_MD_OPC
, output [7:0] O_MD_WR_DATA
, input [7:0] I_MD_RD_DATA
, input I_LOCK
, output O_LOCK
, input PLL_INIT_BYPASS
, output [7:0] MDRDO
, input [1:0] MDOPC
, input MDAINC
, input [7:0] MDWDI
);
`ifdef SIM
`define DL #1
`else
`define DL
`endif
`ifdef SIM
localparam WAIT_TIME = 'd8_000;
localparam LOCK_TIME = 'd2_000;
`else
localparam WAIT_TIME = 'd800_000;
localparam LOCK_TIME = 'd200_000;
`endif
localparam WAIT_CNT = (WAIT_TIME + CLK_PERIOD - 1) / CLK_PERIOD; //! 1ms
localparam LOCK_CNT = (LOCK_TIME + CLK_PERIOD - 1) / CLK_PERIOD;
localparam WW = $clog2(WAIT_CNT + 1);
localparam LW = $clog2(LOCK_CNT + 1);
localparam INIT_STEP_0 = 4'd0
, INIT_STEP_1 = 4'd1
, INIT_STEP_2 = 4'd2
, INIT_STEP_3 = 4'd3
, INIT_STEP_4 = 4'd4
, INIT_STEP_5 = 4'd5
, INIT_STEP_6 = 4'd6
, INIT_STEP_7 = 4'd7
, INIT_STEP_8 = 4'd8
, INIT_STEP_9 = 4'd9
;
reg [ 1:0] rEnable = 'b0;
reg rRomRd = 'b0;
reg [ 7:0] rRomAddr = 'b0;
reg [ 24:0] rRomData = 'b0;
reg [ 2:0] rReqCnt = 'b0;
reg [ 4:0] rLoopCnt = 'b0;
reg [ 3:0] rChkOkCnt = 'b0;
reg [ 5:0] rChkStart = 'b0;
reg [ 3:0] rInitFsmC = INIT_STEP_0 ;
reg [ 3:0] rInitFsmN = INIT_STEP_1 ;
reg [ 7:0] rMdAddr = 'b0;
reg rMdInc = 'b0;
reg [ 1:0] rMdOpc = 'b0;
reg [ 7:0] rMdDOut = 'b0;
reg [ 7:0] rChkFlag = 'b0;
reg rLockReg = 'b0;
reg [LW-1:0] rLockCnt = 'b0;
reg rLocked = 'b0;
reg [WW-1:0] rWaitCnt = 'b0;
reg rLastStep = 'b0;
reg rLockOut = 'b0;
reg rChkVld = 'b0;
reg [ 7:0] rRomAddrVld = 'b0;
reg rRstOut = 1'b1;
wire wEnable = rEnable[1];
wire [ 7:0] wMdAddrNext = rMdAddr + 2'd1;
wire wLocked = (rLockCnt >= LOCK_CNT);
wire wIsStep0 = (rInitFsmC == INIT_STEP_0);
wire wIsStep1 = (rInitFsmC == INIT_STEP_1);
wire wIsStep2 = (rInitFsmC == INIT_STEP_2);
wire wIsStep3 = (rInitFsmC == INIT_STEP_3);
wire wIsStep4 = (rInitFsmC == INIT_STEP_4);
wire wIsStep5 = (rInitFsmC == INIT_STEP_5);
wire wIsStep6 = (rInitFsmC == INIT_STEP_6);
wire wIsStep7 = (rInitFsmC == INIT_STEP_7);
wire wIsStep8 = (rInitFsmC == INIT_STEP_8);
wire wIsStep9 = (rInitFsmC == INIT_STEP_9);
wire wReqOver = ~rRomData[24];
wire wMdrpReq = rRomData[24];
wire wWaitLock = rReqCnt[2];//(rReqCnt == 4);
wire [ 7:0] wReqAddr = rRomData[16+:8];
wire [ 7:0] wReqMask = rRomData[ 8+:8];
wire [ 7:0] wReqData = rRomData[ 0+:8];
localparam ROM_FILE = "";
reg [ 27:0] rRomDReg = 'b0;
reg [27:0] rRom [63:0];
always @ (posedge PLL_INIT_BYPASS or posedge I_MD_CLK or posedge I_RST) begin
if (PLL_INIT_BYPASS || I_RST) rEnable <=`DL 2'b00;
else rEnable <=`DL {rEnable[0], 1'b1};
end
generate
if (ROM_FILE != "") begin: ram_init_file
initial begin
$readmemh (ROM_FILE, rRom);
end
always @ (posedge I_MD_CLK) begin
rRomDReg <=`DL rRom[rRomAddr[5:0]];
end
end else begin : ram_init
always @ (posedge I_MD_CLK) begin
if (~rEnable[1]) begin
rRomDReg <=`DL 28'h000_0000;
//1
rRom[00] <=`DL (MULTI_FAC > 34) ? 28'h10B_3F03
: (MULTI_FAC > 16) ? 28'h10B_3F01
: 28'h10B_3F00;
rRom[01] <=`DL 28'h10C_E080;
rRom[02] <=`DL 28'h111_0701;
rRom[03] <=`DL 28'h112_0C08;
//2
rRom[04] <=`DL (MULTI_FAC > 34) ? 28'h10B_3F03
: (MULTI_FAC > 16) ? 28'h10B_3F01
: 28'h10B_3F00;
rRom[05] <=`DL 28'h10C_E080;
rRom[06] <=`DL 28'h111_0703;
rRom[07] <=`DL 28'h112_0C08;
//3
rRom[08] <=`DL (MULTI_FAC > 34) ? 28'h10B_3F03
: (MULTI_FAC > 16) ? 28'h10B_3F01
: 28'h10B_3F00;
rRom[09] <=`DL 28'h10C_E0A0;
rRom[10] <=`DL 28'h111_0703;
rRom[11] <=`DL 28'h112_0C08;
//4
rRom[12] <=`DL (MULTI_FAC > 34) ? 28'h10B_3F03
: (MULTI_FAC > 16) ? 28'h10B_3F01
: 28'h10B_3F00;
rRom[13] <=`DL 28'h10C_E0A0;
rRom[14] <=`DL 28'h111_0707;
rRom[15] <=`DL 28'h112_0C08;
//5
rRom[16] <=`DL (MULTI_FAC > 34) ? 28'h10B_3F07
: (MULTI_FAC > 16) ? 28'h10B_3F03
: 28'h10B_3F01;
rRom[17] <=`DL 28'h10C_E0A0;
rRom[18] <=`DL 28'h111_0707;
rRom[19] <=`DL 28'h112_0C08;
//6
rRom[20] <=`DL (MULTI_FAC > 34) ? 28'h10B_3F05
: (MULTI_FAC > 16) ? 28'h10B_3F02
: 28'h10B_3F01;
rRom[21] <=`DL 28'h10C_E0C0;
rRom[22] <=`DL 28'h111_0707;
rRom[23] <=`DL 28'h112_0C08;
//over
rRom[24] <=`DL 28'h000_0000;
rRom[25] <=`DL 28'h000_0000;
rRom[26] <=`DL 28'h000_0000;
rRom[27] <=`DL 28'h000_0000;
//1.5
rRom[28] <=`DL (MULTI_FAC > 34) ? 28'h10B3F03
: (MULTI_FAC > 16) ? 28'h10B3F01
: 28'h10B3F00;
rRom[29] <=`DL 28'h10CE080;
rRom[30] <=`DL 28'h1110702;
rRom[31] <=`DL 28'h1120C08;
//2.5
rRom[32] <=`DL (MULTI_FAC > 34) ? 28'h10B3F05
: (MULTI_FAC > 16) ? 28'h10B3F02
: 28'h10B3F00;
rRom[33] <=`DL 28'h10CE080;
rRom[34] <=`DL 28'h1110703;
rRom[35] <=`DL 28'h1120C08;
//3.5
rRom[36] <=`DL (MULTI_FAC > 34) ? 28'h10B3F03
: (MULTI_FAC > 16) ? 28'h10B3F01
: 28'h10B3F00;
rRom[37] <=`DL 28'h10CE0A0;
rRom[38] <=`DL 28'h1110704;
rRom[39] <=`DL 28'h112_0C08;
//4.5
rRom[40] <=`DL (MULTI_FAC > 34) ? 28'h10B3F04
: (MULTI_FAC > 16) ? 28'h10B3F02
: 28'h10B3F00;
rRom[41] <=`DL 28'h10CE0A0;
rRom[42] <=`DL 28'h1110707;
rRom[43] <=`DL 28'h1120C08;
//5.5
rRom[44] <=`DL (MULTI_FAC > 34) ? 28'h10B3F03
: (MULTI_FAC > 16) ? 28'h10B3F01
: 28'h10B3F00;
rRom[45] <=`DL 28'h10CE0C0;
rRom[46] <=`DL 28'h1110707;
rRom[47] <=`DL 28'h1120C08;
rRom[48] <=`DL 28'h000_0000;
rRom[49] <=`DL 28'h000_0000;
rRom[50] <=`DL 28'h000_0000;
rRom[51] <=`DL 28'h000_0000;
rRom[52] <=`DL 28'h000_0000;
rRom[53] <=`DL 28'h000_0000;
rRom[54] <=`DL 28'h000_0000;
rRom[55] <=`DL 28'h000_0000;
rRom[56] <=`DL 28'h000_0000;
rRom[57] <=`DL 28'h000_0000;
rRom[58] <=`DL 28'h000_0000;
rRom[59] <=`DL 28'h000_0000;
rRom[60] <=`DL 28'h000_0000;
rRom[61] <=`DL 28'h000_0000;
rRom[62] <=`DL 28'h000_0000;
rRom[63] <=`DL 28'h000_0000;
end else
rRomDReg <=`DL rRom[rRomAddr[5:0]];
end
end
endgenerate
always @ (*) begin
casex (rChkFlag[5:0])
6'b111_111 : {rChkVld, rRomAddrVld} = 9'b1_0000_1000;
6'b011_111 : {rChkVld, rRomAddrVld} = 9'b1_0000_1000;
6'b111_110 : {rChkVld, rRomAddrVld} = 9'b1_0000_1100;
6'b111_10x : {rChkVld, rRomAddrVld} = 9'b1_0000_1100;
6'bx01_111 : {rChkVld, rRomAddrVld} = 9'b1_0000_0100;
6'b011_110 : {rChkVld, rRomAddrVld} = 9'b1_0000_1000;
6'bxx0_111 : {rChkVld, rRomAddrVld} = 9'b1_0000_0100;
6'bx01_110 : {rChkVld, rRomAddrVld} = 9'b1_0000_1000;
6'b011_10x : {rChkVld, rRomAddrVld} = 9'b1_0000_1100;
6'b111_0xx : {rChkVld, rRomAddrVld} = 9'b1_0001_0000;
6'bxxx_011 : {rChkVld, rRomAddrVld} = 9'b1_0001_1100;
6'bxx0_110 : {rChkVld, rRomAddrVld} = 9'b1_0010_0000;
6'bx01_100 : {rChkVld, rRomAddrVld} = 9'b1_0010_0100;
6'b011_000 : {rChkVld, rRomAddrVld} = 9'b1_0010_1000;
6'b110_000 : {rChkVld, rRomAddrVld} = 9'b1_0010_1100;
6'bxxx_x01 : {rChkVld, rRomAddrVld} = 9'b1_0000_0000;
6'bxxx_010 : {rChkVld, rRomAddrVld} = 9'b1_0000_0100;
6'bxx0_100 : {rChkVld, rRomAddrVld} = 9'b1_0000_1000;
6'bx01_000 : {rChkVld, rRomAddrVld} = 9'b1_0000_1100;
6'b010_000 : {rChkVld, rRomAddrVld} = 9'b1_0001_0000;
6'b100_000 : {rChkVld, rRomAddrVld} = 9'b1_0001_0100;
6'b000_000 : {rChkVld, rRomAddrVld} = 9'b0_0000_0000;
default : {rChkVld, rRomAddrVld} = 9'b0_0000_0000;
endcase
end
always @ (posedge I_MD_CLK) begin
rInitFsmC <=`DL wEnable ? rInitFsmN : INIT_STEP_0;
//!_____________________________________________________________________________
rRomRd <=`DL wEnable & (wIsStep1 | wIsStep6 & ~wWaitLock);
//!_____________________________________________________________________________
rRomData <=`DL rRomRd ? rRomDReg[24:0] : rRomData;
//!_____________________________________________________________________________
rRomAddr <=`DL ~wEnable ? 8'd0
: (wIsStep3 & wReqOver) ? rRomAddrVld
: rRomRd ? rRomAddr + 1'd1
: rRomAddr;
//!_____________________________________________________________________________
rLastStep <=`DL wEnable & (wIsStep3 & wReqOver | rLastStep);
//!_____________________________________________________________________________
rReqCnt <=`DL ~wEnable ? 3'd0
: wIsStep7 ? 3'd0
: wIsStep5 ? rReqCnt + 1'd1
: rReqCnt;
//!_____________________________________________________________________________
rLoopCnt <=`DL ~wEnable ? 3'd0
: wIsStep8 ? rLoopCnt + 1'd1
: rLoopCnt;
//!_____________________________________________________________________________
rLockReg <=`DL wEnable & I_LOCK;
//!_____________________________________________________________________________
rLockCnt <=`DL (~wEnable) ? {LW{1'b0}}
: (~wIsStep7&~wIsStep9) ? {LW{1'b0}}
: (~rLockReg) ? {LW{1'b0}}
: (rLockCnt<LOCK_CNT) ? rLockCnt + 1'd1
: rLockCnt;
//!_____________________________________________________________________________
rLocked <=`DL wLocked;
//!_____________________________________________________________________________
rWaitCnt <=`DL wIsStep3 ? WAIT_CNT[0+:WW]
: ~wIsStep7 ? rWaitCnt
: (|rWaitCnt) ? rWaitCnt - 1'd1
: {WW{1'b0}};
//!_____________________________________________________________________________
if (~wEnable) rChkFlag <=`DL 8'h00;
else if (wIsStep7 & rLocked) rChkFlag[rLoopCnt[2:0]] <=`DL 1'b1;
//!_____________________________________________________________________________
rChkOkCnt <=`DL ~wEnable ? 4'd0
: ~wIsStep7 ? rChkOkCnt
: (rWaitCnt==0) ? 4'd0
: rLocked ? rChkOkCnt + 1'd1
: rChkOkCnt;
end
always @(*) begin
if (~wEnable) rInitFsmN =`DL INIT_STEP_1;
else case (rInitFsmC) /* synthesis full_case */
INIT_STEP_0 : rInitFsmN =`DL INIT_STEP_1;
INIT_STEP_1 : rInitFsmN =`DL INIT_STEP_2;
INIT_STEP_2 : rInitFsmN =`DL INIT_STEP_3;
INIT_STEP_3 : rInitFsmN =`DL wWaitLock ? INIT_STEP_7
: wReqOver & rLastStep ? INIT_STEP_9
: wReqOver &~rLastStep ? INIT_STEP_1
: (rMdAddr >= wReqAddr) ? INIT_STEP_4
: INIT_STEP_3;
INIT_STEP_4 : rInitFsmN =`DL INIT_STEP_5;
INIT_STEP_5 : rInitFsmN =`DL INIT_STEP_6;
INIT_STEP_6 : rInitFsmN =`DL INIT_STEP_2;
INIT_STEP_7 : rInitFsmN =`DL (rWaitCnt==0) ? INIT_STEP_8
: ~rLocked ? INIT_STEP_7
: rLastStep ? INIT_STEP_9
: INIT_STEP_8;
INIT_STEP_8 : rInitFsmN =`DL ~rLastStep ? INIT_STEP_1
: rChkVld ? INIT_STEP_1
: INIT_STEP_9;
INIT_STEP_9 : rInitFsmN =`DL INIT_STEP_9;
default : rInitFsmN =`DL INIT_STEP_9;
endcase
end
always @ (posedge I_MD_CLK) begin
rMdOpc <=`DL ~wEnable ? 2'b00
: wIsStep7 ? 2'b00
: wIsStep5 ? 2'b01
: 2'b10;
//!_____________________________________________________________________________
rMdInc <=`DL wIsStep3 & (~rMdInc ? (rMdAddr<wReqAddr)
: (wMdAddrNext < wReqAddr));
//!_____________________________________________________________________________
rMdAddr <=`DL ~wEnable ? 8'd0
: wIsStep7 ? 8'd0
: rMdInc ? wMdAddrNext
: rMdAddr;
//!_____________________________________________________________________________
rMdDOut <=`DL wIsStep5 ? (I_MD_RD_DATA&~wReqMask|wReqData) : rMdDOut;
//!_____________________________________________________________________________
rRstOut <=`DL ~wEnable | (~wIsStep7 & ~wIsStep9);
//!_____________________________________________________________________________
rLockOut <=`DL rLocked & wIsStep9 & rChkVld;
end
/////////////mdrp switch//////////////////////////
assign O_LOCK = (PLL_INIT_BYPASS == 1'b1) ? I_LOCK : rLockOut;
assign O_RST = (PLL_INIT_BYPASS == 1'b1) ? I_RST : rRstOut;
assign O_MD_INC = (PLL_INIT_BYPASS == 1'b1) ? MDAINC : rMdInc;
assign O_MD_OPC = (PLL_INIT_BYPASS == 1'b1) ? MDOPC : rMdOpc;
assign O_MD_WR_DATA= (PLL_INIT_BYPASS == 1'b1) ? MDWDI : rMdDOut;
assign MDRDO = (PLL_INIT_BYPASS == 1'b1) ? I_MD_RD_DATA : 8'b0000_0000;
/////////////////////////////////////
endmodule//: PLL_INIT
+82 -82
View File
@@ -29,104 +29,104 @@ module apple1_de0_top #(
parameter VRAM_FILENAME = "../../../roms/vga_vram.bin",
parameter WOZMON_ROM_FILENAME = "../../../roms/wozmon.hex"
) (
input CLOCK_50, // the 50 MHz DE0 master clock
input CLOCK_50, // the 50 MHz DE0 master clock
// UART I/O signals
output UART_TXD, // UART transmit pin on DE0 board
input UART_RXD, // UART receive pin on DE0 board
output UART_CTS, // UART clear-to-send pin on DE0 board
output UART_TXD, // UART transmit pin on DE0 board
input UART_RXD, // UART receive pin on DE0 board
output UART_CTS, // UART clear-to-send pin on DE0 board
output [7:0] LEDG, // monitoring for lower 8 address bits
input [2:0] BUTTON, // BUTTON[0] for reset
output [6:0] HEX0_D,
output [6:0] HEX1_D,
output [6:0] HEX2_D,
output [6:0] HEX3_D,
output [7:0] LEDG, // monitoring for lower 8 address bits
input [2:0] BUTTON, // BUTTON[0] for reset
output [6:0] HEX0_D,
output [6:0] HEX1_D,
output [6:0] HEX2_D,
output [6:0] HEX3_D,
input PS2_KBCLK,
input PS2_KBDAT,
input PS2_KBCLK,
input PS2_KBDAT,
output [3:0] VGA_R,
output [3:0] VGA_G,
output [3:0] VGA_B,
output VGA_HS,
output VGA_VS
output [3:0] VGA_R,
output [3:0] VGA_G,
output [3:0] VGA_B,
output VGA_HS,
output VGA_VS
);
//////////////////////////////////////////////////////////////////////////
// Registers and Wires
reg clk25;
wire [15:0] pc_monitor;
//////////////////////////////////////////////////////////////////////////
// Registers and Wires
reg clk25;
wire [15:0] pc_monitor;
// generate 25MHz clock from 50MHz master clock
always @(posedge CLOCK_50)
begin
clk25 <= ~clk25;
end
// generate 25MHz clock from 50MHz master clock
always @(posedge CLOCK_50) begin
clk25 <= ~clk25;
end
wire r_bit, g_bit, b_bit;
wire r_bit, g_bit, b_bit;
//////////////////////////////////////////////////////////////////////////
// Core of system
apple1 #(
.BASIC_FILENAME (BASIC_FILENAME),
.FONT_ROM_FILENAME (FONT_ROM_FILENAME),
.RAM_FILENAME (RAM_FILENAME),
.VRAM_FILENAME (VRAM_FILENAME),
.WOZMON_ROM_FILENAME (WOZMON_ROM_FILENAME)
) apple1_top(
.clk25(clk25),
.rst_n(BUTTON[0]), // we don't have any reset pulse..
.uart_rx(UART_RXD),
.uart_tx(UART_TXD),
.uart_cts(UART_CTS),
.ps2_clk(PS2_KBCLK),
.ps2_din(PS2_KBDAT),
.ps2_select(1'b1),
.vga_h_sync(VGA_HS),
.vga_v_sync(VGA_VS),
.vga_red(r_bit),
.vga_grn(g_bit),
.vga_blu(b_bit),
.pc_monitor(pc_monitor)
);
//////////////////////////////////////////////////////////////////////////
// Core of system
apple1 #(
.BASIC_FILENAME(BASIC_FILENAME),
.FONT_ROM_FILENAME(FONT_ROM_FILENAME),
.RAM_FILENAME(RAM_FILENAME),
.VRAM_FILENAME(VRAM_FILENAME),
.WOZMON_ROM_FILENAME(WOZMON_ROM_FILENAME)
) apple1_top (
.clk25 (clk25),
.rst_n (BUTTON[0]), // we don't have any reset pulse..
.uart_rx (UART_RXD),
.uart_tx (UART_TXD),
.uart_cts (UART_CTS),
.ps2_clk (PS2_KBCLK),
.ps2_din (PS2_KBDAT),
.key_select(2'b10), // PS/2 enabled, UART TX disabled
// .key_select(2'b00), // PS/2 disabled, UART TX enabled
.vga_h_sync(VGA_HS),
.vga_v_sync(VGA_VS),
.vga_red (r_bit),
.vga_grn (g_bit),
.vga_blu (b_bit),
.pc_monitor(pc_monitor)
);
// set the monochrome base colour here..
assign VGA_R[3:0] = {4{r_bit}};
assign VGA_G[3:0] = {4{g_bit}};
assign VGA_B[3:0] = {4{b_bit}};
// set the monochrome base colour here..
assign VGA_R[3:0] = {4{r_bit}};
assign VGA_G[3:0] = {4{g_bit}};
assign VGA_B[3:0] = {4{b_bit}};
//////////////////////////////////////////////////////////////////////////
// Display 6502 address on 7-segment displays
//////////////////////////////////////////////////////////////////////////
// Display 6502 address on 7-segment displays
segmentdisplay seg1(
.clk(clk25),
.latch(1'b1),
.hexdigit_in(pc_monitor[3:0]),
.display_out(HEX0_D)
);
segmentdisplay seg1 (
.clk(clk25),
.latch(1'b1),
.hexdigit_in(pc_monitor[3:0]),
.display_out(HEX0_D)
);
segmentdisplay seg2(
.clk(clk25),
.latch(1'b1),
.hexdigit_in(pc_monitor[7:4]),
.display_out(HEX1_D)
);
segmentdisplay seg2 (
.clk(clk25),
.latch(1'b1),
.hexdigit_in(pc_monitor[7:4]),
.display_out(HEX1_D)
);
segmentdisplay seg3(
.clk(clk25),
.latch(1'b1),
.hexdigit_in(pc_monitor[11:8]),
.display_out(HEX2_D)
);
segmentdisplay seg3 (
.clk(clk25),
.latch(1'b1),
.hexdigit_in(pc_monitor[11:8]),
.display_out(HEX2_D)
);
segmentdisplay seg4(
.clk(clk25),
.latch(1'b1),
.hexdigit_in(pc_monitor[15:12]),
.display_out(HEX3_D)
);
segmentdisplay seg4 (
.clk(clk25),
.latch(1'b1),
.hexdigit_in(pc_monitor[15:12]),
.display_out(HEX3_D)
);
assign LEDG = 0;
assign LEDG = 0;
endmodule
+56 -55
View File
@@ -29,75 +29,76 @@ module apple1_top #(
parameter VRAM_FILENAME = "../../../roms/vga_vram.bin",
parameter WOZMON_ROM_FILENAME = "../../../roms/wozmon.hex"
) (
input pin3_clk_16mhz,// 16 MHz board clock
input pin3_clk_16mhz, // 16 MHz board clock
// Outputs to VGA display
output pin4, // hozizontal VGA sync pulse
output pin5, // vertical VGA sync pulse
output pin4, // hozizontal VGA sync pulse
output pin5, // vertical VGA sync pulse
input pin6, // PS/2 data input
input pin7, // PS/2 clock
input pin6, // PS/2 data input
input pin7, // PS/2 clock
// I/O interface to computer
input pin11, // asynchronous serial data input from computer
output pin12, // asynchronous serial data output to computer
output pin13, // clear to send flag to computer
input pin11, // asynchronous serial data input from computer
output pin12, // asynchronous serial data output to computer
output pin13, // clear to send flag to computer
output reg pin24, // red VGA signal
output reg pin23, // red VGA signal
output reg pin22, // green VGA signal
output reg pin21, // green VGA signal
output reg pin20, // blue VGA signal
output reg pin19 // blue VGA signal
output reg pin24, // red VGA signal
output reg pin23, // red VGA signal
output reg pin22, // green VGA signal
output reg pin21, // green VGA signal
output reg pin20, // blue VGA signal
output reg pin19 // blue VGA signal
);
wire clk25;
wire clk25;
// 16MHz up to 25MHz
clock_pll clock_pll_inst(
.REFERENCECLK(pin3_clk_16mhz),
.PLLOUTGLOBAL(clk25),
.RESET(1'b1)
);
// 16MHz up to 25MHz
clock_pll clock_pll_inst (
.REFERENCECLK(pin3_clk_16mhz),
.PLLOUTGLOBAL(clk25),
.RESET(1'b1)
);
wire [15:0] pc_monitor;
wire [15:0] pc_monitor;
reg [1:0] button = 2'b01;
reg [1:0] button = 2'b01;
wire vga_red;
wire vga_grn;
wire vga_blu;
wire vga_red;
wire vga_grn;
wire vga_blu;
// apple one main system
apple1 #(
.BASIC_FILENAME (BASIC_FILENAME),
.FONT_ROM_FILENAME (FONT_ROM_FILENAME),
.RAM_FILENAME (RAM_FILENAME),
.VRAM_FILENAME (VRAM_FILENAME),
.WOZMON_ROM_FILENAME (WOZMON_ROM_FILENAME)
) my_apple1(
.clk25(clk25),
.rst_n(button[0]),
.ps2_clk(pin7), // PS/2 not working with my keyboard
.ps2_din(pin6),
.ps2_select(1'b0), // change to 1 in order to test with keyboard
.uart_rx(pin11),
.uart_tx(pin12),
.uart_cts(pin13),
.vga_h_sync(pin4),
.vga_v_sync(pin5),
.vga_red(vga_red),
.vga_grn(vga_grn),
.vga_blu(vga_blu),
.pc_monitor(pc_monitor)
);
// apple one main system
apple1 #(
.BASIC_FILENAME(BASIC_FILENAME),
.FONT_ROM_FILENAME(FONT_ROM_FILENAME),
.RAM_FILENAME(RAM_FILENAME),
.VRAM_FILENAME(VRAM_FILENAME),
.WOZMON_ROM_FILENAME(WOZMON_ROM_FILENAME)
) my_apple1 (
.clk25(clk25),
.rst_n(button[0]),
.ps2_clk(pin7), // PS/2 not working with my keyboard
.ps2_din(pin6),
// .key_select(2'b10), // PS/2 enabled, UART TX disabled
.key_select(2'b00), // PS/2 disabled, UART TX enabled
.uart_rx(pin11),
.uart_tx(pin12),
.uart_cts(pin13),
.vga_h_sync(pin4),
.vga_v_sync(pin5),
.vga_red(vga_red),
.vga_grn(vga_grn),
.vga_blu(vga_blu),
.pc_monitor(pc_monitor)
);
assign pin19 = vga_blu;
assign pin20 = vga_blu;
assign pin21 = vga_grn;
assign pin22 = vga_grn;
assign pin23 = vga_red;
assign pin24 = vga_red;
assign pin19 = vga_blu;
assign pin20 = vga_blu;
assign pin21 = vga_grn;
assign pin22 = vga_grn;
assign pin23 = vga_red;
assign pin24 = vga_red;
endmodule
+44 -44
View File
@@ -30,16 +30,16 @@ module apple1_top #(
parameter WOZMON_ROM_FILENAME = "../../../roms/wozmon.hex"
) (
// 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
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
// Outputs to VGA display
output vga_h_sync, // hozizontal VGA sync pulse
output vga_v_sync, // vertical VGA sync pulse
output reg vga_red, // red VGA signal
output reg vga_grn, // green VGA signal
output reg vga_blu, // blue VGA signal
output vga_h_sync, // hozizontal VGA sync pulse
output vga_v_sync, // vertical VGA sync pulse
output reg vga_red, // red VGA signal
output reg vga_grn, // green VGA signal
output reg vga_blu, // blue VGA signal
// Tricolor LED on the UPDuino
output red_led,
@@ -47,45 +47,45 @@ module apple1_top #(
output blue_led
);
wire [15:0] leds;
assign red_led = ~leds[9];
assign green_led = ~leds[8];
assign blue_led = ~leds[7];
wire [15:0] leds;
assign red_led = ~leds[9];
assign green_led = ~leds[8];
assign blue_led = ~leds[7];
wire clk25;
wire clk;
wire clk25;
wire clk;
SB_HFOSC inthosc (
.CLKHFPU(1'b1),
.CLKHFEN(1'b1),
.CLKHF(clk)
);
SB_HFOSC inthosc (
.CLKHFPU(1'b1),
.CLKHFEN(1'b1),
.CLKHF (clk)
);
pll pll(
.clock_in(clk),
.clock_out(clk25),
);
pll pll (
.clock_in (clk),
.clock_out(clk25),
);
// apple one main system
apple1 #(
.BASIC_FILENAME (BASIC_FILENAME),
.FONT_ROM_FILENAME (FONT_ROM_FILENAME),
.RAM_FILENAME (RAM_FILENAME),
.VRAM_FILENAME (VRAM_FILENAME),
.WOZMON_ROM_FILENAME (WOZMON_ROM_FILENAME)
) my_apple1(
.clk25(clk25),
.rst_n(1'b1),
.uart_rx(uart_rx),
.uart_tx(uart_tx),
.uart_cts(uart_cts),
.vga_h_sync(vga_h_sync),
.vga_v_sync(vga_v_sync),
.vga_red(vga_red),
.vga_grn(vga_grn),
.vga_blu(vga_blu),
.pc_monitor(leds),
.ps2_select(1'b0), // no ps2 keyboard right now
);
// apple one main system
apple1 #(
.BASIC_FILENAME(BASIC_FILENAME),
.FONT_ROM_FILENAME(FONT_ROM_FILENAME),
.RAM_FILENAME(RAM_FILENAME),
.VRAM_FILENAME(VRAM_FILENAME),
.WOZMON_ROM_FILENAME(WOZMON_ROM_FILENAME)
) my_apple1 (
.clk25(clk25),
.rst_n(1'b1),
.uart_rx(uart_rx),
.uart_tx(uart_tx),
.uart_cts(uart_cts),
.vga_h_sync(vga_h_sync),
.vga_v_sync(vga_v_sync),
.vga_red(vga_red),
.vga_grn(vga_grn),
.vga_blu(vga_blu),
.pc_monitor(leds),
.key_select(1'b00) // UART only for now
);
endmodule
+16 -16
View File
@@ -44,7 +44,7 @@ module ps2keyboard (
wire ps2_clkdb; // debounced PS/2 clock signal
reg prev_ps2_clkdb; // previous clock state (in clk25 domain)
// keyboard translation signals
reg [7:0] ascii; // ASCII code of received character
reg ascii_rdy; // new ASCII character received
@@ -70,7 +70,7 @@ module ps2keyboard (
else
begin
rx_flag <= 1'b0; // reset the new data flag register
// check for negative edge of PS/2 clock
// and sample the state of the PS/2 data line
if ((prev_ps2_clkdb == 1'b1) && (ps2_clkdb == 1'b0))
@@ -84,7 +84,7 @@ module ps2keyboard (
// scan code here, including
// start, parity and stop bits.
rxcnt <= 0;
// signal new data is present
// note: this signal will only remain high for one
// clock cycle!
@@ -93,13 +93,13 @@ module ps2keyboard (
rx_flag <= 1'b1;
end
end
// update previous clock state
prev_ps2_clkdb <= ps2_clkdb;
end
end
//
// IBM Keyboard code page translation
// state machine for US keyboard layout
@@ -138,11 +138,11 @@ module ps2keyboard (
dout <= {ascii_rdy, 7'b0};
end
end
// keyboard translation state machine
if (rx_flag == 1'b1)
begin
// latch data from the serial buffer into
begin
// latch data from the serial buffer into
// the rx scancode buffer.
rx <= rxshiftbuf[8:1];
case(cur_state)
@@ -154,26 +154,26 @@ module ps2keyboard (
next_state = S_KEYE0;
else
begin
// check the debounce timer, if this is
// check the debounce timer, if this is
// not zero, a new key arrived too quickly
// and we simply discard it. For better
// debouncing, we should check if the key
// is actually the same as the previous received/
// key, but let's try this first to see if it works
// ok...
//if (debounce_timer == 16'd0)
//begin
ascii_rdy <= 1'b1; // new key has arrived!
//debounce_timer <= 16'hFFFF; // reset the debounce timer
//end
// check for a SHIFT key
if ((rx == 8'h59) || (rx == 8'h12))
begin
shift <= 1'b1;
ascii_rdy <= 1'b0; // shift is not a key!
end
end
else begin
if (!shift)
case(rx)
@@ -218,7 +218,7 @@ module ps2keyboard (
8'h4E: ascii <= "-";
8'h55: ascii <= "=";
8'h5D: ascii <= 8'h34; // backslash
8'h66: ascii <= "_"; // backspace
8'h66: ascii <= "_"; // backspace
8'h29: ascii <= " ";
8'h5A: ascii <= 8'd13; // enter
@@ -229,7 +229,7 @@ module ps2keyboard (
8'h41: ascii <= ",";
8'h49: ascii <= ".";
8'h4A: ascii <= "/";
default:
default:
// unsupported key!
begin
ascii_rdy <= 1'b0; // shift is not a key!
@@ -291,7 +291,7 @@ module ps2keyboard (
8'h41: ascii <= "<";
8'h49: ascii <= ">";
8'h4A: ascii <= "?";
default:
default:
// unsupported key!
begin
ascii_rdy <= 1'b0; // shift is not a key!
+74
View File
@@ -0,0 +1,74 @@
localparam [7:0] SHIFT_MASK = 8'b00100010;
function [7:0] scancode2char(input [7:0] scancode, input [7:0] modifiers);
reg [7:0] a;
begin
if (scancode >= 4 && scancode <= 29) begin // only uppercase for apple 1
a = scancode - {8'd4} + {8'd65};
end else if (modifiers == 0) begin
case (scancode)
30: a = "1";
31: a = "2";
32: a = "3";
33: a = "4";
34: a = "5";
35: a = "6";
36: a = "7";
37: a = "8";
38: a = "9";
39: a = "0";
40: a = 13; // enter
41: a = 27; // esc
42: a = "_"; // backspace - Apple1 only understands '_' for backspace
43: a = 9; // tab
44: a = 32; // space
45: a = "-"; // -
46: a = "="; // =
47: a = "["; // [
48: a = "]"; // ]
49: a = "\\"; // \
50: a = "#"; // non-use # ~
51: a = ";"; // ;
52: a = "'"; // '
53: a = "`"; // `
54: a = ","; // ,
55: a = "."; // .
56: a = "/"; // /
57: ; // caps lock
endcase
end if ((modifiers & SHIFT_MASK) && (modifiers & ~SHIFT_MASK) == 0) begin
// shift down
case (scancode)
30: a = "!";
31: a = "@";
32: a = "#";
33: a = "$";
34: a = "%";
35: a = "^";
36: a = "&";
37: a = "*";
38: a = "(";
39: a = ")";
40: a = "\n";
40: a = 13; // enter
41: a = 27; // esc
42: a = "_"; // backspace - Apple1 only understands '_' for backspace
43: a = 9; // tab
44: a = 32; // space
45: a = "_";
46: a = "+";
47: a = "{";
48: a = "}";
49: a = "|";
50: a = "~";
51: a = ":";
52: a = "\"";
53: a = "~";
54: a = "<";
55: a = ">";
56: a = "?";
57: ;
endcase
end
scancode2char = a;
end
endfunction
+394
View File
@@ -0,0 +1,394 @@
// Usb_hid_host: A compact USB HID host core.
//
// nand2mario, 8/2023, based on work by hi631
// modified heavily by Alan Garfield <alan@fromorbit.com> 09/2025
//
// This should support keyboard input out of the box, over low-speed
// USB (1.5Mbps). Just connect D+, D-, VBUS (5V) and GND, and two 15K resistors between
// D+ and GND, D- and GND. Then provide a 12Mhz clock through usbclk.
//
// See https://github.com/nand2mario/usb_hid_host
//
module usb_hid_host (
input usbclk, // 12MHz clock
input usbrst_n, // reset
inout usb_dm, usb_dp, // USB D- and D+
output reg [1:0] typ, // device type. 0: no device, 1: keyboard, 2: mouse, 3: gamepad
output reg report, // pulse after report received from device.
output conerr, // connection or protocol error
// keyboard
output reg [7:0] key_modifiers,
output reg [7:0] key1, key2, key3, key4
// debug
// output [63:0] dbg_hid_report // last HID report
);
wire data_rdy; // data ready
wire data_strobe; // data strobe for each byte
wire [7:0] ukpdat; // actual data
reg [7:0] regs [7:0]; // 0 (VID_L), 1 (VID_H), 2 (PID_L), 3 (PID_H), 4 (INTERFACE_CLASS), 5 (INTERFACE_SUBCLASS), 6 (INTERFACE_PROTOCOL)
wire save; // save dat[b] to output register r
wire [3:0] save_r; // which register to save to
wire [3:0] save_b; // dat[b]
wire connected;
ukp ukp(
.usbrst_n(usbrst_n),
.usbclk(usbclk),
.usb_dp(usb_dp),
.usb_dm(usb_dm),
.usb_oe(),
.ukprdy(data_rdy),
.ukpstb(data_strobe),
.ukpdat(ukpdat),
.save(save),
.save_r(save_r),
.save_b(save_b),
.connected(connected),
.conerr(conerr)
);
reg [3:0] rcvct; // counter for recv data
reg data_strobe_r, data_rdy_r; // delayed data_strobe and data_rdy
reg [7:0] dat[7:0]; // data in last response
// assign dbg_hid_report = {dat[7], dat[6], dat[5], dat[4], dat[3], dat[2], dat[1], dat[0]};
always @(posedge usbclk) begin : process_in_data
data_rdy_r <= data_rdy;
data_strobe_r <= data_strobe;
report <= 0; // ensure pulse
if(~data_rdy) rcvct <= 0;
else begin
if(data_strobe && ~data_strobe_r) begin // rising edge of ukp data strobe
dat[rcvct] <= ukpdat;
if (typ == 1) begin // keyboard
case (rcvct)
0: key_modifiers <= ukpdat;
2: key1 <= ukpdat;
3: key2 <= ukpdat;
4: key3 <= ukpdat;
5: key4 <= ukpdat;
endcase
end
rcvct <= rcvct + {1'd1};
end
end
if(~data_rdy && data_rdy_r && typ != 0) // falling edge of ukp data ready
report <= 1;
end
reg save_delayed;
reg connected_r;
always @(posedge usbclk) begin : response_recognition
save_delayed <= save;
if (save) begin
regs[save_r] <= dat[save_b];
end else if (save_delayed && ~save && save_r == 6) begin
// falling edge of save for bInterfaceProtocol
if (regs[4] == 3) begin // bInterfaceClass. 3: HID, other: non-HID
if (regs[5] == 1) // bInterfaceSubClass. 1: Boot device
typ <= regs[6] == 1 ? 1 : 2; // bInterfaceProtocol. 1: keyboard, 2: mouse
else
typ <= 3; // gamepad
end else
typ <= 0;
end
connected_r <= connected;
if (~connected & connected_r) typ <= 0; // clear device type on disconnect
end
endmodule
module ukp(
input usbrst_n,
input usbclk, // 12MHz clock
inout usb_dp, usb_dm, // D+, D-
output usb_oe,
output reg ukprdy, // data frame is outputing
output ukpstb, // strobe for a byte within the frame
output reg [7:0] ukpdat, // output data when ukpstb=1
output reg save, // save: regs[save_r] <= dat[save_b]
output reg [3:0] save_r, save_b,
output reg connected,
output conerr
);
parameter S_OPCODE = 0;
parameter S_LDI0 = 1;
parameter S_LDI1 = 2;
parameter S_B0 = 3;
parameter S_B1 = 4;
parameter S_B2 = 5;
parameter S_S0 = 6;
parameter S_S1 = 7;
parameter S_S2 = 8;
parameter S_TOGGLE0 = 9;
parameter S_TOGGLE1 = 10;
wire [3:0] inst;
reg [3:0] insth;
wire sample; // 1: an IN sample is available
// reg connected = 0;
reg inst_ready = 0;
reg up = 0;
reg um = 0;
reg cond = 0;
reg nak = 0;
reg dmis = 0;
reg ug, ugw, nrzon; // ug=1: output enabled, 0: hi-Z
reg bank = 0, record1 = 0;
reg [1:0] mbit = 0; // 1: out4/outb is transmitting
reg [3:0] state = 0, stated;
reg [7:0] wk = 0; // W register
reg [7:0] sb = 0; // out value
reg [3:0] sadr; // out4/outb write ptr
reg [13:0] pc = 0, wpc; // program counter, wpc = next pc
reg [2:0] timing = 0; // T register (0~7)
reg [3:0] lb4 = 0, lb4w;
reg [13:0] interval = 0;
reg [6:0] bitadr = 0; // 0~127
reg [7:0] data = 0; // received data
reg [2:0] nrztxct, nrzrxct; // NRZI trans/recv count for bit stuffing
wire interval_cy = interval == 12001;
wire next = ~(state == S_OPCODE & (
inst ==2 & dmi | // start
(inst==4 || inst==5) & timing != 0 | // out0/hiz
inst ==13 & (~sample | (dpi | dmi) & wk != 1) | // in
inst ==14 & ~interval_cy // wait
));
wire branch = state == S_B1 & cond;
wire retpc = state == S_OPCODE && inst==7 ? 1 : 0;
wire jmppc = state == S_OPCODE && inst==15 ? 1 : 0;
wire dbit = sb[7-sadr[2:0]];
wire record;
reg dmid;
reg [23:0] conct;
assign conerr = conct[23] || ~usbrst_n;
usb_hid_host_rom ukprom(.clk(usbclk), .adr(pc), .data(inst));
always @(posedge usbclk) begin
if(~usbrst_n) begin
pc <= 0;
connected <= 0;
cond <= 0;
inst_ready <= 0;
state <= S_OPCODE;
timing <= 0;
mbit <= 0;
bitadr <= 0;
nak <= 1;
ug <= 0;
end else begin
dpi <= usb_dp;
dmi <= usb_dm;
save <= 0; // ensure pulse
if (!inst_ready) begin
inst_ready <= 1;
end else begin
// Instruction decoding
case(state)
S_OPCODE: begin
insth <= inst;
if(inst==1) state <= S_LDI0; // op=ldi
if(inst==3) begin sadr <= 3; state <= S_S0; end // op=out4
if(inst==4) begin ug <= 1; up <= 0; um <= 0; end
if(inst==5) begin ug <= 0; end
if(inst==6) begin sadr <= 7; state <= S_S0; end // op=outb
if (inst[3:2]==2'b10) begin // op=10xx(BZ,BC,BNAK,DJNZ)
state <= S_B0;
case (inst[1:0])
2'b00: cond <= ~dmi;
2'b01: cond <= connected;
2'b10: cond <= nak;
2'b11: cond <= wk != 1;
endcase
end
if(inst==11 | inst==13 & sample) wk <= wk - 1'd1; // op=DJNZ,IN
if(inst==15) begin state <= S_B2; cond <= 1; end // op=jmp
if(inst==12) state <= S_TOGGLE0;
end
// Instructions with operands
// ldi
S_LDI0: begin
wk[3:0] <= inst;
state <= S_LDI1;
end
S_LDI1: begin
wk[7:4] <= inst;
state <= S_OPCODE;
end
// branch/jmp
S_B2: begin
lb4w <= inst;
state <= S_B0;
end
S_B0: begin
lb4 <= inst;
state <= S_B1;
end
// out
S_B1: begin
state <= S_OPCODE;
end
S_S0: begin
sb[3:0] <= inst;
state <= S_S1;
end
S_S1: begin
sb[7:4] <= inst;
state <= S_S2;
mbit <= 1;
end
// toggle and save
S_TOGGLE0: begin
if (inst == 15) connected <= ~connected;// toggle
else save_r <= inst; // save
state <= S_TOGGLE1;
end
S_TOGGLE1: begin
if (inst != 15) begin
save_b <= inst;
save <= 1;
end
state <= S_OPCODE;
end
endcase
// pc control
if (mbit==0) begin
if(jmppc) wpc <= pc + {3'd4};
if (next | branch | retpc) begin
if(retpc) pc <= wpc; // ret
else if(branch)
if(insth==15) // jmp
pc <= { inst, lb4, lb4w, 2'b00 };
else // branch
pc <= { 4'b0000, inst, lb4, 2'b00 };
else pc <= pc + {1'd1}; // next
inst_ready <= 0;
end
end
end
// bit transmission (out4/outb)
if (mbit==1 && timing == 0) begin
if(ug==0) begin
nrztxct <= 0;
end else begin
if(dbit) begin
nrztxct <= nrztxct + {1'd1};
end else begin
nrztxct <= 0;
end
end
if(insth == 4'd6) begin
if(nrztxct!=6) begin
up <= dbit ? up : ~up;
um <= dbit ? ~up : up;
end else begin
up <= ~up;
um <= up;
nrztxct <= 0;
end
end else begin
up <= sb[{1'b1,sadr[1:0]}]; um <= sb[sadr[2:0]];
end
ug <= 1'b1;
if(nrztxct!=6) begin
sadr <= sadr - {1'd1};
end
if(sadr==0) begin
mbit <= 0;
state <= S_OPCODE;
end
end
// start instruction
dmid <= dmi;
if (inst_ready & state == S_OPCODE & inst == 4'b0010) begin // op=start
bitadr <= 0; nak <= 1; nrzrxct <= 0;
end else begin
if(ug==0 && dmi!=dmid) begin
timing <= 1;
end else begin
timing <= timing + {1'd1};
end
end
// IN instruction
if (sample) begin
if (bitadr == 8) begin
nak <= dmi;
end
if(nrzrxct!=6) begin
data[6:0] <= data[7:1];
data[7] <= dmis ~^ dmi; // ~^/^~ is XNOR, testing bit equality
bitadr <= bitadr + {1'd1};
nrzon <= 0;
end else begin
nrzon <= 1;
end
dmis <= dmi;
if(dmis ~^ dmi) begin
nrzrxct <= nrzrxct + {1'd1};
end else begin
nrzrxct <= 0;
end
if (~dmi && ~dpi) begin
ukprdy <= 0; // SE0: packet is finished. Mouses send length 4 reports.
end
end
if (ug==0) begin
if(bitadr==24) ukprdy <= 1; // ignore first 3 bytes
if(bitadr==88) ukprdy <= 0; // output next 8 bytes
end
if ((bitadr>11 & bitadr[2:0] == 3'b000) & (timing == 2)) ukpdat <= data;
// Timing
interval <= interval_cy ? {14'd0} : interval + {1'd1};
record1 <= record;
if (~record & record1) bank <= ~bank;
// Connection status & WDT
ukprdyd <= ukprdy;
nakd <= nak;
if (ukprdy && ~ukprdyd || inst_ready && state == S_OPCODE && inst == 4'b0010)
conct <= 0; // reset watchdog on data received or START instruction
else begin
if(conct[23:22]!=2'b11) conct <= conct + {1'd1};
else begin
pc <= 0;
conct <= 0;
end // !! WDT ON
end
end
end
assign usb_dp = ug ? up : 1'bZ;
assign usb_dm = ug ? um : 1'bZ;
assign usb_oe = ug;
assign sample = inst_ready & state == S_OPCODE & inst == 4'b1101 & timing == 4; // IN
assign record = connected & ~nak;
assign ukpstb = ~nrzon & ukprdy & (bitadr[2:0] == 3'b100) & (timing == 2);
reg dpi, dmi;
reg ukprdyd;
reg nakd;
endmodule
+536
View File
@@ -0,0 +1,536 @@
1
9
0
0
e
9
a
2
8
0
0
1
8
c
0
0
e
b
4
0
f
4
3
0
f
8
4
0
5
f
2
7
0
0
0
0
f
7
7
0
5
f
2
7
0
a
9
0
f
3
8
0
5
0
0
0
f
7
7
0
5
f
2
7
0
a
e
0
c
4
6
c
5
7
f
3
8
0
5
0
f
7
7
0
5
f
2
7
0
a
4
1
c
6
0
f
3
8
0
5
f
4
3
0
f
6
5
0
5
f
2
7
0
0
0
0
f
7
7
0
5
f
2
7
0
a
d
1
f
3
8
0
5
e
f
4
6
0
5
f
2
7
0
0
f
b
7
0
5
f
2
7
0
a
4
2
f
3
8
0
5
c
f
f
f
0
0
0
8
2
3
3
3
0
5
b
1
0
e
f
f
7
0
5
f
2
7
0
a
0
0
f
3
8
0
5
f
0
0
0
c
f
f
f
0
0
0
0
4
1
a
0
e
b
5
3
5
1
8
2
e
3
3
0
5
b
7
3
e
7
0
0
6
0
8
6
d
2
6
0
0
6
0
1
3
3
0
6
0
8
6
3
c
6
0
8
6
6
0
6
0
0
6
1
0
6
0
0
6
0
0
6
2
1
6
0
0
6
0
e
6
4
f
3
3
0
7
0
6
0
8
6
d
2
6
0
0
6
0
1
3
3
0
6
0
8
6
3
c
6
0
8
6
6
0
6
0
0
6
2
0
6
0
0
6
0
0
6
8
1
6
0
0
6
2
a
6
4
5
3
3
0
7
0
6
0
8
6
d
2
6
0
0
6
0
1
3
3
0
6
0
8
6
3
c
6
0
0
6
5
0
6
1
0
6
0
0
6
0
0
6
0
0
6
0
0
6
0
0
6
b
e
6
5
2
3
3
0
7
0
6
0
8
6
d
2
6
1
0
6
8
e
3
3
0
6
0
8
6
3
c
6
0
0
6
9
0
6
1
0
6
0
0
6
0
0
6
0
0
6
0
0
6
0
0
6
7
2
6
5
2
3
3
0
7
0
1
8
6
2
d
0
0
0
1
2
0
0
8
4
7
b
5
7
7
0
6
0
8
6
9
6
6
0
0
6
0
1
3
3
0
7
6
0
8
6
9
6
6
1
0
6
8
e
3
3
0
7
6
0
8
6
9
6
6
1
8
6
8
5
3
3
0
7
6
0
8
6
2
d
3
3
0
7
0
0
+9
View File
@@ -0,0 +1,9 @@
module usb_hid_host_rom(clk, adr, data);
input clk;
input [13:0] adr;
output [3:0] data;
reg [3:0] data;
reg [3:0] mem [0:535];
initial $readmemh("usb_hid_host_rom.hex", mem);
always @(posedge clk) data <= mem[adr];
endmodule
+90
View File
@@ -0,0 +1,90 @@
module usb_keyboard (
input usb_clk,
input rst,
// 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.
// LEDs
output led_connerr,
output led_activity,
// USB
inout usb_dm,
inout usb_dp
);
`include "scancodes.v"
wire [1:0] usb_type;
wire [7:0] key_modifiers, key1, key2, key3, key4;
wire [7:0] hid_regs [7:0];
wire usb_report;
wire usb_conerr;
usb_hid_host usb (
.usbclk(usb_clk),
.usbrst_n(!rst),
.usb_dm(usb_dm),
.usb_dp(usb_dp),
.typ(usb_type),
.report(usb_report),
.key_modifiers(key_modifiers),
.key1(key1),
.key2(key2),
.key3(key3),
.key4(key4),
.conerr(usb_conerr)
);
reg report_toggle; // blinks whenever there's a report
reg usb_rdy; // new USB character flag
reg ascii_rdy; // new ASCII character for CPU
reg [7:0] ascii; // ASCII code of key character
reg [7:0] key_active;
always @(posedge usb_clk or posedge rst) begin
if(rst) begin
usb_rdy <= 1'b0;
ascii_rdy <= 1'b0;
end else begin
usb_rdy <= 1'b0;
if (usb_report) report_toggle <= ~report_toggle;
if (usb_report && usb_type == 1'd1) begin
// keyboard
if (key1 != 0 && key1 != key_active) begin
ascii <= scancode2char(key1, key_modifiers);
usb_rdy <= 1'b1;
end
key_active <= key1;
end
// handle I/O from CPU
if (cs == 1'b1) begin
if (address == 1'b0) begin
// CPU RX buffer address
dout <= {1'b1, ascii[6:0]};
ascii_rdy <= 1'b0;
end
else
begin
// CPU RX status register
dout <= {ascii_rdy, 7'b0};
end
end
if (usb_rdy == 1'b1) begin
ascii_rdy <= 1'b1;
end
end
end
assign led_connerr = ~usb_conerr;
assign led_activity = ~report_toggle;
endmodule