OpenCores
URL https://opencores.org/ocsvn/zipcpu/zipcpu/trunk

Subversion Repositories zipcpu

[/] [zipcpu/] [trunk/] [rtl/] [core/] [slowmpy.v] - Blame information for rev 209

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 209 dgisselq
////////////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    slowmpy.v
4
//
5
// Project:     Zip CPU -- a small, lightweight, RISC CPU soft core
6
//
7
// Purpose:     This is a signed (OPT_SIGNED=1) or unsigned (OPT_SIGNED=0)
8
//              multiply designed for low logic and slow data signals.  It
9
//      takes one clock per bit plus two more to complete the multiply.
10
//
11
//      The OPT_SIGNED version of this algorithm was found on Wikipedia at
12
//      https://en.wikipedia.org/wiki/Binary_multiplier.
13
//
14
// Creator:     Dan Gisselquist, Ph.D.
15
//              Gisselquist Technology, LLC
16
//
17
////////////////////////////////////////////////////////////////////////////////
18
//
19
// Copyright (C) 2018-2019, Gisselquist Technology, LLC
20
//
21
// This program is free software (firmware): you can redistribute it and/or
22
// modify it under the terms of  the GNU General Public License as published
23
// by the Free Software Foundation, either version 3 of the License, or (at
24
// your option) any later version.
25
//
26
// This program is distributed in the hope that it will be useful, but WITHOUT
27
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
28
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
29
// for more details.
30
//
31
// You should have received a copy of the GNU General Public License along
32
// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no
33
// target there if the PDF file isn't present.)  If not, see
34
// <http://www.gnu.org/licenses/> for a copy.
35
//
36
// License:     GPL, v3, as defined and found on www.gnu.org,
37
//              http://www.gnu.org/licenses/gpl.html
38
//
39
//
40
////////////////////////////////////////////////////////////////////////////////
41
//
42
//
43
`default_nettype        none
44
//
45
//
46
module  slowmpy(i_clk, i_reset, i_stb, i_a, i_b, i_aux, o_busy,
47
                o_done, o_p, o_aux);
48
        parameter                       LGNA = 6;
49
        parameter       [LGNA:0] NA = 33;
50
        parameter       [0:0]             OPT_SIGNED = 1'b1;
51
        localparam      NB = NA;        // Must be = NA for OPT_SIGNED to work
52
        //
53
        input   wire    i_clk, i_reset;
54
        //
55
        input   wire    i_stb;
56
        input   wire    signed  [(NA-1):0]       i_a;
57
        input   wire    signed  [(NB-1):0]       i_b;
58
        input   wire                            i_aux;
59
        output  reg                             o_busy, o_done;
60
        output  reg     signed  [(NA+NB-1):0]    o_p;
61
        output  reg                             o_aux;
62
 
63
        reg     [LGNA-1:0]       count;
64
        reg     [NA-1:0] p_a;
65
        reg     [NB-1:0] p_b;
66
        reg     [NA+NB-1:0]      partial;
67
        reg                     aux;
68
 
69
        reg     almost_done;
70
 
71
        wire    pre_done;
72
        assign  pre_done = (count == 0);
73
        initial almost_done = 1'b0;
74
        always @(posedge i_clk)
75
                almost_done <= (!i_reset)&&(o_busy)&&(pre_done);
76
 
77
        initial aux    = 0;
78
        initial o_done = 0;
79
        initial o_busy = 0;
80
        always @(posedge i_clk)
81
        if (i_reset)
82
        begin
83
                aux    <= 0;
84
                o_done <= 0;
85
                o_busy <= 0;
86
        end else if ((!o_busy)&&(i_stb))
87
        begin
88
                o_done <= 0;
89
                o_busy <= 1;
90
                aux    <= i_aux;
91
        end else if ((o_busy)&&(almost_done))
92
        begin
93
                o_done <= 1;
94
                o_busy <= 0;
95
        end else
96
                o_done <= 0;
97
 
98
        wire    [NA-1:0] pwire;
99
        assign  pwire = (p_b[0] ? p_a : 0);
100
 
101
        always @(posedge i_clk)
102
        if (!o_busy)
103
        begin
104
                count <= NA[LGNA-1:0]-1;
105
                partial <= 0;
106
                p_a <= i_a;
107
                p_b <= i_b;
108
        end else begin
109
                p_b <= (p_b >> 1);
110
                // partial[NA+NB-1:NB] <= partial[NA+NB
111
                partial[NB-2:0] <= partial[NB-1:1];
112
                if ((OPT_SIGNED)&&(pre_done))
113
                        partial[NA+NB-1:NB-1] <= { 1'b0, partial[NA+NB-1:NB]} +
114
                                { 1'b0, pwire[NA-1], ~pwire[NA-2:0] };
115
                else if (OPT_SIGNED)
116
                        partial[NA+NB-1:NB-1] <= {1'b0,partial[NA+NB-1:NB]} +
117
                                { 1'b0, !pwire[NA-1], pwire[NA-2:0] };
118
                else
119
                        partial[NA+NB-1:NB-1] <= {1'b0, partial[NA+NB-1:NB]}
120
                                + ((p_b[0]) ? {1'b0,p_a} : 0);
121
                count <= count - 1;
122
        end
123
 
124
        always @(posedge i_clk)
125
        if (almost_done)
126
        begin
127
                if (OPT_SIGNED)
128
                        o_p   <= partial[NA+NB-1:0]
129
                                + {1'b1,{(NA-2){1'b0}},1'b1, {(NB){1'b0}}};
130
                else
131
                        o_p   <= partial[NA+NB-1:0];
132
                o_aux <= aux;
133
        end
134
 
135
`ifdef  FORMAL
136
`define ASSERT  assert
137
`ifdef  SLOWMPY
138
`define ASSUME  assume
139
`else
140
`define ASSUME  assert
141
`endif
142
 
143
        reg     f_past_valid;
144
        initial f_past_valid = 1'b0;
145
        always @(posedge i_clk)
146
                f_past_valid <= 1'b1;
147
        initial assume(i_reset);
148
        always @(*)
149
        if (!f_past_valid)
150
                `ASSUME(i_reset);
151
 
152
        always @(posedge i_clk)
153
        if ((!f_past_valid)||($past(i_reset)))
154
        begin
155
                `ASSERT(almost_done == 0);
156
                `ASSERT(o_done == 0);
157
                `ASSERT(o_busy == 0);
158
                `ASSERT(aux == 0);
159
        end
160
 
161
        // Assumptions about our inputs
162
        always @(posedge i_clk)
163
        if ((f_past_valid)&&(!$past(i_reset))&&($past(i_stb))&&($past(o_busy)))
164
        begin
165
                `ASSUME(i_stb);
166
                `ASSUME($stable(i_a));
167
                `ASSUME($stable(i_b));
168
        end
169
 
170
        //
171
        // For now, just formally verify our internal signaling
172
        //
173
 
174
        always @(posedge i_clk)
175
                `ASSERT(almost_done == (o_busy&&(&count)));
176
 
177
        always @(*)
178
                if (!(&count[LGNA-1:1])||(count[0]))
179
                        `ASSERT(!o_done);
180
 
181
        always @(posedge i_clk)
182
        if (o_done)
183
                `ASSERT(!o_busy);
184
        always @(posedge i_clk)
185
        if (!o_busy)
186
                `ASSERT(!almost_done);
187
 
188
        reg     [NA-1:0] f_a, f_b;
189
        always @(posedge i_clk)
190
        if ((i_stb)&&(!o_busy))
191
        begin
192
                f_a <= i_a;
193
                f_b <= i_b;
194
        end
195
 
196
        always @(*)
197
        if (o_done)
198
        begin
199
                if ((f_a == 0)||(f_b == 0))
200
                        `ASSERT(o_p == 0);
201
                else
202
                        `ASSERT(o_p[NA+NB-1] == f_a[NA-1] ^ f_b[NA-1]);
203
        end
204
 
205
        always @(posedge i_clk)
206
                cover(o_done);
207
 
208
        reg     f_past_done;
209
        initial f_past_done = 1'b0;
210
        always @(posedge i_clk)
211
        if (o_done)
212
                f_past_done = 1'b1;
213
 
214
        always @(posedge i_clk)
215
                cover((o_done)&&(f_past_done));
216
`endif
217
endmodule

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.