From: Ryan <> Date: Tue, 23 Sep 2025 16:18:42 +0000 (-0500) Subject: Add clock-optimized version of CPU0 project X-Git-Url: https://git.the-white-hart.net/?a=commitdiff_plain;h=6656b04f331585bb1ec86b96ae5f722605567457;p=vhdl Add clock-optimized version of CPU0 project --- diff --git a/projects/cpu_0/nexys2_speed.vhd b/projects/cpu_0/nexys2_speed.vhd new file mode 100644 index 0000000..e639457 --- /dev/null +++ b/projects/cpu_0/nexys2_speed.vhd @@ -0,0 +1,588 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_misc.all; + +library utility; +library nexys2_lib; +library ps2; +library rs232; +library vga; +library timer; + + +entity nexys2_speed is + port ( + -- Clock input + clk_50: in std_logic; + + -- EPP interface + DB: inout std_logic_vector(7 downto 0); + EppWRITE: in std_logic; + EppASTB: in std_logic; + EppDSTB: in std_logic; + EppWAIT: out std_logic; + + -- Memory interface + MemOE: out std_logic; + MemWR: out std_logic; + RamAdv: out std_logic; + RamCS: out std_logic; + RamClk: out std_logic; + RamCRE: out std_logic; + RamLB: out std_logic; + RamUB: out std_logic; + RamWait: in std_logic; + FlashRp: out std_logic; + FlashCS: out std_logic; + FlashStSts: in std_logic; + MemAdr: out std_logic_vector(23 downto 1); + MemDB: inout std_logic_vector(15 downto 0); + + -- Switches and LEDs + seg: out std_logic_vector(6 downto 0); + dp: out std_logic; + an: out std_logic_vector(3 downto 0); + Led: out std_logic_vector(7 downto 0); + sw: in std_logic_vector(7 downto 0); + btn: in std_logic_vector(3 downto 0); + + -- VGA video output + vgaRed: out std_logic_vector(3 downto 1); + vgaGreen: out std_logic_vector(3 downto 1); + vgaBlue: out std_logic_vector(3 downto 2); + Hsync: out std_logic; + Vsync: out std_logic; + + -- PS2 (keyboard) + PS2C: inout std_logic; + PS2D: inout std_logic; + + -- RS232 (mouse) + RsRx: in std_logic; + RsTx: out std_logic + ); +end nexys2_speed; + + +architecture behavioral of nexys2_speed is + + -- Device Wishbone SYSCON + signal d_rst: std_logic; -- Device reset (P.O.R. or host) + signal d_clk: std_logic; -- Device clock, in case DCM used instead of clk_50 later + + -- Wishbone busses + signal cyc: std_logic; + signal stb: std_logic; + signal we: std_logic; + signal ack: std_logic; + signal adr: std_logic_vector(31 downto 0); + signal dat_mosi: std_logic_vector(7 downto 0); + signal dat_miso: std_logic_vector(7 downto 0); + + signal fls_cyc: std_logic; + signal ram_cyc: std_logic; + signal mem_ack: std_logic; + signal mem_miso: std_logic_vector(7 downto 0); + + signal bridge_a_cyc: std_logic; + signal bridge_a_ack: std_logic; + signal bridge_a_miso: std_logic_vector(7 downto 0); + signal bridge_b_cyc: std_logic; + signal bridge_b_stb: std_logic; + signal bridge_b_we: std_logic; + signal bridge_b_ack: std_logic; + signal bridge_b_adr: std_logic_vector(31 downto 0); + signal bridge_b_mosi: std_logic_vector(7 downto 0); + signal bridge_b_miso: std_logic_vector(7 downto 0); + + signal scr_cyc: std_logic; + signal tile_cyc: std_logic; + signal pal_cyc: std_logic; + signal vga_ack: std_logic; + signal vga_miso: std_logic_vector(7 downto 0); + + signal host_cyc: std_logic; + signal host_ack: std_logic; + signal host_miso: std_logic_vector(7 downto 0); + + signal ps2_cyc: std_logic; + signal ps2_ack: std_logic; + signal ps2_miso: std_logic_vector(7 downto 0); + + signal uart_cyc: std_logic; + signal uart_ack: std_logic; + signal uart_miso: std_logic_vector(7 downto 0); + + signal timer0_cyc: std_logic; + signal timer0_ack: std_logic; + signal timer0_miso: std_logic_vector(7 downto 0); + + signal timer1_cyc: std_logic; + signal timer1_ack: std_logic; + signal timer1_miso: std_logic_vector(7 downto 0); + + -- Interrupt signals + signal host_flags: std_logic_vector(7 downto 0); + + signal ps2_rx_ready: std_logic; + signal ps2_rx_full: std_logic; + signal ps2_tx_ready: std_logic; + signal ps2_tx_empty: std_logic; + signal ps2_err_nack: std_logic; + signal ps2_err_txto: std_logic; + signal ps2_err_rxto: std_logic; + signal ps2_err_missed: std_logic; + signal ps2_err_parity: std_logic; + signal ps2_err_framing: std_logic; + + signal uart_rx_ready: std_logic; + signal uart_rx_full: std_logic; + signal uart_tx_ready: std_logic; + signal uart_tx_empty: std_logic; + signal uart_err_break: std_logic; + signal uart_err_framing: std_logic; + signal uart_err_parity: std_logic; + signal uart_err_overflow: std_logic; + + signal timer0_zero: std_logic; + signal timer1_zero: std_logic; + + -- Memory physical interface, routed through host controller + signal d_MemOE: std_logic; + signal d_MemWR: std_logic; + signal d_RamAdv: std_logic; + signal d_RamCS: std_logic; + signal d_RamClk: std_logic; + signal d_RamCRE: std_logic; + signal d_RamUB: std_logic; + signal d_RamLB: std_logic; + signal d_RamWait: std_logic; + signal d_FlashRp: std_logic; + signal d_FlashCS: std_logic; + signal d_FlashStSts: std_logic; + signal d_MemAdr: std_logic_vector(23 downto 1); + signal d_MemDB_i: std_logic_vector(15 downto 0); + signal d_MemDB_o: std_logic_vector(15 downto 0); + + -- Interrupt signals + signal int_cpu: std_logic; + signal int_vec: std_logic_vector(7 downto 0); + signal ints: std_logic_vector(15 downto 0); + + -- Debug signals + signal deb_wait: std_logic; + signal deb_pc: std_logic_vector(31 downto 0); + signal deb_ins: std_logic_vector(7 downto 0); + signal deb_t: std_logic_vector(31 downto 0); + signal deb_n: std_logic_vector(31 downto 0); + signal deb_r: std_logic_vector(31 downto 0); + signal debug_i: std_logic_vector(63 downto 0); + signal debug_o: std_logic_vector(63 downto 0); + +begin + + e_cpu: entity work.cpu + port map ( + rst_i => d_rst, + clk_i => d_clk, + + cyc_o => cyc, + stb_o => stb, + we_o => we, + ack_i => ack, + adr_o => adr, + dat_o => dat_mosi, + dat_i => dat_miso, + + int_i => int_cpu, + vec_i => int_vec, + + halt_i => sw(7), + step_i => deb_wait, + pc_o => open,--deb_pc, + ins_o => open,--deb_ins, + t_o => open,--deb_t, + n_o => open,--deb_n, + r_o => open--deb_r + ); + + deb_wait <= debug_i(0); + debug_o <= (others => '0'); + --with debug_i(2 downto 1) select debug_o <= + -- x"000000" & deb_ins & deb_pc when "00", + -- deb_n & deb_t when "01", + -- x"00000000" & deb_r when others; + + int_vec(7 downto 4) <= (others => '0'); + ints(0) <= '0'; + e_int: entity work.int_ctrl + port map ( + int_o => int_cpu, + vec_o => int_vec(3 downto 0), + int_i => ints + ); + + d_clk <= clk_50; + + + e_mapper_a: entity utility.wb_mapper_a32d8 + generic map (N => 3) + port map ( + cyc_i => cyc, + ack_o => ack, + adr_i => adr, + dat_o => dat_miso, + + mask(0) => "00000011000000000000000000000000", -- Flash + mask(1) => "00000011000000000000000000000000", -- RAM + mask(2) => "00000010000000000000000000000000", -- Bridge + + match(0) => "00000000000000000000000000000000", + match(1) => "00000001000000000000000000000000", + match(2) => "00000010000000000000000000000000", + + cyc_o(0) => fls_cyc, + cyc_o(1) => ram_cyc, + cyc_o(2) => bridge_a_cyc, + + ack_i(0) => mem_ack, + ack_i(1) => mem_ack, + ack_i(2) => bridge_a_ack, + + dat_i(0) => mem_miso, + dat_i(1) => mem_miso, + dat_i(2) => bridge_a_miso + ); + + + e_bridge: entity utility.wb_bridge + generic map (A_WIDTH => 32, D_WIDTH => 8) + port map ( + rst_i => d_rst, + clk_i => d_clk, + + a_cyc_i => bridge_a_cyc, + a_stb_i => stb, + a_we_i => we, + a_ack_o => bridge_a_ack, + a_adr_i => adr, + a_dat_i => dat_mosi, + a_dat_o => bridge_a_miso, + + b_cyc_o => bridge_b_cyc, + b_stb_o => bridge_b_stb, + b_we_o => bridge_b_we, + b_ack_i => bridge_b_ack, + b_adr_o => bridge_b_adr, + b_dat_o => bridge_b_mosi, + b_dat_i => bridge_b_miso + ); + + -- Flash: 0x00000000-0x00ffffff + -- Ram: 0x01000000-0x01ffffff + -- Vbuf: 0x02000000-0x02003fff + -- Tiles: 0x02004000-0x020047ff + -- Palette: 0x02006000-0x02007fff + -- Host: 0x02008000-0x02008007 + -- PS2: 0x02008008-0x0200800f + -- UART: 0x02008010-0x02008017 + -- Timer0: 0x02008018-0x0200801b + -- Timer1: 0x0200801c-0x0200801f + e_mapper_b: entity utility.wb_mapper_a32d8 + generic map (N => 8) + port map ( + cyc_i => bridge_b_cyc, + ack_o => bridge_b_ack, + adr_i => bridge_b_adr, + dat_o => bridge_b_miso, + + mask(0) => "00000000000000001100000000000000", -- VGA screen buffer + mask(1) => "00000000000000001110000000000000", -- VGA tile memory + mask(2) => "00000000000000001110000000000000", -- VGA palette + mask(3) => "00000000000000001100000000011000", -- Host + mask(4) => "00000000000000001100000000011000", -- PS2 + mask(5) => "00000000000000001100000000011000", -- UART + mask(6) => "00000000000000001100000000011100", -- Timer0 + mask(7) => "00000000000000001100000000011100", -- Timer1 + + match(0) => "00000000000000000000000000000000", -- VGA scrbuf + match(1) => "00000000000000000100000000000000", -- VGA tiles + match(2) => "00000000000000000110000000000000", -- VGA palette + match(3) => "00000000000000001000000000000000", + match(4) => "00000000000000001000000000001000", + match(5) => "00000000000000001000000000010000", + match(6) => "00000000000000001000000000011000", + match(7) => "00000000000000001000000000011100", + + cyc_o(0) => scr_cyc, + cyc_o(1) => tile_cyc, + cyc_o(2) => pal_cyc, + cyc_o(3) => host_cyc, + cyc_o(4) => ps2_cyc, + cyc_o(5) => uart_cyc, + cyc_o(6) => timer0_cyc, + cyc_o(7) => timer1_cyc, + + ack_i(0) => vga_ack, + ack_i(1) => vga_ack, + ack_i(2) => vga_ack, + ack_i(3) => host_ack, + ack_i(4) => ps2_ack, + ack_i(5) => uart_ack, + ack_i(6) => timer0_ack, + ack_i(7) => timer1_ack, + + dat_i(0) => vga_miso, + dat_i(1) => vga_miso, + dat_i(2) => vga_miso, + dat_i(3) => host_miso, + dat_i(4) => ps2_miso, + dat_i(5) => uart_miso, + dat_i(6) => timer0_miso, + dat_i(7) => timer1_miso + ); + + + e_mem: entity nexys2_lib.mem_wb8_0_opt + port map ( + rst_i => d_rst, + clk_i => d_clk, + + -- Internal access + fls_cyc_i => fls_cyc, + ram_cyc_i => ram_cyc, + stb_i => stb, + we_i => we, + ack_o => mem_ack, + adr_i => adr(23 downto 0), + dat_i => dat_mosi, + dat_o => mem_miso, + + -- Configuration + --wait_cycles => "01100", + + -- Memory interface + MemOE => d_MemOE, + MemWR => d_MemWR, + RamAdv => d_RamAdv, + RamCS => d_RamCS, + RamClk => d_RamClk, + RamCRE => d_RamCRE, + RamUB => d_RamUB, + RamLB => d_RamLB, + RamWait => d_RamWait, + FlashRp => d_FlashRp, + FlashCS => d_FlashCS, + FlashStSts => d_FlashStSts, + MemAdr => d_MemAdr, + MemDB_i => d_MemDB_i, + MemDB_o => d_MemDB_o + ); + + + e_vga: entity vga.vga_tiler_opt + port map ( + rst_i => d_rst, + clk_i => d_clk, + + -- Internal access to screen buffer and tile set + scr_cyc_i => scr_cyc, + tile_cyc_i => tile_cyc, + pal_cyc_i => pal_cyc, + stb_i => bridge_b_stb, + we_i => bridge_b_we, + ack_o => vga_ack, + adr_i => bridge_b_adr(13 downto 0), + dat_i => bridge_b_mosi, + dat_o => vga_miso, + + vga_clk => d_clk, -- TODO: Plug this into a DCM + + -- External pins + vgaRed => vgaRed, + vgaGreen => vgaGreen, + vgaBlue => vgaBlue, + Hsync => Hsync, + Vsync => Vsync + ); + + + ints(1) <= or_reduce(host_flags); + e_host: entity nexys2_lib.host_ctrl_opt + port map ( + clk_i => d_clk, + rst_i => '0', + + -- Signals to the internal device + d_rst_o => d_rst, + d_flags_o => host_flags, + debug_i => debug_o, + debug_o => debug_i, + + -- Internal access to control registers + d_cyc_i => host_cyc, + d_stb_i => bridge_b_stb, + d_we_i => bridge_b_we, + d_ack_o => host_ack, + d_adr_i => bridge_b_adr(2 downto 0), + d_dat_i => bridge_b_mosi, + d_dat_o => host_miso, + + -- Internal memory interface, can be switched off to allow the host to control memory + d_MemOE => d_MemOE, + d_MemWR => d_MemWR, + d_RamAdv => d_RamAdv, + d_RamCS => d_RamCS, + d_RamClk => d_RamClk, + d_RamCRE => d_RamCRE, + d_RamLB => d_RamLB, + d_RamUB => d_RamUB, + d_RamWait => d_RamWait, + d_FlashRp => d_FlashRp, + d_FlashCS => d_FlashCS, + d_FlashStSts => d_FlashStSts, + d_MemAdr => d_MemAdr, + d_MemDB_o => d_MemDB_o, + d_MemDB_i => d_MemDB_i, + + -- External pins + EppAstb => EppASTB, + EppDstb => EppDSTB, + EppWr => EppWRITE, + EppDB => DB, + EppWait => EppWAIT, + + MemOE => MemOE, + MemWR => MemWR, + RamAdv => RamAdv, + RamCS => RamCS, + RamClk => RamClk, + RamCRE => RamCRE, + RamLB => RamLB, + RamUB => RamUB, + RamWait => RamWait, + FlashRp => FlashRp, + FlashCS => FlashCS, + FlashStSts => FlashStSts, + MemAdr => MemAdr, + MemDB => MemDB, + + seg => seg, + dp => dp, + an => an, + Led => Led, + sw => sw + ); + + + ints(2) <= ps2_rx_ready or + ps2_rx_full or + ps2_tx_ready or + ps2_tx_empty or + ps2_err_nack or + ps2_err_txto or + ps2_err_rxto or + ps2_err_missed or + ps2_err_parity or + ps2_err_framing; + e_ps2: entity ps2.ps2_host_wb_opt + port map ( + rst_i => d_rst, + clk_i => d_clk, + + -- Internal access + cyc_i => ps2_cyc, + stb_i => bridge_b_stb, + we_i => bridge_b_we, + ack_o => ps2_ack, + adr_i => bridge_b_adr(2 downto 0), + dat_i => bridge_b_mosi, + dat_o => ps2_miso, + + -- Interrupt signals + rx_ready => ps2_rx_ready, + rx_full => ps2_rx_full, + tx_ready => ps2_tx_ready, + tx_empty => ps2_tx_empty, + err_nack => ps2_err_nack, + err_txto => ps2_err_txto, + err_rxto => ps2_err_rxto, + err_missed => ps2_err_missed, + err_parity => ps2_err_parity, + err_framing => ps2_err_framing, + + -- External pins + ps2_clk => PS2C, + ps2_data => PS2D + ); + + + ints(3) <= uart_rx_ready or + uart_rx_full or + uart_tx_ready or + uart_tx_empty or + uart_err_break or + uart_err_framing or + uart_err_overflow; + e_rs232: entity rs232.rs232_uart_opt + port map ( + rst_i => d_rst, + clk_i => d_clk, + + -- Internal access + cyc_i => uart_cyc, + stb_i => bridge_b_stb, + we_i => bridge_b_we, + ack_o => uart_ack, + adr_i => bridge_b_adr(2 downto 0), + dat_i => bridge_b_mosi, + dat_o => uart_miso, + + -- Interrupt signals + rx_ready => uart_rx_ready, + rx_full => uart_rx_full, + tx_ready => uart_tx_ready, + tx_empty => uart_tx_empty, + err_break => uart_err_break, + err_framing => uart_err_framing, + err_parity => uart_err_parity, + err_overflow => uart_err_overflow, + + -- External pins + tx => RsTx, + rx => RsRx + ); + + + ints(4) <= timer0_zero; + e_timer0: entity timer.timer + port map ( + rst_i => d_rst, + clk_i => d_clk, + cyc_i => timer0_cyc, + stb_i => bridge_b_stb, + we_i => bridge_b_we, + ack_o => timer0_ack, + adr_i => bridge_b_adr(1 downto 0), + dat_i => bridge_b_mosi, + dat_o => timer0_miso, + zero => timer0_zero + ); + + + ints(5) <= timer1_zero; + e_timer1: entity timer.timer + port map ( + rst_i => d_rst, + clk_i => d_clk, + cyc_i => timer1_cyc, + stb_i => bridge_b_stb, + we_i => bridge_b_we, + ack_o => timer1_ack, + adr_i => bridge_b_adr(1 downto 0), + dat_i => bridge_b_mosi, + dat_o => timer1_miso, + zero => timer1_zero + ); + +end behavioral; diff --git a/projects/cpu_0/program.sh b/projects/cpu_0/program.sh index 561bf2a..c5b760c 100755 --- a/projects/cpu_0/program.sh +++ b/projects/cpu_0/program.sh @@ -1,4 +1,4 @@ #!/usr/bin/env bash -djtgcfg -d Nexys2 -i 0 -f nexys2_opt.bit prog +djtgcfg -d Nexys2 -i 0 -f nexys2_speed.bit prog