Created
August 6, 2025 17:17
-
-
Save pavel-kirienko/e5fa3ad59dfe67ab8a2ed91023f187de to your computer and use it in GitHub Desktop.
10-bit sin(x) lookup table in Verilog based on a 256x9-bit ROM cell
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// Stateless, purely combinational sin(x) look-up table. Can be used as the phase-to-amplitude converter of an NCO. | |
/// It stores 256 9-bit items in a look-up table representing the first quarter of the wave. | |
/// The input x is expected to be normalized into [0, 1024) that maps to [0, 2 pi). | |
/// The signed output is normalized into [-511, +511] (sic! -512 not used). | |
module sine_lookup_1024( | |
input wire [9:0] x, | |
output wire signed [9:0] out | |
); | |
reg [8:0] entry; // Not an actual register, just a wire assignable from the always block. | |
assign out = x[9] ? -$signed({1'b0, entry}) : $signed({1'b0, entry}); // The MSb represents the half-wave index. | |
wire [7:0] index = x[8] ? ~x[7:0] : x[7:0]; // The second-to-MSb is set if the quarter needs to be inverted. | |
always @* begin // always_comb | |
// The LUT was generated in Python: | |
// half_period_table = [round(math.sin(math.pi * 0.5 * (x / 256)) * 511) for x in range(256)] | |
// for i,e in enumerate(half_period_table): | |
// print(f"{i:<4d}: entry = {e:4d};") | |
case(index) | |
0 : entry = 0; | |
1 : entry = 3; | |
2 : entry = 6; | |
3 : entry = 9; | |
4 : entry = 13; | |
5 : entry = 16; | |
6 : entry = 19; | |
7 : entry = 22; | |
8 : entry = 25; | |
9 : entry = 28; | |
10 : entry = 31; | |
11 : entry = 34; | |
12 : entry = 38; | |
13 : entry = 41; | |
14 : entry = 44; | |
15 : entry = 47; | |
16 : entry = 50; | |
17 : entry = 53; | |
18 : entry = 56; | |
19 : entry = 59; | |
20 : entry = 63; | |
21 : entry = 66; | |
22 : entry = 69; | |
23 : entry = 72; | |
24 : entry = 75; | |
25 : entry = 78; | |
26 : entry = 81; | |
27 : entry = 84; | |
28 : entry = 87; | |
29 : entry = 90; | |
30 : entry = 94; | |
31 : entry = 97; | |
32 : entry = 100; | |
33 : entry = 103; | |
34 : entry = 106; | |
35 : entry = 109; | |
36 : entry = 112; | |
37 : entry = 115; | |
38 : entry = 118; | |
39 : entry = 121; | |
40 : entry = 124; | |
41 : entry = 127; | |
42 : entry = 130; | |
43 : entry = 133; | |
44 : entry = 136; | |
45 : entry = 139; | |
46 : entry = 142; | |
47 : entry = 145; | |
48 : entry = 148; | |
49 : entry = 151; | |
50 : entry = 154; | |
51 : entry = 157; | |
52 : entry = 160; | |
53 : entry = 163; | |
54 : entry = 166; | |
55 : entry = 169; | |
56 : entry = 172; | |
57 : entry = 175; | |
58 : entry = 178; | |
59 : entry = 181; | |
60 : entry = 184; | |
61 : entry = 187; | |
62 : entry = 190; | |
63 : entry = 193; | |
64 : entry = 196; | |
65 : entry = 198; | |
66 : entry = 201; | |
67 : entry = 204; | |
68 : entry = 207; | |
69 : entry = 210; | |
70 : entry = 213; | |
71 : entry = 216; | |
72 : entry = 218; | |
73 : entry = 221; | |
74 : entry = 224; | |
75 : entry = 227; | |
76 : entry = 230; | |
77 : entry = 233; | |
78 : entry = 235; | |
79 : entry = 238; | |
80 : entry = 241; | |
81 : entry = 244; | |
82 : entry = 246; | |
83 : entry = 249; | |
84 : entry = 252; | |
85 : entry = 255; | |
86 : entry = 257; | |
87 : entry = 260; | |
88 : entry = 263; | |
89 : entry = 265; | |
90 : entry = 268; | |
91 : entry = 271; | |
92 : entry = 273; | |
93 : entry = 276; | |
94 : entry = 279; | |
95 : entry = 281; | |
96 : entry = 284; | |
97 : entry = 286; | |
98 : entry = 289; | |
99 : entry = 292; | |
100 : entry = 294; | |
101 : entry = 297; | |
102 : entry = 299; | |
103 : entry = 302; | |
104 : entry = 304; | |
105 : entry = 307; | |
106 : entry = 309; | |
107 : entry = 312; | |
108 : entry = 314; | |
109 : entry = 317; | |
110 : entry = 319; | |
111 : entry = 322; | |
112 : entry = 324; | |
113 : entry = 327; | |
114 : entry = 329; | |
115 : entry = 331; | |
116 : entry = 334; | |
117 : entry = 336; | |
118 : entry = 338; | |
119 : entry = 341; | |
120 : entry = 343; | |
121 : entry = 345; | |
122 : entry = 348; | |
123 : entry = 350; | |
124 : entry = 352; | |
125 : entry = 355; | |
126 : entry = 357; | |
127 : entry = 359; | |
128 : entry = 361; | |
129 : entry = 364; | |
130 : entry = 366; | |
131 : entry = 368; | |
132 : entry = 370; | |
133 : entry = 372; | |
134 : entry = 374; | |
135 : entry = 377; | |
136 : entry = 379; | |
137 : entry = 381; | |
138 : entry = 383; | |
139 : entry = 385; | |
140 : entry = 387; | |
141 : entry = 389; | |
142 : entry = 391; | |
143 : entry = 393; | |
144 : entry = 395; | |
145 : entry = 397; | |
146 : entry = 399; | |
147 : entry = 401; | |
148 : entry = 403; | |
149 : entry = 405; | |
150 : entry = 407; | |
151 : entry = 409; | |
152 : entry = 410; | |
153 : entry = 412; | |
154 : entry = 414; | |
155 : entry = 416; | |
156 : entry = 418; | |
157 : entry = 420; | |
158 : entry = 421; | |
159 : entry = 423; | |
160 : entry = 425; | |
161 : entry = 427; | |
162 : entry = 428; | |
163 : entry = 430; | |
164 : entry = 432; | |
165 : entry = 433; | |
166 : entry = 435; | |
167 : entry = 437; | |
168 : entry = 438; | |
169 : entry = 440; | |
170 : entry = 441; | |
171 : entry = 443; | |
172 : entry = 445; | |
173 : entry = 446; | |
174 : entry = 448; | |
175 : entry = 449; | |
176 : entry = 451; | |
177 : entry = 452; | |
178 : entry = 454; | |
179 : entry = 455; | |
180 : entry = 456; | |
181 : entry = 458; | |
182 : entry = 459; | |
183 : entry = 461; | |
184 : entry = 462; | |
185 : entry = 463; | |
186 : entry = 465; | |
187 : entry = 466; | |
188 : entry = 467; | |
189 : entry = 468; | |
190 : entry = 470; | |
191 : entry = 471; | |
192 : entry = 472; | |
193 : entry = 473; | |
194 : entry = 474; | |
195 : entry = 476; | |
196 : entry = 477; | |
197 : entry = 478; | |
198 : entry = 479; | |
199 : entry = 480; | |
200 : entry = 481; | |
201 : entry = 482; | |
202 : entry = 483; | |
203 : entry = 484; | |
204 : entry = 485; | |
205 : entry = 486; | |
206 : entry = 487; | |
207 : entry = 488; | |
208 : entry = 489; | |
209 : entry = 490; | |
210 : entry = 491; | |
211 : entry = 492; | |
212 : entry = 492; | |
213 : entry = 493; | |
214 : entry = 494; | |
215 : entry = 495; | |
216 : entry = 496; | |
217 : entry = 496; | |
218 : entry = 497; | |
219 : entry = 498; | |
220 : entry = 499; | |
221 : entry = 499; | |
222 : entry = 500; | |
223 : entry = 501; | |
224 : entry = 501; | |
225 : entry = 502; | |
226 : entry = 502; | |
227 : entry = 503; | |
228 : entry = 503; | |
229 : entry = 504; | |
230 : entry = 505; | |
231 : entry = 505; | |
232 : entry = 505; | |
233 : entry = 506; | |
234 : entry = 506; | |
235 : entry = 507; | |
236 : entry = 507; | |
237 : entry = 508; | |
238 : entry = 508; | |
239 : entry = 508; | |
240 : entry = 509; | |
241 : entry = 509; | |
242 : entry = 509; | |
243 : entry = 509; | |
244 : entry = 510; | |
245 : entry = 510; | |
246 : entry = 510; | |
247 : entry = 510; | |
248 : entry = 510; | |
249 : entry = 511; | |
250 : entry = 511; | |
251 : entry = 511; | |
252 : entry = 511; | |
253 : entry = 511; | |
254 : entry = 511; | |
255 : entry = 511; | |
default: entry = 9'bxxxxxxxxx; // Sentry to ensure we don't infer a latch. | |
endcase | |
end | |
endmodule |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// iverilog -Wall -Wno-timescale -y. sine_lookup_1024_tb.v && vvp a.out > sine.tab | |
/// Then analyze the dump using Jupyter or whatever. | |
module sine_lookup_1024_tb; | |
reg [9:0] x; | |
wire signed [9:0] out; | |
sine_lookup_1024 sine (x, out); | |
integer i; | |
initial begin | |
$dumpfile("sine_lookup_1024.vcd"); | |
$dumpvars(); | |
for (i = 0; i < 1024; i++) begin | |
# 1 x = i[9:0]; | |
# 1 | |
$display(x, " ", out); | |
end | |
# 1 $finish(); | |
end | |
endmodule |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment