module controller (iCLK,iRST_N_LCD,LCD_DATA,LCD_RW,LCD_EN,LCD_RS,key,sw0,hash,plain_text,match,sys_reset);
input sw0,match;
output reg sys_reset;
input [3:0] key;
output reg [63:0] hash;
input wire [55:0] plain_text;
wire [127:0] hash_ascii;
hex_to_ascii u2(hash,hash_ascii);
reg go;
always@(*)
begin
if(sw0 & ~key[0]) //reset: sw0 up and key0 pressed
begin
sys_reset=1'b1; //hold the LM cracker in reset
go=1'b0;
end
else if(~sw0 & ~key[0])//go: sw0 down and key0 pressed
begin
go=1'b1;
sys_reset=1'b0; //set the LM cracker loose
end
else if(match)
begin
go=1'b0;
end
end
// Host Side
input iCLK,iRST_N_LCD;
// LCD Side
output [7:0] LCD_DATA;
output LCD_RW,LCD_EN,LCD_RS;
// Internal Wires/Registers
reg [5:0] LUT_INDEX;
reg [8:0] LUT_DATA;
reg [5:0] mLCD_ST;
reg [17:0] mDLY;
reg mLCD_Start;
reg [7:0] mLCD_DATA;
reg mLCD_RS;
wire mLCD_Done;
parameter LCD_INTIAL = 0;
parameter LCD_LINE1 = 5;
parameter LCD_CH_LINE = LCD_LINE1+16;
parameter LCD_LINE2 = LCD_LINE1+16+1;
//parameter LUT_SIZE = LCD_LINE1+32+1;
parameter LUT_SIZE = LCD_LINE1+32+1+1; //insert one additional command
//first row cursor. pressing key3 moves left sw0 and k3 to move right
reg [3:0] pos;
always@(posedge ms_tick)
begin
if(~key[3] && ~go)
begin
if(sw0)
pos=pos+4'h1;
else
pos=pos-4'h1;
end
end
reg k1,k2,k3;
//timer registers
reg [31:0] timer;
reg [31:0] timer_ms;
always@(posedge iCLK)
begin
timer=timer+31'd1;
timer_ms=timer_ms+31'd1;
if(timer==32'hcdfe60) //27E6/2
begin
timer=32'd0;
sec_tick=~sec_tick; //switch every 500ms
end
if(timer_ms==32'h2932e0) //27E6 * .1
begin
timer_ms=32'd0;
ms_tick=~ms_tick; //switch every 100ms
end
end
//time elapsed timer since start of LM crack; count in ascii
reg [7:0] digit3,digit2,digit1,digit0,sec; //digit 2 is msb; counts from 0000-9999minutes. sec counts from 0-60 sec
always@(posedge sec_tick) //posedge sec_tick is every one second
begin
if(go)
begin
if(sec==8'd59) //not ascii
begin
sec=8'd0;
if(digit0==8'h39) //ascii
begin
digit0=8'h30;
if(digit1==8'h39)
begin
digit1=8'h30;
if(digit2==8'h39)
begin
digit2=8'h30;
if(digit3==8'h39)
begin
digit3=8'h30;
end
else
begin
digit3=digit3+8'h01;
end
end
else
begin
digit2=digit2+8'h01;
end
end
else
begin
digit1=digit1+8'h01;
end
end
else
begin
digit0=digit0+8'h01;
end
end
else
begin
sec=sec+8'd1;
end
end
else if(~go && ~match)
begin
digit3=8'h30;
digit2=8'h30;
digit1=8'h30;
digit0=8'h30;
sec=8'd0;
end
end
reg sec_tick; //1 second period
reg ms_tick;// 200ms period
wire blink;
assign blink = sec_tick;
always@(posedge ms_tick)
begin
if(~key[2] && ~go) //go up
begin
case(pos)
0:hash[3:0]=hash[3:0]+4'd1;
1:hash[7:4]=hash[7:4]+4'd1;
2:hash[11:8]=hash[11:8]+4'd1;
3:hash[15:12]=hash[15:12]+4'd1;
4:hash[19:16]=hash[19:16]+4'd1;
5:hash[23:20]=hash[23:20]+4'd1;
6:hash[27:24]=hash[27:24]+4'd1;
7:hash[31:28]=hash[31:28]+4'd1;
8:hash[35:32]=hash[35:32]+4'd1;
9:hash[39:36]=hash[39:36]+4'd1;
10:hash[43:40]=hash[43:40]+4'd1;
11:hash[47:44]=hash[47:44]+4'd1;
12:hash[51:48]=hash[51:48]+4'd1;
13:hash[55:52]=hash[55:52]+4'd1;
14:hash[59:56]=hash[59:56]+4'd1;
15:hash[63:60]=hash[63:60]+4'd1;
endcase
end
else if(~key[1] && ~go) //go down
begin
case(pos)
0:hash[3:0]=hash[3:0]-4'd1;
1:hash[7:4]=hash[7:4]-4'd1;
2:hash[11:8]=hash[11:8]-4'd1;
3:hash[15:12]=hash[15:12]-4'd1;
4:hash[19:16]=hash[19:16]-4'd1;
5:hash[23:20]=hash[23:20]-4'd1;
6:hash[27:24]=hash[27:24]-4'd1;
7:hash[31:28]=hash[31:28]-4'd1;
8:hash[35:32]=hash[35:32]-4'd1;
9:hash[39:36]=hash[39:36]-4'd1;
10:hash[43:40]=hash[43:40]-4'd1;
11:hash[47:44]=hash[47:44]-4'd1;
12:hash[51:48]=hash[51:48]-4'd1;
13:hash[55:52]=hash[55:52]-4'd1;
14:hash[59:56]=hash[59:56]-4'd1;
15:hash[63:60]=hash[63:60]-4'd1;
endcase
end
end
always@(posedge iCLK or negedge iRST_N_LCD)
begin
if(!iRST_N_LCD)
begin
LUT_INDEX <= 0;
mLCD_ST <= 0;
mDLY <= 0;
mLCD_Start <= 0;
mLCD_DATA <= 0;
mLCD_RS <= 0;
end
else
begin
if(LUT_INDEXbegin
case(mLCD_ST)
0: begin
mLCD_DATA <= LUT_DATA[7:0];
mLCD_RS <= LUT_DATA[8];
mLCD_Start <= 1;
mLCD_ST <= 1;
end
1: begin
if(mLCD_Done)
begin
mLCD_Start <= 0;
mLCD_ST <= 2;
end
end
2: begin
if(mDLY<18'h3FFFE)
mDLY <= mDLY+1;
else
begin
mDLY <= 0;
mLCD_ST <= 3;
end
end
3: begin
LUT_INDEX <= LUT_INDEX+1;
mLCD_ST <= 0;
end
endcase
end
else //modified to redraw LCD continuously
begin
LUT_INDEX <= LCD_LINE1; //loop
mLCD_ST <= 0;
end
end
end
always
begin
case(LUT_INDEX)
// Initial
LCD_INTIAL+0: LUT_DATA <= 9'h038;
LCD_INTIAL+1: LUT_DATA <= 9'h00C; //display on off cursor and blinking command
LCD_INTIAL+2: LUT_DATA <= 9'h001; //clear display command
LCD_INTIAL+3: LUT_DATA <= 9'h006; //entry mode set command
LCD_INTIAL+4: LUT_DATA <= 9'h080; //set ddram address to 00000000 command
// Line 1
LCD_LINE1+0: LUT_DATA <= {1'b1,match?8'hff:((blink&&(pos==4'd15)&&~go)?8'h20:hash_ascii[127:120])};
LCD_LINE1+1: LUT_DATA <= {1'b1,match?8'hff:((blink&&(pos==4'd14)&&~go)?8'h20:hash_ascii[119:112])};
LCD_LINE1+2: LUT_DATA <= {1'b1,match?(|plain_text[55:48]?plain_text[55:48]:8'hff):((blink&&(pos==4'd13)&&~go)?8'h20:hash_ascii[111:104])};
LCD_LINE1+3: LUT_DATA <= {1'b1,match?(|plain_text[47:40]?plain_text[47:40]:8'hff):((blink&&(pos==4'd12)&&~go)?8'h20:hash_ascii[103:96])};
LCD_LINE1+4: LUT_DATA <= {1'b1,match?(|plain_text[39:32]?plain_text[39:32]:8'hff):((blink&&(pos==4'd11)&&~go)?8'h20:hash_ascii[95:88])};
LCD_LINE1+5: LUT_DATA <= {1'b1,match?(|plain_text[31:24]?plain_text[31:24]:8'hff):((blink&&(pos==4'd10)&&~go)?8'h20:hash_ascii[87:80])};
LCD_LINE1+6: LUT_DATA <= {1'b1,match?(|plain_text[23:16]?plain_text[23:16]:8'hff):((blink&&(pos==4'd9)&&~go)?8'h20:hash_ascii[79:72])};
LCD_LINE1+7: LUT_DATA <= {1'b1,match?(|plain_text[15:8]?plain_text[15:8]:8'hff):((blink&&(pos==4'd8)&&~go)?8'h20:hash_ascii[71:64])};
LCD_LINE1+8: LUT_DATA <= {1'b1,match?(|plain_text[7:0]?plain_text[7:0]:8'hff):((blink&&(pos==4'd7)&&~go)?8'h20:hash_ascii[63:56])};
LCD_LINE1+9: LUT_DATA <= {1'b1,match?8'hff:((blink&&(pos==4'd6)&&~go)?8'h20:hash_ascii[55:48])};
LCD_LINE1+10: LUT_DATA <= {1'b1,match?8'hff:((blink&&(pos==4'd5)&&~go)?8'h20:hash_ascii[47:40])};
LCD_LINE1+11: LUT_DATA <= {1'b1,match?8'hff:((blink&&(pos==4'd4)&&~go)?8'h20:hash_ascii[39:32])};
LCD_LINE1+12: LUT_DATA <= {1'b1,match?8'hff:((blink&&(pos==4'd3)&&~go)?8'h20:hash_ascii[31:24])};
LCD_LINE1+13: LUT_DATA <= {1'b1,match?8'hff:((blink&&(pos==4'd2)&&~go)?8'h20:hash_ascii[23:16])};
LCD_LINE1+14: LUT_DATA <= {1'b1,match?8'hff:((blink&&(pos==4'd1)&&~go)?8'h20:hash_ascii[15:8])};
LCD_LINE1+15: LUT_DATA <= {1'b1,match?8'hff:((blink&&(pos==4'd0)&&~go)?8'h20:hash_ascii[7:0])};
// Change Line
LCD_CH_LINE: LUT_DATA <= 9'h0C0;
// Line 2
LCD_LINE2+0: LUT_DATA <= {1'b1,digit3}; //timer digits
LCD_LINE2+1: LUT_DATA <= {1'b1,digit2};
LCD_LINE2+2: LUT_DATA <= {1'b1,digit1};
LCD_LINE2+3: LUT_DATA <= {1'b1,digit0};
LCD_LINE2+4: LUT_DATA <= 9'h16d; //m
LCD_LINE2+5: LUT_DATA <= 9'h169; //i
LCD_LINE2+6: LUT_DATA <= 9'h16e; //n
LCD_LINE2+7: LUT_DATA <= 9'h12e; //.
LCD_LINE2+8: LUT_DATA <= {1'b1,~match?(go?((blink&&go)?8'h52:8'h20):8'h20):8'h20}; //R
LCD_LINE2+9: LUT_DATA <= {1'b1,~match?(go?((blink&&go)?8'h55:8'h20):8'h73):8'h46}; //U S F
LCD_LINE2+10: LUT_DATA <= {1'b1,~match?(go?((blink&&go)?8'h4e:8'h20):8'h65):8'h4f}; //N E O
LCD_LINE2+11: LUT_DATA <= {1'b1,~match?(go?((blink&&go)?8'h4e:8'h20):8'h74):8'h55}; //N T U
LCD_LINE2+12: LUT_DATA <= {1'b1,~match?(go?((blink&&go)?8'h49:8'h20):8'h75):8'h4e}; //I U N
LCD_LINE2+13: LUT_DATA <= {1'b1,~match?(go?((blink&&go)?8'h4e:8'h20):8'h70):8'h44}; //N P D
LCD_LINE2+14: LUT_DATA <= {1'b1,~match?(go?((blink&&go)?8'h47:8'h20):8'h20):8'h20}; //G
LCD_LINE2+15: LUT_DATA <= 9'h120; //space
//return home command //modified to refresh LCD continuously
LCD_LINE2+16: LUT_DATA <= 9'h002; //38th index
default: LUT_DATA <= 9'h000;
endcase
end
LCD_Controller u0(.iDATA(mLCD_DATA),
.iRS(mLCD_RS),
.iStart(mLCD_Start),
.oDone(mLCD_Done),
.iCLK(iCLK),
.iRST_N(iRST_N_LCD),
.LCD_DATA(LCD_DATA),
.LCD_RW(LCD_RW),
.LCD_EN(LCD_EN),
.LCD_RS(LCD_RS) );
endmodule