-
Notifications
You must be signed in to change notification settings - Fork 1
/
per2bpm.vhd
89 lines (78 loc) · 3.04 KB
/
per2bpm.vhd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
-- The TapTempo Project
-- Created on : 21/11/2020
-- Author : Fabien Marteau <mail@fabienm.eu>
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.all;
library work;
use work.taptempo_pkg.all;
Entity per2bpm is
port(
-- clock and reset
clk_i : in std_logic;
rst_i : in std_logic;
-- inputs
btn_per_i : in std_logic_vector(BTN_PER_SIZE-1 downto 0);
btn_per_valid : in std_logic;
-- outputs
bpm_o : out std_logic_vector(BPM_SIZE-1 downto 0);
bpm_valid : out std_logic
);
end entity;
Architecture per2bpm_1 of per2bpm is
constant DIVIDENTWIDTH : natural := log2ceil(1 + (MIN_US/TP_CYCLE)*1000);
constant REGWIDTH : natural := BTN_PER_SIZE + DIVIDENTWIDTH;
signal divisor : unsigned(REGWIDTH-1 downto 0);
signal remainder : unsigned(REGWIDTH-1 downto 0);
signal quotient : unsigned(REGWIDTH-1 downto 0);
signal ctrlcnt : natural range 0 to DIVIDENTWIDTH + 1;
type t_state is (s_init, s_compute, s_result);
signal state_reg : t_state;
begin
div_process : process(clk_i, rst_i)
constant ZEROS : unsigned(DIVIDENTWIDTH-1 downto 0) := (others => '0');
begin
if rst_i = '1' then
divisor <= (others => '0');
remainder <= (others => '0');
quotient <= (others => '0');
ctrlcnt <= DIVIDENTWIDTH;
state_reg <= s_init;
elsif rising_edge(clk_i) then
case state_reg is
when s_init =>
if (to_integer(unsigned(btn_per_i)) < BTN_PER_MIN) then
divisor <= to_unsigned(BTN_PER_MIN, BTN_PER_SIZE) & ZEROS;
else
divisor <= unsigned(btn_per_i) & ZEROS;
end if;
remainder <= to_unsigned((MIN_US / TP_CYCLE) * 1000, REGWIDTH);
quotient <= (others => '0');
ctrlcnt <= DIVIDENTWIDTH;
if (btn_per_valid = '1') then
state_reg <= s_compute;
end if;
when s_compute =>
if divisor <= remainder then
remainder <= remainder - divisor;
quotient <= quotient(REGWIDTH-2 downto 0) & "1";
else
quotient <= quotient(REGWIDTH-2 downto 0) & "0";
end if;
divisor <= "0" & divisor(REGWIDTH-1 downto 1);
if (ctrlcnt = 0) then
state_reg <= s_result;
else
ctrlcnt <= ctrlcnt - 1;
state_reg <= s_compute;
end if;
when s_result =>
state_reg <= s_init;
when others =>
state_reg <= s_init;
end case;
end if;
end process div_process;
bpm_o <= std_logic_vector(quotient(BPM_SIZE-1 downto 0));
bpm_valid <= '1' when state_reg = s_result else '0';
end Architecture per2bpm_1;