URL
https://opencores.org/ocsvn/sudoku/sudoku/trunk
Subversion Repositories sudoku
Compare Revisions
- This comparison shows the changes necessary to convert path
/sudoku/trunk
- from Rev 5 to Rev 7
- ↔ Reverse comparison
Rev 5 → Rev 7
/parameterized_rtl/sudoku_search.v
0,0 → 1,459
module sudoku_search(/*AUTOARG*/ |
// Outputs |
outGrid, done, error, |
// Inputs |
clk, rst, start, inGrid |
); |
|
function integer my_clog2; |
input integer value; |
begin |
value = value-1; |
for (my_clog2=0; value>0; my_clog2=my_clog2+1) |
value = value>>1; |
end |
endfunction // for |
|
parameter LG_DEPTH = 6; |
parameter DIM = 3; |
localparam DIM_S = (DIM*DIM); |
localparam DIM_Q = (DIM_S*DIM_S); |
localparam LG_DIM_S = my_clog2(DIM_S); |
localparam LG_DIM_Q = my_clog2(DIM_Q); |
|
|
localparam DEPTH = 1 << LG_DEPTH; |
|
input clk; |
input rst; |
input start; |
|
input [(DIM_S*DIM_S*DIM_S -1):0] inGrid; |
output [(DIM_S*DIM_S*DIM_S - 1):0] outGrid; |
|
output done; |
output error; |
|
|
reg [4:0] r_state, n_state; |
reg [31:0] r_stack_pos, t_stack_pos; |
reg [31:0] t_stack_addr; |
|
|
reg t_write_stack, t_read_stack; |
reg t_clr, t_start; |
|
reg [(LG_DIM_Q-1):0] r_minIdx, t_minIdx; |
|
reg [(DIM_S-1):0] r_cell, t_cell; |
wire [(DIM_S-1):0] w_ffs_mask; |
|
reg [(DIM_S*DIM_S*DIM_S-1):0] r_board; |
reg [(DIM_S*DIM_S*DIM_S-1):0] n_board; |
wire [(DIM_S*DIM_S*DIM_S -1):0] w_stack_out; |
reg [(DIM_S*DIM_S*DIM_S -1):0] t_stack_in; |
|
|
wire [(DIM_S*DIM_S*DIM_S -1):0] s_outGrid; |
wire [(DIM_S-1):0] s_outGrid2d[(DIM_Q-1):0]; |
wire [(DIM_S*DIM_S*DIM_S -1):0] w_nGrid; |
reg [(DIM_S-1):0] t_outGrid2d[(DIM_Q-1):0]; |
|
reg t_done, r_done; |
reg t_error, r_error; |
|
assign done = r_done; |
assign error = r_error; |
|
genvar i; |
|
assign outGrid = s_outGrid; |
|
wire [(LG_DIM_Q-1):0] w_minIdx, w_unsolvedCells; |
|
wire [(LG_DIM_S-1):0] w_minPoss; |
wire w_allDone, w_anyChanged, w_anyError, w_timeOut; |
|
generate |
for(i=0;i<DIM_Q;i=i+1) |
begin: unflatten |
assign s_outGrid2d[i] = s_outGrid[(DIM_S*(i+1))-1:DIM_S*i]; |
end |
endgenerate |
|
integer j; |
always@(*) |
begin |
for(j=0;j<DIM_Q;j=j+1) |
begin |
t_outGrid2d[j] = s_outGrid2d[j]; |
end |
t_outGrid2d[r_minIdx] = w_ffs_mask; |
end |
|
generate |
for(i=0;i<DIM_Q;i=i+1) |
begin: flatten |
assign w_nGrid[(DIM_S*(i+1)-1):(DIM_S*i)] = t_outGrid2d[i]; |
end |
endgenerate |
|
|
find_first_set #(.DIM_S(DIM_S)) ffs0 |
( |
.in(r_cell), |
.out_mask(w_ffs_mask) |
); |
|
always@(*) |
begin |
t_clr = 1'b0; |
t_start = 1'b0; |
|
t_write_stack = 1'b0; |
t_read_stack = 1'b0; |
t_stack_in = 'd0; |
|
t_stack_pos = r_stack_pos; |
t_stack_addr = t_stack_pos; |
|
n_state = r_state; |
n_board = r_board; |
|
t_minIdx = r_minIdx; |
t_cell = r_cell; |
|
t_done = r_done; |
t_error = r_error; |
|
case(r_state) |
/* copy input to stack */ |
5'd0: |
begin |
if(start) |
begin |
t_write_stack = 1'b1; |
t_stack_pos = r_stack_pos + 32'd1; |
n_state = 5'd1; |
t_stack_in = inGrid; |
end |
else |
begin |
n_state = 5'd0; |
end |
end |
/* pop state off the top of the stack, |
* data valid in the next state */ |
5'd1: |
begin |
t_read_stack = 1'b1; |
//$display("reading new board"); |
|
t_stack_pos = r_stack_pos - 32'd1; |
t_stack_addr = t_stack_pos; |
|
n_state = (r_stack_pos == 32'd0) ? 5'd31 : 5'd2; |
end |
/* data out of stack ram is |
* valid .. save in register */ |
5'd2: |
begin |
t_clr = 1'b1; |
|
n_board = w_stack_out; |
n_state = 5'd3; |
end |
|
/* stack read..valid in r_state */ |
5'd3: |
begin |
t_start = 1'b1; |
n_state = 5'd4; |
if(r_board === 'dx) |
begin |
$display("GOT X!"); |
$display("%b", r_board); |
|
$finish(); |
end |
end |
|
/* wait for exact cover |
* hardware to complete */ |
5'd4: |
begin |
if(w_allDone) |
begin |
n_state = w_anyError ? 5'd1 : 5'd8; |
end |
else if(w_timeOut) |
begin |
$display("got time out, min cell in %d", w_minIdx); |
t_minIdx = w_minIdx; |
n_state = 5'd5; |
end |
else |
begin |
n_state = 5'd4; |
end |
end // case: 5'd4 |
|
5'd5: |
begin |
/* extra cycle */ |
t_cell = s_outGrid2d[r_minIdx]; |
n_state = 5'd6; |
end |
|
/* timeOut -> push next states onto the stack */ |
5'd6: |
begin |
/* if min cell is zero, the board is incorrect |
* and we have no need to push successors */ |
if(r_cell == 9'd0) |
begin |
n_state = 5'd1; |
end |
else |
begin |
t_cell = r_cell & (~w_ffs_mask); |
t_stack_in = w_nGrid; |
t_write_stack = 1'b1; |
t_stack_pos = r_stack_pos + 32'd1; |
n_state = (t_stack_pos == (DEPTH-1)) ? 5'd31: 5'd7; |
end |
end |
|
5'd7: |
begin |
n_state = (r_cell == 9'd0) ? 5'd1 : 5'd6; |
end |
|
5'd8: |
begin |
t_done = 1'b1; |
n_state = 5'd8; |
end |
|
5'd31: |
begin |
n_state = 5'd31; |
t_error = 1'b1; |
end |
|
default: |
begin |
n_state = 5'd0; |
end |
endcase // case (r_state) |
end |
|
|
always@(posedge clk) |
begin |
if(rst) |
begin |
r_board <= 'd0; |
r_state <= 5'd0; |
r_stack_pos <= 32'd0; |
r_minIdx <= 7'd0; |
r_cell <= 9'd0; |
r_done <= 1'b0; |
r_error <= 1'b0; |
end |
else |
begin |
r_board <= n_board; |
r_state <= n_state; |
r_stack_pos <= t_stack_pos; |
r_minIdx <= t_minIdx; |
r_cell <= t_cell; |
r_done <= t_done; |
r_error <= t_error; |
end |
end // always@ (posedge clk) |
|
/* stack ram */ |
|
stack_ram #(.LG_DEPTH(LG_DEPTH), .WIDTH(DIM_Q*DIM_S)) |
stack0 |
( |
// Outputs |
.d_out (w_stack_out), |
// Inputs |
.clk (clk), |
.w (t_write_stack), |
.addr (t_stack_addr[(LG_DEPTH-1):0] ), |
.d_in (t_stack_in) |
); |
|
|
sudoku #(.DIM(DIM)) |
cover0 ( |
// Outputs |
.outGrid (s_outGrid), |
.unsolvedCells (w_unsolvedCells), |
.timeOut (w_timeOut), |
.allDone (w_allDone), |
.anyChanged (w_anyChanged), |
.anyError (w_anyError), |
.minIdx (w_minIdx), |
.minPoss (w_minPoss), |
// Inputs |
.clk (clk), |
.rst (rst), |
.clr (t_clr), |
.start (t_start), |
.inGrid (r_board) |
); |
|
endmodule // sudoku_search |
|
|
|
module stack_ram(/*AUTOARG*/ |
// Outputs |
d_out, |
// Inputs |
clk, w, addr, d_in |
); |
parameter LG_DEPTH = 4; |
parameter WIDTH = 16; |
|
localparam DEPTH = 1 << LG_DEPTH; |
|
input clk; |
input w; |
input [(LG_DEPTH-1):0] addr; |
|
input [(WIDTH-1):0] d_in; |
output [(WIDTH-1):0] d_out; |
|
reg [(WIDTH-1):0] r_dout; |
assign d_out = r_dout; |
|
reg [(WIDTH-1):0] mem [(DEPTH-1):0]; |
|
always@(posedge clk) |
begin |
if(w) |
begin |
if(d_in == 'dx) |
begin |
$display("pushing X!!!"); |
$finish(); |
end |
mem[addr] <= d_in; |
end |
else |
begin |
r_dout <= mem[addr]; |
end |
end // always@ (posedge clk) |
|
endmodule // stack_ram |
|
module find_first_set(out_mask,in); |
parameter DIM_S = 9; |
|
input [(DIM_S-1):0] in; |
output [(DIM_S-1):0] out_mask; |
|
genvar i; |
wire [(DIM_S-1):0] w_fz; |
wire [(DIM_S-1):0] w_fzo; |
assign w_fz[0] = in[0]; |
assign w_fzo[0] = in[0]; |
|
assign out_mask = w_fzo; |
|
generate |
for(i=1;i<DIM_S;i=i+1) |
begin : www |
fz fzN ( |
.out(w_fzo[i]), |
.f_out(w_fz[i]), |
.f_in(w_fz[i-1]), |
.in(in[i]) |
); |
end |
endgenerate |
endmodule // find_first_set |
|
module fz(/*AUTOARG*/ |
// Outputs |
out, f_out, |
// Inputs |
f_in, in |
); |
input f_in; |
input in; |
output out; |
output f_out; |
|
assign out = in & (~f_in); |
assign f_out = f_in | in; |
|
endmodule |
|
module chk_pow2(in, out); |
parameter DIM_S = 9; |
input [(DIM_S-1):0] in; |
output out; |
|
wire [(DIM_S-1):0] w_ones = ~('d0); |
wire [(DIM_S-1):0] w_m = in + w_ones; |
assign out = ((w_m & in) == 'd0) && (in != 'd0); |
|
endmodule // one_set |
|
module checkCorrect(/*AUTOARG*/ |
// Outputs |
y, |
// Inputs |
in |
); |
parameter DIM_S = 9; |
localparam DIM_Q = DIM_S*DIM_S; |
|
input [(DIM_Q-1):0] in; |
|
output y; |
|
wire [(DIM_S-1):0] grid1d [(DIM_S-1):0]; |
wire [(DIM_S-1):0] w_set; |
|
wire [(DIM_S-1):0] w_mask = ~('d0); |
|
wire [(DIM_S-1):0] w_accum_or [(DIM_S-1):0]; |
genvar i; |
generate |
for(i=0;i<DIM_S;i=i+1) |
begin: accum_or |
if(i==0) |
begin |
assign w_accum_or[i] = grid1d[i]; |
end |
else |
begin |
assign w_accum_or[i] = w_accum_or[i-1] | grid1d[i]; |
end |
end |
endgenerate |
|
wire [(DIM_S-1):0] w_gridOR = w_accum_or[(DIM_S-1)]; |
|
wire w_allSet = (w_gridOR == w_mask); |
wire w_allAssign = (w_set == w_mask); |
|
assign y = w_allSet & w_allAssign; |
|
generate |
for(i=0;i<DIM_S;i=i+1) |
begin: unflatten |
assign grid1d[i] = in[(DIM_S*(i+1))-1:DIM_S*i]; |
chk_pow2 #(.DIM_S(DIM_S)) pchk (.in(grid1d[i]), .out(w_set[i])); |
end |
endgenerate |
endmodule // checkCorrect |
|
/parameterized_rtl/piece.v
0,0 → 1,357
module piece(/*AUTOARG*/ |
// Outputs |
changed, done, curr_value, error, |
// Inputs |
clk, rst, start, clr, start_value, my_row, my_col, my_square |
); |
parameter DIM_S = 9; |
|
input clk; |
input rst; |
input start; |
input clr; |
|
output changed; |
output done; |
output error; |
|
input [(DIM_S-1):0] start_value; |
output [(DIM_S-1):0] curr_value; |
|
input [(DIM_S*(DIM_S-1)-1):0] my_row; |
input [(DIM_S*(DIM_S-1)-1):0] my_col; |
input [(DIM_S*(DIM_S-1)-1):0] my_square; |
|
wire [(DIM_S-1):0] row2d [(DIM_S-2):0]; |
wire [(DIM_S-1):0] col2d [(DIM_S-2):0]; |
wire [(DIM_S-1):0] sqr2d [(DIM_S-2):0]; |
|
wire [(DIM_S-1):0] row2d_solv [(DIM_S-2):0]; |
wire [(DIM_S-1):0] col2d_solv [(DIM_S-2):0]; |
wire [(DIM_S-1):0] sqr2d_solv [(DIM_S-2):0]; |
|
reg [(DIM_S-1):0] r_curr_value; |
reg [(DIM_S-1):0] t_next_value; |
assign curr_value = r_curr_value; |
|
reg [2:0] r_state, n_state; |
reg r_solved, t_solved; |
reg t_changed,r_changed; |
reg t_error,r_error; |
|
assign done = r_solved; |
assign changed = r_changed; |
assign error = r_error; |
|
wire [(DIM_S-1):0] w_solved; |
|
wire w_piece_solved = (w_solved != 'd0); |
one_set #(.DIM_S(DIM_S)) s0 (r_curr_value, w_solved); |
|
always@(posedge clk) |
begin |
if(rst) |
begin |
r_curr_value <= 'd0; |
r_state <= 3'd0; |
r_solved <= 1'b0; |
r_changed <= 1'b0; |
r_error <= 1'b0; |
end |
else |
begin |
r_curr_value <= clr ? 'd0 : t_next_value; |
r_state <= clr ? 3'd0 : n_state; |
r_solved <= clr ? 1'b0 : t_solved; |
r_changed <= clr ? 1'b0 : t_changed; |
r_error <= clr ? 1'b0 : t_error; |
end |
end // always@ (posedge clk) |
|
|
genvar i; |
generate |
for(i=0;i<(DIM_S-1);i=i+1) |
begin: unflatten |
assign row2d[i] = my_row[(DIM_S*(i+1))-1:DIM_S*i]; |
assign col2d[i] = my_col[(DIM_S*(i+1))-1:DIM_S*i]; |
assign sqr2d[i] = my_square[(DIM_S*(i+1))-1:DIM_S*i]; |
end |
endgenerate |
|
generate |
for(i=0;i<(DIM_S-1);i=i+1) |
begin: unique_rows |
one_set #(.DIM_S(DIM_S)) rs (row2d[i], row2d_solv[i]); |
one_set #(.DIM_S(DIM_S)) cs (col2d[i], col2d_solv[i]); |
one_set #(.DIM_S(DIM_S)) ss (sqr2d[i], sqr2d_solv[i]); |
end |
endgenerate |
|
/* OR output of one_set to find cells |
* that are already set in col, grid, row */ |
wire [(DIM_S-1):0] set_row, set_col, set_sqr; |
wire [(DIM_S-1):0] row_or, col_or, sqr_or; |
|
wire [(DIM_S-1):0] w_accum_row2d [(DIM_S-2):0]; |
wire [(DIM_S-1):0] w_accum_col2d [(DIM_S-2):0]; |
wire [(DIM_S-1):0] w_accum_sqr2d [(DIM_S-2):0]; |
|
wire [(DIM_S-1):0] w_accum_row_or [(DIM_S-2):0]; |
wire [(DIM_S-1):0] w_accum_col_or [(DIM_S-2):0]; |
wire [(DIM_S-1):0] w_accum_sqr_or [(DIM_S-2):0]; |
|
generate |
for(i=0;i<(DIM_S-1);i=i+1) |
begin: set_accums |
if(i==0) |
begin |
assign w_accum_row2d[i] = row2d_solv[i]; |
assign w_accum_col2d[i] = col2d_solv[i]; |
assign w_accum_sqr2d[i] = sqr2d_solv[i]; |
|
assign w_accum_row_or[i] = row2d[i]; |
assign w_accum_col_or[i] = col2d[i]; |
assign w_accum_sqr_or[i] = sqr2d[i]; |
end |
else |
begin |
assign w_accum_row2d[i] = w_accum_row2d[i-1] | row2d_solv[i]; |
assign w_accum_col2d[i] = w_accum_col2d[i-1] | col2d_solv[i]; |
assign w_accum_sqr2d[i] = w_accum_sqr2d[i-1] | sqr2d_solv[i]; |
|
assign w_accum_row_or[i] = w_accum_row_or[i-1] | row2d[i]; |
assign w_accum_col_or[i] = w_accum_col_or[i-1] | col2d[i]; |
assign w_accum_sqr_or[i] = w_accum_sqr_or[i-1] | sqr2d[i]; |
end |
end |
endgenerate |
|
assign set_row = w_accum_row2d[DIM_S-2]; |
assign set_col = w_accum_col2d[DIM_S-2]; |
assign set_sqr = w_accum_sqr2d[DIM_S-2]; |
|
assign row_or = w_accum_row_or[DIM_S-2]; |
assign col_or = w_accum_col_or[DIM_S-2]; |
assign sqr_or = w_accum_sqr_or[DIM_S-2]; |
|
|
integer ii; |
always@(posedge clk) |
begin |
if(rst==1'b0) |
begin |
for(ii=0;ii<(DIM_S-1);ii=ii+1) |
begin |
if(row2d_solv[ii] === 'dx) |
begin |
$display("row %d", ii); |
$stop(); |
end |
end |
end |
end |
|
|
wire [(DIM_S-1):0] row_nor = ~row_or; |
wire [(DIM_S-1):0] col_nor = ~col_or; |
wire [(DIM_S-1):0] sqr_nor = ~sqr_or; |
|
wire [(DIM_S-1):0] row_singleton; |
wire [(DIM_S-1):0] col_singleton; |
wire [(DIM_S-1):0] sqr_singleton; |
|
one_set #(.DIM_S(DIM_S)) s1 (r_curr_value & row_nor, row_singleton); |
one_set #(.DIM_S(DIM_S)) s2 (r_curr_value & col_nor, col_singleton); |
one_set #(.DIM_S(DIM_S)) s3 (r_curr_value & sqr_nor, sqr_singleton); |
|
/* these are the values of the set rows, columns, and |
* squares */ |
|
wire [(DIM_S-1):0] not_poss = set_row | set_col | set_sqr; |
wire [(DIM_S-1):0] new_poss = r_curr_value & (~not_poss); |
|
wire w_piece_zero = (r_curr_value == 'd0); |
|
always@(*) |
begin |
t_next_value = r_curr_value; |
n_state = r_state; |
t_solved = r_solved; |
t_changed = 1'b0; |
t_error = r_error; |
|
case(r_state) |
3'd0: |
begin |
if(start) |
begin |
t_next_value = start_value; |
n_state = 3'd1; |
t_changed = 1'b1; |
t_error = 1'b0; |
end |
end |
3'd1: |
begin |
if(w_piece_solved | w_piece_zero) |
begin |
t_solved = 1'b1; |
n_state = 3'd7; |
t_changed = 1'b1; |
t_error = w_piece_zero; |
end |
else |
begin |
t_changed = (new_poss != r_curr_value); |
t_next_value = new_poss; |
n_state = 3'd2; |
end |
end // case: 3'd1 |
3'd2: |
begin |
if(w_piece_solved | w_piece_zero) |
begin |
t_solved = 1'b1; |
n_state = 3'd7; |
t_error = w_piece_zero; |
end |
else |
begin |
if(row_singleton != 'd0) |
begin |
//$display("used row singleton"); |
t_next_value = row_singleton; |
t_changed = 1'b1; |
t_solved = 1'b1; |
n_state = 3'd7; |
end |
else if(col_singleton != 'd0) |
begin |
//$display("used col singleton"); |
t_next_value = col_singleton; |
t_changed = 1'b1; |
t_solved = 1'b1; |
n_state = 3'd7; |
end |
else if(sqr_singleton != 'd0) |
begin |
//$display("used sqr singleton"); |
t_next_value = sqr_singleton; |
t_changed = 1'b1; |
t_solved = 1'b1; |
n_state = 3'd7; |
end |
else |
begin |
n_state = 3'd1; |
end |
end |
end |
3'd7: |
begin |
t_solved = 1'b1; |
n_state = 3'd7; |
end |
|
endcase // case (r_state) |
end |
endmodule // piece |
|
module one_set(in, out); |
parameter DIM_S = 9; |
input [(DIM_S-1):0] in; |
output [(DIM_S-1):0] out; |
|
wire [(DIM_S-1):0] w_ones = ~('d0); |
wire [(DIM_S-1):0] w_m = in + w_ones; |
wire w_pow2 = ((w_m & in) == 'd0) && (in != 'd0); |
|
assign out = {DIM_S{w_pow2}} & in; |
endmodule // one_set |
|
module ones_count(in, out); |
parameter LG_IN_WIDTH = 4; |
localparam IN_WIDTH= (1 << LG_IN_WIDTH); |
localparam OUT_WIDTH = LG_IN_WIDTH; |
|
input [(IN_WIDTH-1):0] in; |
output [(OUT_WIDTH-1):0] out; |
|
localparam NUM_COUNT4 = IN_WIDTH/4; |
wire [2:0] w_cnt4 [(NUM_COUNT4-1):0]; |
wire [(OUT_WIDTH-1):0] w_sum [(NUM_COUNT4-1):0]; |
genvar i; |
|
generate |
for(i=0;i<NUM_COUNT4;i=i+1) |
begin: count4z |
one_count4 cc (in[(4*(i+1))-1:4*(i)], w_cnt4[i]); |
end |
endgenerate |
|
generate |
for(i=0;i<NUM_COUNT4;i=i+1) |
begin: sumz |
if(i==0) |
begin |
assign w_sum[i] = { {(OUT_WIDTH-3){1'b0}}, w_cnt4[i]}; |
end |
else |
begin |
assign w_sum[i] = w_sum[i-1] + { {(OUT_WIDTH-3){1'b0}}, w_cnt4[i]}; |
end |
end |
endgenerate |
|
assign out = w_sum[NUM_COUNT4-1]; |
|
endmodule // ones_count |
|
/* |
module ones_count81(input [80:0] in, output [6:0] out); |
wire [83:0] w_in = {3'd0, in}; |
wire [2:0] ps [20:0]; |
|
integer x; |
reg [6:0] t_sum; |
genvar i; |
generate |
for(i=0;i<21;i=i+1) |
begin : builders |
one_count4 os (w_in[(4*(i+1)) - 1 : 4*i], ps[i]); |
end |
endgenerate |
always@(*) |
begin |
t_sum = 7'd0; |
for(x = 0; x < 21; x=x+1) |
begin |
t_sum = t_sum + {3'd0, ps[x]}; |
end |
end |
assign out = t_sum; |
|
endmodule // ones_count81 |
*/ |
|
module one_count4(input [3:0] in, output [2:0] out); |
assign out = |
(in == 4'b0000) ? 3'd0 : |
(in == 4'b0001) ? 3'd1 : |
(in == 4'b0010) ? 3'd1 : |
(in == 4'b0011) ? 3'd2 : |
(in == 4'b0100) ? 3'd1 : |
(in == 4'b0101) ? 3'd2 : |
(in == 4'b0110) ? 3'd2 : |
(in == 4'b0111) ? 3'd3 : |
(in == 4'b1000) ? 3'd1 : |
(in == 4'b1001) ? 3'd2 : |
(in == 4'b1010) ? 3'd2 : |
(in == 4'b1011) ? 3'd3 : |
(in == 4'b1100) ? 3'd2 : |
(in == 4'b1101) ? 3'd3 : |
(in == 4'b1110) ? 3'd3 : |
3'd4; |
endmodule // one_count4 |
|
/parameterized_rtl/minPiece.v
0,0 → 1,197
module minPiece(/*AUTOARG*/ |
// Outputs |
minPoss, minIdx, |
// Inputs |
clk, rst, inGrid |
); |
|
function integer my_clog2; |
input integer value; |
begin |
value = value-1; |
for (my_clog2=0; value>0; my_clog2=my_clog2+1) |
value = value>>1; |
end |
endfunction |
|
parameter DIM = 3; |
localparam DIM_S = DIM*DIM; |
localparam DIM_Q = DIM_S*DIM_S; |
|
localparam LG_DIM_S = my_clog2(DIM_S); |
localparam LG_DIM_Q = my_clog2(DIM_Q); |
|
localparam PAD_WIDTH = (1<<LG_DIM_Q); |
localparam PAD = PAD_WIDTH - DIM_Q; |
|
|
input clk; |
input rst; |
|
input [(DIM_S*DIM_S*DIM_S -1):0] inGrid; |
|
output [(LG_DIM_S-1):0] minPoss; |
output [(LG_DIM_Q-1):0] minIdx; |
|
reg [(LG_DIM_S-1):0] r_minPoss; |
reg [(LG_DIM_Q-1):0] r_minIdx; |
|
assign minPoss = r_minPoss; |
assign minIdx = r_minIdx; |
|
wire [(DIM_S-1):0] grid2d [(DIM_Q-1):0]; |
|
wire [(LG_DIM_S-1):0] w_reduce_poss [(LG_DIM_Q):0][(PAD_WIDTH-1):0]; |
wire [(LG_DIM_Q-1):0] w_reduce_indices [(LG_DIM_Q):0][(PAD_WIDTH-1):0]; |
|
genvar i,j; |
|
/* unflatten */ |
generate |
for(i=0;i<PAD_WIDTH;i=i+1) |
begin: unflatten |
if(i < DIM_Q) |
begin |
assign grid2d[i] = inGrid[(DIM_S*(i+1))-1:DIM_S*i]; |
countPoss #(.DIM(DIM)) cP1 (.clk(clk), .rst(rst), .in(grid2d[i]), .out(w_reduce_poss[0][i])); |
assign w_reduce_indices[0][i] = i; |
end |
else |
begin |
assign w_reduce_poss[0][i] = ~0; |
assign w_reduce_indices[0][i] = i; |
end // else: !if(i < DIM_Q) |
//assign w_reduce_indices[0][i] = i; |
end |
endgenerate |
|
localparam RIDX=LG_DIM_Q; |
generate |
for(i=1;i<(LG_DIM_Q+1);i=i+1) |
begin: level_reduce |
for(j=0;j<(1<<(LG_DIM_Q-i));j=j+1) |
begin: elem_reduce |
cmpPiece #(.DIM(DIM)) cmpr |
( |
.outPoss(w_reduce_poss[i][j]), |
.outIdx(w_reduce_indices[i][j]), |
.inPoss_0(w_reduce_poss[i-1][2*j]), |
.inIdx_0(w_reduce_indices[i-1][2*j]), |
.inPoss_1(w_reduce_poss[i-1][2*j+1]), |
.inIdx_1(w_reduce_indices[i-1][2*j+1]) |
); |
end |
end |
endgenerate |
|
always@(posedge clk) |
begin |
if(rst) |
begin |
r_minIdx <= 0; |
r_minPoss <= (~0); |
end |
else |
begin |
r_minIdx <= w_reduce_indices[RIDX][0]; |
r_minPoss <= w_reduce_poss[RIDX][0]; |
end |
end // always@ (posedge clk) |
|
endmodule // minPiece |
|
|
module cmpPiece(/*AUTOARG*/ |
// Outputs |
outPoss, outIdx, |
// Inputs |
inPoss_0, inIdx_0, inPoss_1, inIdx_1 |
); |
|
function integer my_clog2; |
input integer value; |
begin |
value = value-1; |
for (my_clog2=0; value>0; my_clog2=my_clog2+1) |
value = value>>1; |
end |
endfunction // for |
|
parameter DIM=3; |
localparam DIM_S = DIM*DIM; |
localparam DIM_Q = DIM_S*DIM_S; |
localparam LG_DIM_S = my_clog2(DIM_S); |
localparam LG_DIM_Q = my_clog2(DIM_Q); |
|
input [(LG_DIM_S-1):0] inPoss_0; |
input [(LG_DIM_Q-1):0] inIdx_0; |
|
input [(LG_DIM_S-1):0] inPoss_1; |
input [(LG_DIM_Q-1):0] inIdx_1; |
|
output [(LG_DIM_S-1):0] outPoss; |
output [(LG_DIM_Q-1):0] outIdx; |
|
wire w_cmp = (inPoss_0 < inPoss_1); |
|
assign outPoss = w_cmp ? inPoss_0 : inPoss_1; |
assign outIdx = w_cmp ? inIdx_0 : inIdx_1; |
|
endmodule // cmpPiece |
|
module countPoss(clk,rst,in,out); |
function integer my_clog2; |
input integer value; |
begin |
value = value-1; |
for (my_clog2=0; value>0; my_clog2=my_clog2+1) |
value = value>>1; |
end |
endfunction // for |
|
parameter DIM=3; |
localparam DIM_S = DIM*DIM; |
localparam DIM_Q = DIM_S*DIM_S; |
|
localparam LG_DIM_S = my_clog2(DIM_S); |
localparam LG_DIM_Q = my_clog2(DIM_Q); |
|
localparam PAD = (1<<LG_DIM_S) - DIM_S; |
localparam PAD_WIDTH = (1<<LG_DIM_S); |
|
input [(DIM_S-1):0] in; |
input clk; |
input rst; |
|
output [(LG_DIM_S-1):0] out; |
reg [(LG_DIM_S-1):0] r_out; |
assign out = r_out; |
|
|
wire [(PAD_WIDTH-1):0] w_pad_in; |
generate |
begin: padding |
if(PAD > 0) |
begin |
assign w_pad_in = { {PAD{1'b0}}, in}; |
end |
else |
begin |
assign w_pad_in = in; |
end |
end |
endgenerate |
|
wire [(LG_DIM_S-1):0] w_cnt; |
|
ones_count #(.LG_IN_WIDTH(LG_DIM_S)) c0 (.in(w_pad_in), .out(w_cnt)); |
|
wire [(LG_DIM_S-1):0] w_out = (w_cnt == 'd1) ? ~0 : w_cnt; |
|
always@(posedge clk) |
begin |
r_out <= rst ? ~0 : w_out; |
end |
|
endmodule // countPoss |
|
/parameterized_rtl/sudoku.v
0,0 → 1,286
module sudoku(/*AUTOARG*/ |
// Outputs |
outGrid, unsolvedCells, timeOut, allDone, anyChanged, anyError, |
minIdx, minPoss, |
// Inputs |
clk, rst, clr, start, inGrid |
); |
function integer my_clog2; |
input integer value; |
begin |
value = value-1; |
for (my_clog2=0; value>0; my_clog2=my_clog2+1) |
value = value>>1; |
end |
endfunction // for |
|
parameter DIM = 3; |
localparam DIM_S = (DIM*DIM); |
localparam DIM_Q = (DIM_S*DIM_S); |
|
localparam LG_DIM_S = my_clog2(DIM_S); |
localparam LG_DIM_Q = my_clog2(DIM_Q); |
|
localparam PAD_WIDTH = (1<<LG_DIM_Q); |
localparam PAD = PAD_WIDTH - DIM_Q; |
|
input clk; |
input rst; |
input clr; |
|
input start; |
|
input [(DIM_S*DIM_S*DIM_S -1):0] inGrid; |
output [(DIM_S*DIM_S*DIM_S - 1):0] outGrid; |
|
/* TODO: PARAMETERIZE */ |
output [(LG_DIM_Q-1):0] unsolvedCells; |
output [(LG_DIM_Q-1):0] minIdx; |
output [(LG_DIM_S-1):0] minPoss; |
|
output timeOut; |
output allDone; |
output anyChanged; |
output anyError; |
|
|
wire [(DIM_S-1):0] grid2d [(DIM_Q-1):0]; |
wire [(DIM_S-1):0] currGrid [(DIM_Q-1):0]; |
wire [(DIM_Q-1):0] done; |
wire [(DIM_Q-1):0] changed; |
wire [(DIM_Q-1):0] error; |
|
assign allDone = &done; |
assign anyChanged = |changed; |
//assign anyError = |error; |
|
reg [3:0] r_cnt; |
assign timeOut = (r_cnt == 4'b1111); |
always@(posedge clk) |
begin |
if(rst) |
begin |
r_cnt <= 4'd0; |
end |
else |
begin |
r_cnt <= start ? 4'd0 : (|changed ? 4'd0 : r_cnt + 4'd1); |
end |
end // always@ (posedge clk) |
|
minPiece #(.DIM(DIM)) mP0 |
( |
.minPoss(minPoss), |
.minIdx(minIdx), |
.clk(clk), |
.rst(rst), |
.inGrid(outGrid) |
); |
|
|
genvar i, j; |
genvar ii,jj; |
|
generate |
for(i=0;i<DIM_Q;i=i+1) |
begin: unflatten |
assign grid2d[i] = inGrid[(DIM_S*(i+1))-1:(DIM_S*i)]; |
end |
endgenerate |
|
wire [(LG_DIM_Q-1):0] w_unSolvedCells; |
reg [(LG_DIM_Q-1):0] r_unSolvedCells; |
always@(posedge clk) |
begin |
if(rst) |
begin |
r_unSolvedCells <= DIM_Q; |
end |
else |
begin |
r_unSolvedCells <= start ? DIM_Q : w_unSolvedCells; |
end |
end // always@ (posedge clk) |
assign unsolvedCells = r_unSolvedCells; |
|
|
wire [(PAD_WIDTH-1):0] w_pad_in; |
generate |
begin: padding |
if(PAD > 0) |
begin |
assign w_pad_in = { {PAD{1'b0}}, (~done)}; |
end |
else |
begin |
assign w_pad_in = ~done; |
end |
end |
endgenerate |
|
ones_count #(.LG_IN_WIDTH(LG_DIM_Q)) oc1 (.in(w_pad_in), .out(w_unSolvedCells)); |
|
wire [(DIM_S*(DIM_S-1)-1):0] w_rows [(DIM_Q-1):0]; |
wire [(DIM_S*(DIM_S-1)-1):0] w_cols [(DIM_Q-1):0]; |
wire [(DIM_S*(DIM_S-1)-1):0] w_sqrs [(DIM_Q-1):0]; |
|
generate |
for(i=0;i<DIM_Q;i=i+1) |
begin: pieces |
piece # (.DIM_S(DIM_S)) |
pg ( |
// Outputs |
.changed (changed[i]), |
.done (done[i]), |
.curr_value (currGrid[i]), |
.error (error[i]), |
// Inputs |
.clk (clk), |
.rst (rst), |
.clr (clr), |
.start (start), |
.start_value (grid2d[i]), |
.my_row (w_rows[i]), |
.my_col (w_cols[i]), |
.my_square (w_sqrs[i]) |
); |
end // block: pieces |
endgenerate |
|
|
generate |
for(i=0;i<DIM_S;i=i+1) |
begin: col_outer |
for(ii=0;ii<DIM_S;ii=ii+1) |
begin: gen_cols |
for(jj=0;jj<DIM_S;jj=jj+1) |
begin: gen_col_elem |
if(i > jj) |
begin |
assign w_cols[i*DIM_S+ii][(DIM_S*(jj+1)-1):DIM_S*jj] = currGrid[DIM_S*(jj)+ii]; |
end |
|
else if(jj > i) |
begin |
assign w_cols[i*DIM_S+ii][ (DIM_S*(jj)-1):DIM_S*(jj-1)] = currGrid[ DIM_S*(jj) + ii]; |
end |
end |
end // block: gen_cols |
end // block: col_outer |
endgenerate |
|
|
generate |
for(i=0;i<DIM_S;i=i+1) |
begin: row_outer |
for(ii=0;ii<DIM_S;ii=ii+1) |
begin: rows_cols |
for(jj=0;jj<DIM_S;jj=jj+1) |
begin: gen_row_elem |
if(ii > jj) |
begin |
assign w_rows[i*DIM_S+ii][(DIM_S*(jj+1)-1):DIM_S*jj] = currGrid[DIM_S*(i)+jj]; |
end |
|
else if(jj > ii) |
begin |
assign w_rows[i*DIM_S+ii][ (DIM_S*(jj)-1):DIM_S*(jj-1)] = currGrid[ DIM_S*(i)+jj]; |
end |
end |
end |
end |
endgenerate |
|
|
generate |
for(i=0;i<DIM_S;i=i+1) |
begin: outer_y_sqr |
for(j=0;j<DIM_S;j=j+1) |
begin: outer_x_sqr |
for(ii=DIM*(i/DIM); ii < DIM*((i/DIM)+1); ii=ii+1) |
begin: inner_y_sqr |
for(jj=DIM*(j/DIM); jj < DIM*((j/DIM)+1); jj=jj+1) |
begin: inner_x_sqr |
if((i*DIM_S + j) > (ii*DIM_S + jj)) |
begin |
assign w_sqrs[i*DIM_S+j][(DIM_S*((ii-(DIM*(i/DIM)))*DIM + (jj-(DIM*(j/DIM)))+1) - 1):(DIM_S*((ii-(DIM*(i/DIM)))*DIM + (jj-(DIM*(j/DIM)))))] = currGrid[DIM_S*(ii)+jj]; |
end |
|
else if((i*DIM_S + j) < (ii*DIM_S + jj)) |
begin |
assign w_sqrs[i*DIM_S+j][(DIM_S*((ii-(DIM*(i/DIM)))*DIM + (jj-(DIM*(j/DIM))-1)+1) - 1):(DIM_S*((ii-(DIM*(i/DIM)))*DIM + (jj-(DIM*(j/DIM))-1)))] = currGrid[DIM_S*(ii)+jj]; |
end |
end |
end |
end |
end // block: outer_y_sqr |
endgenerate |
|
generate |
for(i=0;i<DIM_Q;i=i+1) |
begin: outGridGen |
assign outGrid[(DIM_S*(i+1)-1):(DIM_S*i)] = currGrid[i]; |
|
end |
endgenerate |
|
|
wire [(DIM_Q-1):0] c_rows [(DIM_S-1):0]; |
wire [(DIM_Q-1):0] c_cols [(DIM_S-1):0]; |
wire [(DIM_Q-1):0] c_grds [(DIM_S-1):0]; |
|
wire [(3*DIM_S - 1):0] w_correct; |
|
generate |
for(ii=0;ii<DIM_S;ii=ii+1) |
begin: row_check |
for(jj=0;jj<DIM_S;jj=jj+1) |
begin: row_elem_check |
assign c_rows[jj][(DIM_S*(ii+1)-1):DIM_S*ii] = currGrid[(DIM_S*jj) + ii]; |
end |
end |
endgenerate |
|
generate |
for(ii=0;ii<DIM_S;ii=ii+1) |
begin: col_check |
for(jj=0;jj<DIM_S;jj=jj+1) |
begin: col_elem_check |
assign c_cols[jj][(DIM_S*(ii+1)-1):DIM_S*ii] = currGrid[DIM_S*ii + jj]; |
end |
end |
endgenerate |
|
genvar iii,jjj; |
generate |
for(ii=0; ii < DIM; ii=ii+1) |
begin: grd_check_y |
for(jj = 0; jj < DIM; jj=jj+1) |
begin: grd_check_x |
for(iii=DIM*ii; iii < DIM*(ii+1); iii=iii+1) |
begin: gg_y |
for(jjj=DIM*jj; jjj < DIM*(jj+1); jjj=jjj+1) |
begin: gg_x |
assign c_grds[DIM*ii+jj][DIM_S*(DIM*(iii-DIM*ii) + (jjj-DIM*jj)+1)-1:DIM_S*(DIM*(iii-DIM*ii) + (jjj-DIM*jj))] = currGrid[DIM_S*iii + jjj]; |
end |
end |
end |
end |
endgenerate |
|
generate |
for(ii=0;ii<DIM_S;ii=ii+1) |
begin: checks |
checkCorrect #(.DIM_S(DIM_S)) cC_R |
(.y(w_correct[0*(DIM_S) + ii]), .in(c_rows[ii])); |
checkCorrect #(.DIM_S(DIM_S)) cC_C |
(.y(w_correct[1*(DIM_S) + ii]), .in(c_cols[ii])); |
checkCorrect #(.DIM_S(DIM_S)) cC_G |
(.y(w_correct[2*(DIM_S) + ii]), .in(c_grds[ii])); |
end |
endgenerate |
|
|
assign anyError = ~(&w_correct); |
|
endmodule |