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