Skip to content

Instantly share code, notes, and snippets.

@daxfohl
Last active December 10, 2015 09:28
Show Gist options
  • Save daxfohl/4414011 to your computer and use it in GitHub Desktop.
Save daxfohl/4414011 to your computer and use it in GitHub Desktop.
sudoku all
module trigger(clk, rxReady, rxData, txBusy, txStart, txData);
input clk;
input[7:0] rxData;
input rxReady;
input txBusy;
output reg txStart;
output reg[7:0] txData;
localparam READ=0, SOLVING=1, WRITE1=2, WRITE2=3;
localparam ROW=0, COL=1, SQ=2;
localparam LENSQT = 3;
localparam LEN = LENSQT * LENSQT;
localparam SQLEN = LEN * LEN;
localparam LENCUB = SQLEN * LEN;
localparam LENMAX = LEN - 1;
localparam RGNTYPES = 3;
localparam RGNS = RGNTYPES * LEN;
localparam ALLBITS = (1 << LEN) - 1;
integer ioCount;
reg[LENMAX:0] data[0:LENMAX][0:LENMAX];
reg[LENMAX:0] teData[0:LENMAX][0:LENMAX];
reg te;
integer teStart;
integer teOffset;
integer state;
integer ticks;
reg changed;
integer regn;
initial begin
txStart = 0;
state = READ;
te = 0;
teStart = 0;
teOffset = 0;
ticks = 0;
changed = 0;
end
always @(posedge clk) begin
integer ioCell, ioByte, ioCol, ioRow;
ioByte = ioCount%4;
ioCell = ioCount/4;
ioCol = ioCell%LEN;
ioRow = ioCell/LEN;
case (state)
READ: begin
if (rxReady) begin
data[ioRow][ioCol][ioByte*8+7 -:8] <= rxData;
if (ioCount == SQLEN*4-1) begin
ioCount <= 0;
state <= state + 1;
end else begin
ioCount <= ioCount + 1;
end
end
end
SOLVING: begin
integer r;
reg[LENMAX:0] dataNew[0:LENMAX][0:LENMAX];
reg dorked;
integer teCell, teVal, teSum, teR, teC, teVTemp, teCellVal;
reg teAtLeastOne, teMoreThanOne, teBadAttempt;
ticks = ticks + 1;
teSum = (teStart + teOffset) % LENCUB;
teCell = teSum / LEN;
teVal = teSum % LEN;
teR = teCell / LEN;
teC = teCell % LEN;
teAtLeastOne = 0;
teMoreThanOne = 0;
teCellVal = data[teR][teC];
for (teVTemp = 0; teVTemp < LEN; teVTemp = teVTemp + 1) begin
teMoreThanOne = teMoreThanOne || teAtLeastOne && teCellVal[teVTemp];
teAtLeastOne = teAtLeastOne || teCellVal[teVTemp];
end
teBadAttempt = te && (teAtLeastOne && !teMoreThanOne || !teCellVal[teVal]);
dorked = 0;
if (!teBadAttempt) begin
integer rgnType;
integer rgn;
reg[LENMAX:0] cells[0:LENMAX];
reg[LENMAX:0] coverRemoved[0:LENMAX];
reg covered[0:LENMAX];
reg[LENMAX:0] exactlyOneCellContainsV;
integer j, i, v;
for (r = 0; r < LEN; r = r + 1) begin
integer c;
for (c = 0; c < LEN; c = c + 1) begin
dataNew[r][c] = te ? teData[r][c] : data[r][c];
end
end
rgnType = regn / LEN;
rgn = regn % LEN;
for (i = 0; i < LEN; i = i + 1) begin
cells[i] = rgnType == ROW ? dataNew[rgn][i]
: rgnType == COL ? dataNew[i][rgn]
: dataNew[rgn / LENSQT * LENSQT + i % LENSQT][rgn % LENSQT * LENSQT + i / LENSQT];
end
for (i = 0; i < LEN; i = i + 1) begin
integer cover;
integer coveredCount;
integer vCount;
cover = cells[i];
coveredCount = 0;
for (j = 0; j < LEN; j = j + 1) begin
coverRemoved[j] = cells[j] & (~cover);
covered[j] = coverRemoved[j] == 0;
coveredCount = coveredCount + (covered[j] ? 1 : 0);
end
vCount = 0;
for (v = 0; v < LEN; v = v + 1) begin
vCount = vCount + cover[v];
end
if (vCount == coveredCount) begin
for (j = 0; j < LEN; j = j + 1) begin
cells[j] = covered[j] ? cells[j] : coverRemoved[j];
end
end
end
for (v = 0; v < LEN; v = v + 1) begin
reg atLeastOneCellContainsV;
reg twoCellsContainV;
atLeastOneCellContainsV = 0;
twoCellsContainV = 0;
for (i = 0; i < LEN; i = i + 1) begin
twoCellsContainV = twoCellsContainV || atLeastOneCellContainsV && cells[i][v];
atLeastOneCellContainsV = atLeastOneCellContainsV || cells[i][v];
end
exactlyOneCellContainsV[v] = atLeastOneCellContainsV && !twoCellsContainV;
end
for (i = 0; i < LEN; i = i + 1) begin
integer dataTest;
dataTest = exactlyOneCellContainsV & cells[i];
cells[i] = dataTest == 0 ? cells[i] : dataTest;
end
for (i = 0; i < LEN; i = i + 1) begin
reg atLeastOne;
reg moreThanOne;
atLeastOne = 0;
moreThanOne = 0;
for (v = 0; v < LEN; v = v + 1) begin
moreThanOne = moreThanOne || atLeastOne && cells[i][v];
atLeastOne = atLeastOne || cells[i][v];
end
if (!moreThanOne) begin
for (j = 0; j < LEN; j = j + 1) begin
if (i != j)
begin
cells[j] = cells[j] & ~cells[i];
end
end
end
end
for (i = 0; i < LEN; i = i + 1) begin
integer c;
r = rgnType == ROW ? rgn
: rgnType == COL ? i
: rgn / LENSQT * LENSQT + i % LENSQT;
c = rgnType == ROW ? i
: rgnType == COL ? rgn
: rgn % LENSQT * LENSQT + i / LENSQT;
dataNew[r][c] = cells[i];
end
for (r = 0; r < LEN; r = r + 1) begin
integer c;
for (c = 0; c < LEN; c = c + 1) begin
integer newVal;
newVal = dataNew[r][c];
if (te) begin
changed = changed || newVal != teData[r][c];
dorked = dorked || newVal == 0;
teData[r][c] = newVal;
end else begin
changed = changed || newVal != data[r][c];
data[r][c] = newVal;
end
end
end
regn = (regn + 1) % RGNS;
end
if (regn == 0 && !changed || teBadAttempt || dorked) begin
changed = 0;
if (!te) begin
te = 1;
end else begin
if (dorked && !teBadAttempt) begin
data[teR][teC][teVal] = 0;
te = 0;
teStart = (teSum + 1) % LENCUB;
teOffset = 0;
end else begin
teOffset = teOffset + 1;
if (teOffset == LENCUB) begin
state = WRITE1;
end
end
end
if (te) begin
for (r = 0; r < LEN; r = r + 1) begin
integer c;
for (c = 0; c < LEN; c = c + 1) begin
teData[r][c] = data[r][c];
end
teSum = (teStart + teOffset) % LENCUB;
teCell = teSum / LEN;
teVal = teSum % LEN;
teR = teCell / LEN;
teC = teCell % LEN;
teData[teR][teC] = 1 << teVal;
end
end
end
if (regn == 0) begin
changed = 0;
end
end
WRITE1: begin
if (!txBusy) begin
txData <= data[ioRow][ioCol][ioByte*8+7 -:8];
txStart <= 1;
state <= WRITE2;
end
end
WRITE2: begin
txStart <= 0;
if (ioCount != SQLEN*4-1) begin
ioCount <= ioCount + 1;
state <= WRITE1;
end else begin
ioCount <= 0;
state <= READ;
end
end
endcase
end
endmodule
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment