1library ieee;
2use ieee.std_logic_1164.all;
3
4entity mod5x is
5    generic (
6        NBITS:  natural := 13
7    );
8    port (
9        clk:        in  std_logic;
10        dividend:   in  std_logic_vector (NBITS - 1 downto 0);
11        load:       in  std_logic;
12        remzero:    out std_logic
13    );
14end entity;
15
16architecture foo of mod5x is
17    -- type remains is (r0, r1, r2, r3, r4); -- remainder values
18    -- type remain_array is array (NBITS downto 0) of remains;
19    -- signal remaindr:    remain_array := (others => r0);
20--     type branch is array (remains, bit) of remains;
21-- -- Dave Tweeds state transition table:
22--     constant br_table:  branch := ( r0 => ('0' => r0, '1' => r1),
23--                                     r1 => ('0' => r2, '1' => r3),
24--                                     r2 => ('0' => r4, '1' => r0),
25--                                     r3 => ('0' => r1, '1' => r2),
26--                                     r4 => ('0' => r3, '1' => r4)
27--                                   );
28    signal is_zero:     std_logic;
29begin
30
31do_ig:
32    process (dividend)
33        type remains is (r0, r1, r2, r3, r4); -- remainder values
34        type remain_array is array (NBITS downto 0) of remains;
35        variable tbit:      bit_vector(NBITS - 1 downto 0);
36        variable remaind:   remain_array := (others => r0);
37        type branch is array (remains, bit) of remains;
38    -- Dave Tweeds state transition table:
39        constant br_table:  branch := ( r0 => ('0' => r0, '1' => r1),
40                                        r1 => ('0' => r2, '1' => r3),
41                                        r2 => ('0' => r4, '1' => r0),
42                                        r3 => ('0' => r1, '1' => r2),
43                                        r4 => ('0' => r3, '1' => r4)
44                                      );
45    begin
46do_mod:
47        for i in NBITS - 1 downto 0 loop
48             tbit := to_bitvector(dividend);
49             remaind(i) := br_table(remaind(i + 1),tbit(i));
50         end loop;
51        -- remaindr <= remaind;   -- all values for waveform display
52        if remaind(0) = r0 then
53            is_zero <= '1';
54        else
55            is_zero <= '0';
56        end if;
57    end process;
58
59remainders:
60    process (clk)
61    begin
62        if rising_edge(clk) then
63            remzero <= is_zero
64            ;
65        end if;
66    end process;
67end architecture;
68
69library ieee;
70use ieee.std_logic_1164.all;
71use ieee.numeric_std.all;
72
73entity mod5x_tb is
74end entity;
75
76architecture foo of mod5x_tb is
77    constant NBITS:    integer range 0 to 13 := 8;
78    signal clk:        std_logic := '0';
79    signal dividend:   std_logic_vector (NBITS - 1 downto 0);
80    signal load:       std_logic := '0';
81
82    signal remzero:    std_logic;
83
84    signal psample:    std_ulogic;
85    signal sample:     std_ulogic;
86    signal done:       boolean;
87begin
88DUT:
89    entity work.mod5x
90        generic map  (NBITS)
91        port map (
92            clk => clk,
93            dividend => dividend,
94            load => load,
95            remzero => remzero
96        );
97CLOCK:
98    process
99    begin
100        wait for 5 ns;
101        clk <= not clk;
102        if done'delayed(30 ns) then
103            wait;
104        end if;
105    end process;
106STIMULI:
107    process
108    begin
109        for i in 0 to 2 ** NBITS - 1 loop
110            wait for 10 ns;
111            dividend <= std_logic_vector(to_unsigned(i,NBITS));
112            wait for 10 ns;
113            load <= '1';
114            wait for 10 ns;
115            load <= '0';
116        end loop;
117        wait for 15 ns;
118        done <= true;
119        wait;
120    end process;
121
122SAMPLER:
123    process (clk)
124    begin
125        if rising_edge(clk) then
126            psample <= load;
127            sample <= psample;
128        end if;
129    end process;
130
131MONITOR:
132    process (sample)
133        variable i:     integer;
134        variable rem5:  integer;
135    begin
136        if rising_edge (sample) then
137            i := to_integer(unsigned(dividend));
138            rem5 := i mod 5;
139            if rem5 = 0 and remzero /= '1' then
140                assert rem5 = 0 and remzero = '1'
141                    report LF & HT &
142                        "i = " & integer'image(i) &
143                        " rem 5 expected " & integer'image(rem5) &
144                        " remzero = " & std_ulogic'image(remzero)
145                    SEVERITY ERROR;
146            end if;
147        end if;
148    end process;
149
150end architecture;