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

Subversion Repositories sudoku

[/] [sudoku/] [trunk/] [parameterized_rtl/] [sudoku_search.v] - Blame information for rev 7

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 7 dsheffie
module sudoku_search(/*AUTOARG*/
2
   // Outputs
3
   outGrid, done, error,
4
   // Inputs
5
   clk, rst, start, inGrid
6
   );
7
 
8
   function integer my_clog2;
9
      input integer value;
10
      begin
11
         value = value-1;
12
         for (my_clog2=0; value>0; my_clog2=my_clog2+1)
13
           value = value>>1;
14
      end
15
   endfunction // for
16
 
17
   parameter LG_DEPTH = 6;
18
   parameter DIM = 3;
19
   localparam DIM_S = (DIM*DIM);
20
   localparam DIM_Q = (DIM_S*DIM_S);
21
   localparam LG_DIM_S = my_clog2(DIM_S);
22
   localparam LG_DIM_Q = my_clog2(DIM_Q);
23
 
24
 
25
   localparam DEPTH = 1 << LG_DEPTH;
26
 
27
   input clk;
28
   input rst;
29
   input start;
30
 
31
   input [(DIM_S*DIM_S*DIM_S -1):0] inGrid;
32
   output [(DIM_S*DIM_S*DIM_S - 1):0] outGrid;
33
 
34
   output         done;
35
   output         error;
36
 
37
 
38
   reg [4:0]       r_state, n_state;
39
   reg [31:0]      r_stack_pos, t_stack_pos;
40
   reg [31:0]      t_stack_addr;
41
 
42
 
43
   reg            t_write_stack, t_read_stack;
44
   reg            t_clr, t_start;
45
 
46
   reg [(LG_DIM_Q-1):0] r_minIdx, t_minIdx;
47
 
48
   reg [(DIM_S-1):0] r_cell, t_cell;
49
   wire [(DIM_S-1):0] w_ffs_mask;
50
 
51
   reg [(DIM_S*DIM_S*DIM_S-1):0] r_board;
52
   reg [(DIM_S*DIM_S*DIM_S-1):0] n_board;
53
   wire [(DIM_S*DIM_S*DIM_S -1):0] w_stack_out;
54
   reg [(DIM_S*DIM_S*DIM_S -1):0]  t_stack_in;
55
 
56
 
57
   wire [(DIM_S*DIM_S*DIM_S -1):0] s_outGrid;
58
   wire [(DIM_S-1):0]               s_outGrid2d[(DIM_Q-1):0];
59
   wire [(DIM_S*DIM_S*DIM_S -1):0] w_nGrid;
60
   reg [(DIM_S-1):0]                t_outGrid2d[(DIM_Q-1):0];
61
 
62
   reg            t_done, r_done;
63
   reg            t_error, r_error;
64
 
65
   assign done = r_done;
66
   assign error = r_error;
67
 
68
   genvar         i;
69
 
70
   assign outGrid = s_outGrid;
71
 
72
   wire [(LG_DIM_Q-1):0] w_minIdx, w_unsolvedCells;
73
 
74
   wire [(LG_DIM_S-1):0] w_minPoss;
75
   wire                  w_allDone, w_anyChanged, w_anyError, w_timeOut;
76
 
77
   generate
78
      for(i=0;i<DIM_Q;i=i+1)
79
        begin: unflatten
80
           assign s_outGrid2d[i] = s_outGrid[(DIM_S*(i+1))-1:DIM_S*i];
81
        end
82
   endgenerate
83
 
84
   integer j;
85
   always@(*)
86
     begin
87
        for(j=0;j<DIM_Q;j=j+1)
88
          begin
89
             t_outGrid2d[j] = s_outGrid2d[j];
90
          end
91
        t_outGrid2d[r_minIdx] = w_ffs_mask;
92
     end
93
 
94
   generate
95
      for(i=0;i<DIM_Q;i=i+1)
96
        begin: flatten
97
           assign w_nGrid[(DIM_S*(i+1)-1):(DIM_S*i)] = t_outGrid2d[i];
98
        end
99
   endgenerate
100
 
101
 
102
   find_first_set #(.DIM_S(DIM_S)) ffs0
103
     (
104
      .in(r_cell),
105
      .out_mask(w_ffs_mask)
106
      );
107
 
108
   always@(*)
109
     begin
110
        t_clr = 1'b0;
111
        t_start = 1'b0;
112
 
113
        t_write_stack = 1'b0;
114
        t_read_stack = 1'b0;
115
        t_stack_in = 'd0;
116
 
117
        t_stack_pos = r_stack_pos;
118
        t_stack_addr = t_stack_pos;
119
 
120
        n_state = r_state;
121
        n_board = r_board;
122
 
123
        t_minIdx = r_minIdx;
124
        t_cell = r_cell;
125
 
126
        t_done = r_done;
127
        t_error = r_error;
128
 
129
        case(r_state)
130
          /* copy input to stack */
131
          5'd0:
132
            begin
133
               if(start)
134
                 begin
135
                    t_write_stack = 1'b1;
136
                    t_stack_pos = r_stack_pos + 32'd1;
137
                    n_state = 5'd1;
138
                    t_stack_in = inGrid;
139
                 end
140
               else
141
                 begin
142
                    n_state = 5'd0;
143
                 end
144
            end
145
          /* pop state off the top of the stack,
146
           * data valid in the next state */
147
          5'd1:
148
            begin
149
               t_read_stack = 1'b1;
150
               //$display("reading new board");
151
 
152
               t_stack_pos = r_stack_pos - 32'd1;
153
               t_stack_addr = t_stack_pos;
154
 
155
               n_state = (r_stack_pos == 32'd0) ? 5'd31 : 5'd2;
156
            end
157
          /* data out of stack ram is
158
           * valid .. save in register */
159
          5'd2:
160
            begin
161
               t_clr = 1'b1;
162
 
163
               n_board = w_stack_out;
164
               n_state = 5'd3;
165
            end
166
 
167
          /* stack read..valid in r_state */
168
          5'd3:
169
            begin
170
               t_start = 1'b1;
171
               n_state = 5'd4;
172
               if(r_board === 'dx)
173
                 begin
174
                    $display("GOT X!");
175
                    $display("%b", r_board);
176
 
177
                    $finish();
178
                 end
179
            end
180
 
181
          /* wait for exact cover
182
           * hardware to complete */
183
          5'd4:
184
            begin
185
               if(w_allDone)
186
                 begin
187
                    n_state = w_anyError ? 5'd1 : 5'd8;
188
                 end
189
               else if(w_timeOut)
190
                 begin
191
                    $display("got time out, min cell in %d", w_minIdx);
192
                    t_minIdx = w_minIdx;
193
                    n_state = 5'd5;
194
                 end
195
               else
196
                 begin
197
                    n_state = 5'd4;
198
                 end
199
            end // case: 5'd4
200
 
201
          5'd5:
202
            begin
203
               /* extra cycle */
204
               t_cell = s_outGrid2d[r_minIdx];
205
               n_state = 5'd6;
206
            end
207
 
208
          /* timeOut -> push next states onto the stack */
209
          5'd6:
210
            begin
211
               /* if min cell is zero, the board is incorrect
212
                * and we have no need to push successors */
213
               if(r_cell == 9'd0)
214
                 begin
215
                    n_state = 5'd1;
216
                 end
217
               else
218
                 begin
219
                    t_cell = r_cell & (~w_ffs_mask);
220
                    t_stack_in = w_nGrid;
221
                    t_write_stack = 1'b1;
222
                    t_stack_pos = r_stack_pos + 32'd1;
223
                    n_state = (t_stack_pos == (DEPTH-1)) ? 5'd31: 5'd7;
224
                 end
225
            end
226
 
227
          5'd7:
228
            begin
229
               n_state = (r_cell == 9'd0) ? 5'd1 : 5'd6;
230
            end
231
 
232
          5'd8:
233
            begin
234
               t_done = 1'b1;
235
               n_state = 5'd8;
236
            end
237
 
238
          5'd31:
239
            begin
240
               n_state = 5'd31;
241
               t_error = 1'b1;
242
            end
243
 
244
          default:
245
            begin
246
               n_state = 5'd0;
247
            end
248
        endcase // case (r_state)
249
     end
250
 
251
 
252
   always@(posedge clk)
253
     begin
254
        if(rst)
255
          begin
256
             r_board <= 'd0;
257
             r_state <= 5'd0;
258
             r_stack_pos <= 32'd0;
259
             r_minIdx <= 7'd0;
260
             r_cell <= 9'd0;
261
             r_done <= 1'b0;
262
             r_error <= 1'b0;
263
          end
264
        else
265
          begin
266
             r_board <= n_board;
267
             r_state <= n_state;
268
             r_stack_pos <= t_stack_pos;
269
             r_minIdx <= t_minIdx;
270
             r_cell <= t_cell;
271
             r_done <= t_done;
272
             r_error <= t_error;
273
          end
274
     end // always@ (posedge clk)
275
 
276
   /* stack ram */
277
 
278
   stack_ram #(.LG_DEPTH(LG_DEPTH), .WIDTH(DIM_Q*DIM_S))
279
   stack0
280
     (
281
      // Outputs
282
      .d_out            (w_stack_out),
283
      // Inputs
284
      .clk              (clk),
285
      .w                        (t_write_stack),
286
      .addr             (t_stack_addr[(LG_DEPTH-1):0] ),
287
      .d_in             (t_stack_in)
288
      );
289
 
290
 
291
   sudoku #(.DIM(DIM))
292
   cover0 (
293
           // Outputs
294
           .outGrid             (s_outGrid),
295
           .unsolvedCells       (w_unsolvedCells),
296
           .timeOut             (w_timeOut),
297
           .allDone             (w_allDone),
298
           .anyChanged          (w_anyChanged),
299
           .anyError            (w_anyError),
300
           .minIdx              (w_minIdx),
301
           .minPoss             (w_minPoss),
302
           // Inputs
303
           .clk                 (clk),
304
           .rst                 (rst),
305
           .clr                 (t_clr),
306
           .start               (t_start),
307
           .inGrid              (r_board)
308
           );
309
 
310
endmodule // sudoku_search
311
 
312
 
313
 
314
module stack_ram(/*AUTOARG*/
315
   // Outputs
316
   d_out,
317
   // Inputs
318
   clk, w, addr, d_in
319
   );
320
   parameter LG_DEPTH = 4;
321
   parameter WIDTH = 16;
322
 
323
   localparam DEPTH = 1 << LG_DEPTH;
324
 
325
   input clk;
326
   input w;
327
   input [(LG_DEPTH-1):0] addr;
328
 
329
   input [(WIDTH-1):0] d_in;
330
   output [(WIDTH-1):0] d_out;
331
 
332
   reg [(WIDTH-1):0]     r_dout;
333
   assign d_out = r_dout;
334
 
335
   reg [(WIDTH-1):0]     mem [(DEPTH-1):0];
336
 
337
   always@(posedge clk)
338
     begin
339
        if(w)
340
          begin
341
             if(d_in == 'dx)
342
               begin
343
                  $display("pushing X!!!");
344
                  $finish();
345
               end
346
             mem[addr] <= d_in;
347
          end
348
        else
349
          begin
350
             r_dout <= mem[addr];
351
          end
352
     end // always@ (posedge clk)
353
 
354
endmodule // stack_ram
355
 
356
module find_first_set(out_mask,in);
357
   parameter DIM_S = 9;
358
 
359
   input [(DIM_S-1):0] in;
360
   output [(DIM_S-1):0] out_mask;
361
 
362
   genvar       i;
363
   wire [(DIM_S-1):0] w_fz;
364
   wire [(DIM_S-1):0] w_fzo;
365
   assign w_fz[0] = in[0];
366
   assign w_fzo[0] = in[0];
367
 
368
   assign out_mask = w_fzo;
369
 
370
   generate
371
      for(i=1;i<DIM_S;i=i+1)
372
        begin : www
373
           fz fzN (
374
                   .out(w_fzo[i]),
375
                   .f_out(w_fz[i]),
376
                   .f_in(w_fz[i-1]),
377
                   .in(in[i])
378
                   );
379
        end
380
   endgenerate
381
endmodule // find_first_set
382
 
383
module fz(/*AUTOARG*/
384
   // Outputs
385
   out, f_out,
386
   // Inputs
387
   f_in, in
388
   );
389
   input f_in;
390
   input in;
391
   output out;
392
   output f_out;
393
 
394
   assign out = in & (~f_in);
395
   assign f_out = f_in | in;
396
 
397
endmodule
398
 
399
module chk_pow2(in, out);
400
   parameter DIM_S = 9;
401
   input [(DIM_S-1):0] in;
402
   output              out;
403
 
404
   wire [(DIM_S-1):0]    w_ones = ~('d0);
405
   wire [(DIM_S-1):0]    w_m = in + w_ones;
406
   assign out = ((w_m & in) == 'd0) && (in != 'd0);
407
 
408
endmodule // one_set
409
 
410
module checkCorrect(/*AUTOARG*/
411
   // Outputs
412
   y,
413
   // Inputs
414
   in
415
   );
416
   parameter DIM_S = 9;
417
   localparam DIM_Q = DIM_S*DIM_S;
418
 
419
   input [(DIM_Q-1):0] in;
420
 
421
   output              y;
422
 
423
   wire [(DIM_S-1):0]  grid1d [(DIM_S-1):0];
424
   wire [(DIM_S-1):0]  w_set;
425
 
426
   wire [(DIM_S-1):0]  w_mask = ~('d0);
427
 
428
   wire [(DIM_S-1):0]  w_accum_or [(DIM_S-1):0];
429
   genvar              i;
430
   generate
431
     for(i=0;i<DIM_S;i=i+1)
432
        begin: accum_or
433
           if(i==0)
434
             begin
435
                assign w_accum_or[i] = grid1d[i];
436
             end
437
           else
438
             begin
439
                assign w_accum_or[i] = w_accum_or[i-1] | grid1d[i];
440
             end
441
        end
442
   endgenerate
443
 
444
   wire [(DIM_S-1):0] w_gridOR = w_accum_or[(DIM_S-1)];
445
 
446
   wire       w_allSet = (w_gridOR == w_mask);
447
   wire       w_allAssign = (w_set == w_mask);
448
 
449
   assign y = w_allSet & w_allAssign;
450
 
451
   generate
452
      for(i=0;i<DIM_S;i=i+1)
453
        begin: unflatten
454
           assign grid1d[i] = in[(DIM_S*(i+1))-1:DIM_S*i];
455
           chk_pow2 #(.DIM_S(DIM_S)) pchk (.in(grid1d[i]), .out(w_set[i]));
456
        end
457
   endgenerate
458
endmodule // checkCorrect
459
 

powered by: WebSVN 2.1.0

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