clkscale.vhd 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. --+-----------------------------------+-------------------------------------+--
  2. --| ___ ___ | (c) 2013-2014 William R Sowerbutts |--
  3. --| ___ ___ ___ ___( _ ) / _ \ | will@sowerbutts.com |--
  4. --| / __|/ _ \ / __|_ / _ \| | | | | |--
  5. --| \__ \ (_) | (__ / / (_) | |_| | | A Z80 FPGA computer, just for fun |--
  6. --| |___/\___/ \___/___\___/ \___/ | |--
  7. --| | http://sowerbutts.com/ |--
  8. --+-----------------------------------+-------------------------------------+--
  9. --| An attempt to modulate the CPU clock so it can be slowed down without |--
  10. --| also modulating the clock to the peripherals (which would break the |--
  11. --| UART and DRAM at least). This works but not all the peripherals are |--
  12. --| currently compatible (the UART, at least, doesn't handle this well). |--
  13. --| Strongly uggest you avoid using this before you fix the peripherals. |--
  14. --+-------------------------------------------------------------------------+--
  15. library IEEE;
  16. use IEEE.STD_LOGIC_1164.ALL;
  17. use IEEE.NUMERIC_STD.ALL;
  18. entity clkscale is
  19. port ( clk : in std_logic;
  20. reset : in std_logic;
  21. cpu_address : in std_logic_vector(2 downto 0);
  22. data_in : in std_logic_vector(7 downto 0);
  23. data_out : out std_logic_vector(7 downto 0);
  24. enable : in std_logic;
  25. read_notwrite : in std_logic;
  26. clk_enable : out std_logic
  27. );
  28. end clkscale;
  29. -- a counter which counts up until it reaches a target value.
  30. -- when the counter is at the target value the clock is enabled
  31. -- for one cycle and the counter is reset. the clock is disabled
  32. -- the rest of the time. this means the clock is enabled in the
  33. -- proportion 1/(1+r) where r is the register value.
  34. architecture Behavioral of clkscale is
  35. signal counter_target : unsigned(7 downto 0) := (others => '0');
  36. signal counter_value : unsigned(7 downto 0) := (others => '0');
  37. signal output : std_logic;
  38. begin
  39. data_out <= std_logic_vector(counter_target);
  40. clk_enable <= output;
  41. clkscale_proc: process(clk)
  42. begin
  43. if rising_edge(clk) then
  44. if reset = '1' then
  45. counter_target <= to_unsigned(0, 8);
  46. counter_value <= to_unsigned(0, 8);
  47. output <= '1';
  48. else
  49. -- reset on target, enable clock for one cycle
  50. if counter_value = counter_target then
  51. counter_value <= to_unsigned(0, 8);
  52. output <= '1';
  53. else
  54. counter_value <= counter_value + 1;
  55. output <= '0';
  56. end if;
  57. -- register write
  58. if enable = '1' and read_notwrite = '0' then
  59. counter_target <= unsigned(data_in);
  60. end if;
  61. end if;
  62. end if;
  63. end process;
  64. end Behavioral;