Em viết 1 mini calculator, thực hiện các phép + _ * / . Tất cả chạy ổn định rồi. Em viết thêm phím nhớ M+,MR để gọi số nhớ, MC xóa số nhớ. Em dung biến mem[n:0] để lưu kết quả phép tính, khi nhấn MR thì xuất ra LCD. Nghĩ đơn giản nhưng khi viết lại ko chạy được. ĐÂy chỉ là module xử lý chính, em còn các module quét phím, chuyển binary sang BCD để hiện thị LCD nữa. 2 state em dùng cho phím nhớ là hienthi_state và phímnhớ_state. Em viết theo lưu đồ máy trạng thái. Các anh xem góp y cho em với ạ,
Nếu em thay phim C = phím DEL tức là xóa từng kí tự, có vẻ công việc sẽ phức tạp vì giá trị nhập trong input_state sẽ đc nhân 10+ giá trị mới nhập, vậy nếu ta xóa 1 số sẽ chia 10 lấy phần nguyên, nhưng việc đó làm thế nào xin các anh chị góp ý.
Nếu em thay phim C = phím DEL tức là xóa từng kí tự, có vẻ công việc sẽ phức tạp vì giá trị nhập trong input_state sẽ đc nhân 10+ giá trị mới nhập, vậy nếu ta xóa 1 số sẽ chia 10 lấy phần nguyên, nhưng việc đó làm thế nào xin các anh chị góp ý.
Code:
module maincontrol(clock, data_ready, scan_code,lcd_out, lcd_rs,lcd_en,lcd_rw);
parameter n=44;
parameter n_div =61;
parameter int_digit=8;
parameter fract_digit=5;
parameter digit=13;
input clock;
input data_ready;
input [7:0] scan_code;
output [7:0] lcd_out;
output lcd_rs;
output lcd_en;
output reg lcd_rw;
parameter lcd_start_state =5'b 00000;
parameter lcd_set_state =5'b 00001;
parameter AC_state =5'b 00010;
parameter C_state =5'b 00011;
parameter input_state =5'b 00100;
parameter two_opr_state =5'b 00101;
parameter two_opr1_state =5'b 00110;
parameter wait_state =5'b 00111;
parameter scancode_state =5'b 01000;
parameter div_S0_state =5'b 10110;
parameter div_S1_state =5'b 10111;
parameter div_S2_state =5'b 11000;
parameter div_S3_state =5'b 11001;
parameter to_uniform_state=5'b 11010;
parameter lcd_wait_state =5'b 11011;
parameter lcd_wait1_state =5'b 11100;
parameter phimnho_state =5'b 11101;
parameter hienthi_state =5'b 11110;
reg [4:0] state;
//----------------------------------ma phim nhan
// hang 1
parameter zero_sc =8'b 11011110; // so 0
parameter point_sc =8'b 11101110; // dau .
parameter equal_sc =8'b 10111110; // dau =
parameter AC_sc =8'b 01111110; // phim AC/C
// hang 2
parameter seven_sc =8'b 11101101; // so 7
parameter eight_sc =8'b 11011101; // so 8
parameter mc_sc =8'b 10111101; // so 9
parameter madd_sc =8'b 01111101; // phim shift
// hang 3
parameter four_sc =8'b 11101011; // so 4
parameter five_sc =8'b 11011011; // so 5
parameter six_sc =8'b 10111011; // so 6
parameter mr_sc =8'b 01111011; // dau x/:
// hang 4
parameter one_sc =8'b 11100111; // so 1
parameter two_sc =8'b 11010111; // so 2
parameter three_sc =8'b 10110111; // so 3
parameter add_sc =8'b 01110111; // dau +/-
// khai bao phep tinh hai toan hang
parameter non_op =4'b 0000;
parameter add =4'b 0001;
parameter sub =4'b 0010;
parameter div =4'b 0011;
parameter mul =4'b 0100;
reg shift_flag; // bao cho biet tinh arc
reg [3:0] number_value;
reg [n:0] input_value;
reg [n:0] result_value;
reg [n+1:0] return_add;
reg [n+1:0] mem;
reg equal,mad;
reg [3:0] cur_op;
reg [3:0] next_op;
reg point_flag;
reg [2*n:0] return_mul;
// dem digit
reg [4:0] int_cnt; // truoc dau .
reg [4:0] fract_cnt; // sau dau .
// bo chia
reg [n_div:0] div1_s;
reg [n:0] div2_s;
reg [n_div:0] quotient; // ket qua
reg [n+n_div-2:0] divider; // so chia
reg [n_div-1:0] dividend; // so bi chia
reg [5:0] div_cnt;
// khai bao cho lcd
reg [2:0] lcd_sel_s;
reg [7:0] lcd_val_s;
reg [n:0] lcd_result_s; // ket qua hiet thi lcd
reg lcd_start_s; // ban dau phai cho la 1
wire lcd_ready_s;
reg lcd_clear_flag;
reg sc_return_flag; // sau khi xoa lcd thi tra ve trang thai scancode
wire lcd_err_s;
reg [n:0] tam;
reg [4:0] dem;
// ham nhan10 61bit
function [n_div:0] mul_10_ext;
input [n_div:0] l;
reg [n_div-1:0] l_3; // nhan 2^3;
reg [n_div-1:0] l_1; // nhan 2^1;
reg [n_div:0] result;
begin
l_3={l[n_div-4:0],3'b 000};
l_1={l[n_div-2:0],1'b 0};
result[n_div]= l[n_div];
result[n_div-1:0]=l_3+l_1;
mul_10_ext=result;
end
endfunction
// ham nhan 10
function [n:0] mul_10;
input [n:0] l;
reg [n-1:0] l_3; // nhan 2^3;
reg [n-1:0] l_1; // nhan 2^1;
reg [n:0] result;
begin
l_3={l[n-4:0],3'b 000};
l_1={l[n-2:0],1'b 0};
result[n]= l[n];
result[n-1:0]=l_3+l_1;
mul_10=result;
end
endfunction
// ham cong_tru
function [n+1:0] add_sub;
input sign_l;
input sign_r;
input [n-1:0] l;
input [n-1:0] r;
reg [n+1:0] result;
begin
if((sign_l^sign_r)==1) // khac dau
begin
if(l>=r)
begin
result[n+1]=sign_l; // l>r dau cua ket qua giong dau cua l
result[n:0]= ({1'b0,l})-({1'b 0,r});
end
else
begin
result[n+1]=sign_r;
result[n:0]= ({1'b0,r})-({1'b 0,l});
end
end
else // cung dau
begin
result[n+1]=sign_l;
result[n:0]= ({1'b0,l})+({1'b 0,r});
end
add_sub=result;
end
endfunction
// ham nhan
function [2*n:0] multiplier;
input [n:0] l,r;
reg [2*n:0] result;
begin
result[2*n]=(l[n]^r[n]);
result[2*n-1:0]=l[n-1:0]*r[n-1:0];
multiplier=result;
end
endfunction
lcd_modul z(clock,lcd_sel_s,lcd_start_s,lcd_val_s,lcd_result_s,lcd_ready_s,lcd_en,lcd_err_s,lcd_rs,lcd_out);
always @(posedge clock)
begin
lcd_rw=0;
mem=0;
case (state)
lcd_start_state: begin
lcd_start_s=1;
state=lcd_set_state;
end
lcd_set_state: begin
lcd_sel_s = 3'b 000; // set func cho lcd
if(lcd_ready_s==1)
begin
lcd_start_s=0;
state=AC_state;
end
end
lcd_wait_state: begin // cho lcd_ready xuong muc thap
if (lcd_ready_s==0)
state=lcd_wait1_state;
end
lcd_wait1_state:begin // cho lcd_ready len muc 1
if (lcd_ready_s==1)
begin
lcd_start_s=0;
if (sc_return_flag==1) // xoa hien thi roi tra ve trang thai nhap
begin
state=scancode_state; // vi khi co phim an moi xoa ket qua
sc_return_flag=0; // dang nhap ky tu nay nen phai tra ve trang thai scancode
end
else
state=wait_state; // cho nhap ky tu moi
end
end
AC_state: begin
int_cnt=0;
fract_cnt=0;
result_value=0;
input_value=0;
lcd_result_s=0;
next_op=non_op;
cur_op=non_op;
point_flag=0;
lcd_start_s=1;
lcd_sel_s=3'b 001; // clear lcd
shift_flag=0;
lcd_clear_flag=0;
equal=0;
state=lcd_wait_state;
end
C_state: begin
int_cnt=0;
fract_cnt=0;
shift_flag=0;
input_value=0;
point_flag=0;
lcd_start_s=1;
lcd_sel_s=3'b 001; // clear lcd
state=lcd_wait_state;
end
scancode_state: begin
if(lcd_err_s==1)
begin
if(scan_code==AC_sc)
state=AC_state;
end
else
begin
if(data_ready==1)
begin
if(lcd_clear_flag==1) // xoa hien thi chuan bi nhap moi
begin
if(scan_code==add_sc)
lcd_clear_flag=0;
else
begin
lcd_clear_flag=0; // khi an phim moi xoa ket qua cu
lcd_start_s=1;
lcd_sel_s=3'b 001;
sc_return_flag=1;
state=lcd_wait_state;
end
end
else
begin
case (scan_code)
AC_sc : begin
if(shift_flag==0)
state=AC_state;
else
state=C_state; //phim C
end
zero_sc : begin
number_value=4'b 0000;
state=input_state;
end
one_sc : begin
number_value=4'b 0001;
state=input_state;
end
two_sc : begin
number_value=4'b 0010;
state=input_state;
end
three_sc: begin
number_value=4'b 0011;
state=input_state;
end
four_sc : begin
number_value=4'b 0100;
state=input_state;
end
five_sc : begin
number_value=4'b 0101;
state=input_state;
end
six_sc : begin
number_value=4'b 0110;
state=input_state;
end
seven_sc: begin
number_value=4'b 0111;
state=input_state;
end
eight_sc: begin
number_value=4'b 1000;
state=input_state;
end
/* nine_sc : begin
number_value=4'b 1001;
state=input_state;
end */
madd_sc : begin
state=phimnho_state;
end
mr_sc : begin
state=hienthi_state;
end
mc_sc : begin
mem=0;
state=lcd_wait_state;
end
add_sc : begin // hai toan hang
if(shift_flag==0)
begin
next_op=add;
state=to_uniform_state;
end
else //phep -
begin
next_op=sub;
state=to_uniform_state;
end
end
/* mul_sc : begin // hai toan hang
if(shift_flag==0)
begin
next_op=mul;
state=to_uniform_state;
end
else //phep :
begin
next_op=div;
state=to_uniform_state;
end
end */ // mot toan hang
/* shift_sc: begin
shift_flag=~(shift_flag); // chua xoa cac co nay
lcd_start_s=1;
lcd_sel_s=3'b 110;
state=lcd_wait_state;
end */
point_sc: begin // dau cham thap phan
point_flag=1;
lcd_start_s=1;
lcd_sel_s=3'b 010; // right shift
lcd_val_s=8'h 2E;
state=lcd_wait_state;
end
equal_sc: begin // dau =
equal=1;
next_op=non_op;
state=to_uniform_state;
end
default : ;
endcase
end
end
end
end
input_state : begin
if(point_flag==1)
begin
if(fract_cnt==fract_digit) // so digit cho phep sau dau cham thap phan
state=wait_state; // tro ve trang thi cho nhap ky tu
else
begin
fract_cnt=fract_cnt+1;
input_value=mul_10(input_value)+number_value;
lcd_val_s= { 4'b 0011, number_value};
lcd_start_s=1;
lcd_sel_s=3'b 010; // dich phai
state=lcd_wait_state;
end
end
else
begin
if(int_cnt==int_digit) // so digit cho phep truoc dau cham thap phan
state=wait_state; // tro ve trang thi cho nhap ky tu
else
begin
int_cnt=int_cnt+1;
input_value=mul_10(input_value)+number_value;
lcd_val_s= { 4'b 0011, number_value};
lcd_start_s=1;
lcd_sel_s=3'b 010; // dich phai
state=lcd_wait_state;
end
end
end
to_uniform_state:begin // xu ly gia tri nhap vao cho vo dang a.10^-3
shift_flag=0; // xoa shift
if(fract_cnt==fract_digit)
begin
point_flag=0;
if(cur_op==sub)
begin
input_value[n]=~input_value[n];
cur_op=add;
end
state=two_opr_state;
if (mad==1)
state=phimnho_state;
end
else
begin
input_value=mul_10(input_value);
fract_cnt=fract_cnt+1;
state=to_uniform_state;
end
end
two_opr_state: begin // do cur_op luu gia tri truoc sau 1 xung clock thi cong tru chung
case (cur_op)
add : begin
return_add=add_sub(result_value[n],input_value[n],result_value[n-1:0],input_value[n-1:0]);
state=two_opr1_state;
end
mul : begin
return_mul=multiplier(result_value,input_value);
state=two_opr1_state;
end
div : begin
div1_s[n_div]=result_value[n];
div1_s[n_div-1:0]=0;
div1_s[n-1:0]=result_value[n-1:0];
div2_s=input_value;
cur_op=next_op;
state=div_S0_state;
end
non_op: begin
cur_op=next_op;
if(equal==1)
equal=0;
else // neu khong phaidau bang thi luu ket qua vao ket qua
begin
result_value=input_value;
end
lcd_clear_flag=1;
state=wait_state;
end
default:;
endcase
int_cnt=0;
fract_cnt=0;
input_value=0;
end
two_opr1_state: begin // xu ly ket qua tra ve
case (cur_op)
add : begin
if(return_add[n]==1) // tran
begin
lcd_start_s=1;
lcd_sel_s=3'b 100; // bao loi
end
else
begin
lcd_start_s=1;
result_value[n]=return_add[n+1];
result_value[n-1:0]=return_add[n-1:0];
lcd_result_s[n]=return_add[n+1];
lcd_result_s[n-1:0]=return_add[n-1:0];
lcd_sel_s=3'b 011; // hien thi ket qua ra lcd
lcd_clear_flag=1;
end
state=lcd_wait_state;
end
mul : begin
if(return_mul[2*n-1:n_div]!= 33'h 000000000) // tran
begin
lcd_start_s=1;
lcd_sel_s=3'b 100; // bao loi
state=lcd_wait_state;
end
else
begin
div1_s[n_div]=return_mul[2*n];
div1_s[n_div-1:0]=return_mul[n_div-1:0];
div2_s[n:17]=0;
div2_s[16:0]=20'h 186A0; // 100000
state=div_S1_state;
end
end
default:;
endcase
point_flag=0;
cur_op=next_op;
int_cnt=0;
fract_cnt=0;
input_value=0; // reset lai gia tri nhap
end
// bo chia
div_S0_state: begin // mul 1000 voi so bi chia
if(div_cnt==5'b 00011)
begin
div1_s=mul_10_ext(div1_s);
div_cnt=div_cnt+1;
end
else if(div_cnt==5'b 00101)
begin
div_cnt=0;
state=div_S1_state;
end
else
begin
div1_s=mul_10_ext(div1_s);
div_cnt=div_cnt+1;
end
end
div_S1_state: begin
div_cnt=n_div-1;
divider[n_div-2:0]=0; // nhan voi 2^(nSB-1) cua ket qua
dividend=div1_s[n_div-1:0];
divider[n+n_div-2:n_div-1]=div2_s[n-1:0];
state=div_S2_state;
end
div_S2_state: begin
if(divider[n+n_div-2:n_div]!=43'h 00000000000)
quotient[div_cnt]=0;
else
begin
if(dividend>=divider[n_div-1:0])
begin
quotient[div_cnt]=1;
dividend=dividend-divider[n_div-1:0];
end
else
quotient[div_cnt]=0;
end
divider={1'b 0,divider[n+n_div-2:1]}; // n-1 lan lap de tinh duoc n-1 gia tri cua thuong
if(div_cnt==0)
begin
div_cnt=0;
quotient[n_div]=div1_s[n_div] ^ div2_s[n];
state=div_S3_state;
end
else
begin
div_cnt=div_cnt-1;
state=div_S2_state;
end
end
div_S3_state: begin
if(quotient[n_div-1:n]!= 17'h 0000) // tran
begin
lcd_start_s=1;
lcd_sel_s=3'b 100; // bao loi
state=lcd_wait_state;
end
else
begin
result_value[n]=quotient[n_div]; // dau
result_value[n-1:0]=quotient[n-1:0];
end
lcd_result_s[n]=quotient[n_div]; // dau
lcd_result_s[n-1:0]=quotient[n-1:0];
lcd_start_s=1;
lcd_sel_s= 3'b 011; // hien thi ket qua ra lcd
lcd_clear_flag=1; // bao xoa khi co 1 phim duoc an de nhap moi
state =lcd_wait_state;
end
phimnho_state: begin
mem=add_sub(lcd_result_s[n],mem[n],lcd_result_s[n-1:0],mem[n-1:0]);
if(mem[n]==1) // tran
begin
mem[n]=0;
mem[n-1:0]=0;
state=lcd_wait_state;
end
end
hienthi_state : begin
lcd_start_s=1;
lcd_result_s[n]=mem[n+1];
lcd_result_s[n-1:0]=mem[n-1:0];
lcd_sel_s=3'b 011; // hien thi ket qua ra lcd
lcd_clear_flag=1;
state=lcd_wait_state;
end
wait_state : begin // trang thai cho scan code ready xuong 0
if(data_ready==0)
state=scancode_state;
else
state=wait_state;
end
default: ;
endcase
end
endmodule

Comment