setupCrossword[wordStrings_]:=(
m=Length[chars];

words=Characters/@wordStrings;
chars=Union@Flatten@words;

wordMatch[vars_,word_]:=And@@(Thread[{vars,word}]);
validWord[vars_]:=Or@@(wordMatch[vars,#]&/@words);
validCell[{i_,j_}]:=BooleanCountingFunction[{1},{{i,j},#}&/@chars];

row[i_]:={i,#}&/@Range[n];
col[i_]:={#,i}&/@Range[n];
cells=Flatten[row/@Range[n],1];

rowCons=validWord[row[#]]&/@Range[n];
colCons=validWord[col[#]]&/@Range[n];
cellCons=validCell/@cells;
formula=And@@(Join[rowCons,colCons,cellCons]);
vars=Table[{{i,j},c},{i,1,n},{j,1,n},{c,chars}]//Flatten[#,2]&;
decodeInstance[instance_]:=(
choices=Extract[vars,Position[instance,True]];
grid=Table[{i,j},{i,1,n},{j,1,n}]/.Rule@@@choices
)
);

n=3;
wordLimit=200;
wordStrings=Select[DictionaryLookup[],StringLength[#]==n&&LowerCaseQ[#]&];
setupCrossword[wordStrings[[;;wordLimit]]];

vals=SatisfiabilityInstances[formula,vars,5];
Framed@Style[TableForm@decodeInstance@#,{Large,Bold,Orange}]&/@vals