源代码:
1. 最初版本(仅满足题目中的基本要求,用 LED 显示输出结果)
module test1(
input [3:0] num1,
input [3:0] num2,
input clk,outcome,
output [3:0] sum
);
reg [3:0]sum;
always@(posedge clk)
begin
if(outcome)
begin
sum=num1+num2;
end
end
endmodule
2. 增加清零功能:
module test1(
input [3:0] num1,
input [3:0] num2,
input clk,outcome,clr,
output [3:0] sum
);
reg [3:0]sum;
always@(posedge clk)
begin
if(outcome)
begin
sum=num1+num2;
end
else if(clr) sum=0;
end
endmodule
3. 使用数码管显示(且溢出时会显示 E):
module test1(
input [3:0] num1,
input [3:0] num2,
input clk,outcome,clr,
output reg [6:0] a_to_g,
output reg [3:0]lead
);
reg [4:0]sum;
reg [1:0]tmp;
reg[32:0]cln;
always@(*)
begin
case(tmp)
0:a_to_g=7'b1111110;
1:a_to_g=7'b0110000;
default:a_to_g=7'b1001111;
endcase
end
always@(posedge clk)
if(outcome) sum=num1+num2;
else if(clr) sum=0;
always@(posedge clk)
cln=cln+1;
always@(*)
begin
if(!sum[4])
begin
case(cln[13:12])
0:begin tmp=sum[0];
lead=4'b1000;end
1:begin tmp=sum[1];
lead=4'b0100;end
2:begin tmp=sum[2];
lead=4'b0010;end
3:begin tmp=sum[3];
lead=4'b0001;end
endcase
end
else
begin
case(cln[13:12])
0:begin tmp=3;
lead=4'b1000;end
1:begin tmp=3;
lead=4'b0100;end
2:begin tmp=3;
lead=4'b0010;end
3:begin tmp=3;
lead=4'b0001;end
endcase
end
end
endmodule
4. 拓展功能:使用微动开关输入数值,数码管动态显示数值与符号(用 LED 显示),在微
动开关弹起时有效,并添加开关防抖功能
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2019/09/28 13:31:07
// Design Name:
// Module Name: test1
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module test1(
input button1,button0,button_add,button_minus,//按键 0,1,加,减
input clk,outcome,clr,//时钟,等于号(显示结果的按键),清零
output reg [6:0] a_to_g,
output reg [3:0]lead,//控制四个数码管的亮暗与否
output reg [7:0]lattice=8'b00000000//控制 LED 显示符号
);
reg [4:0]sum=5'b00000;//两个数字的和或差
reg [1:0]tmp;
reg[32:0]cln;//一个多位数的时钟,用于数码管显示
reg[3:0]num1=4'b0000,num2=4'b0000;//数字 1 与数字 2
reg sign;//用于判断加法还是减法
reg [3:0]detector1=4'b0000,detector2=4'b0000;//用于检测输入数字 1 与数字 2 的
情况
reg outcome_state=0,button_add_state=0,button_minus_state=0;// 判断 这几 个按
键被按下的状态是否有效
reg [31:0]outcome_in,add_in,minus_in,button1_in,button0_in;
wire outcome_in_pos,add_in_pos,minus_in_pos,button1_in_pos,button0_in_pos;//用
于判断当按键松开时输出为 1
integer tmpi;//循环变量
always@(posedge clk)
begin
if(clr) //清零
begin
sum<=5'b00000;
outcome_state=0;
button_add_state=0;
button_minus_state=0;
end
//此部分为:若加或减被按下且有效则更改开关 state 状态,为后续显示 LED 做铺垫
else if(add_in_pos)
begin
sign<=1;
button_add_state<=~button_add_state;
end
else if(minus_in_pos)
begin
sign<=0;
button_minus_state<=~button_minus_state;
end
if(outcome_in_pos)
outcome_state<=1;
if(sign)//用于判断加法还是减法,调整 sum 的值(其实应该是 sum 或 difference)
sum=num1+num2;
else if(~sign)sum=num1-num2;
end
always@(*)
begin
case(tmp)
0:a_to_g=7'b1111110;
1:a_to_g=7'b0110000;
default:a_to_g=7'b1001111;
endcase
end
always@(posedge clk)//此部分用于输入数字 1 与 2 的值
if(clr)//清零
begin
detector1=4'b0000;
detector2=4'b0000;
num1=4'b0000;
num2=4'b0000;
end
else
begin
for(tmpi=0;tmpi<4;tmpi=tmpi+1)//此循环可保证输入 0,1 数字串的顺序正确性,不会因
always 语句一直运行而导致无法判别 0,1 的顺序
if(~detector1[tmpi]&&(tmpi==0||detector1[tmpi-1]))
begin
if(button0_in_pos)
begin
num1[3-tmpi]<=0;
detector1[tmpi]<=1;
end
else if(button1_in_pos)
begin
num1[3-tmpi]<=1;
detector1[tmpi]<=1;
end
end
if(detector1==4'b1111&&(button_add_state||button_minus_state))
begin
for(tmpi=0;tmpi<4;tmpi=tmpi+1)
if(!detector2[tmpi]&&(tmpi==0||detector2[tmpi-1]))
if(button0_in_pos)
begin
num2[3-tmpi]<=0;
detector2[tmpi]<=1;
end
else if(button1_in_pos)
begin
num2[3-tmpi]<=1;
detector2[tmpi]<=1;
end
end
end
always@(posedge clk)//此部分用于判断微动开关的按下是否有效,且有一定防抖功能
begin
outcome_in[31:0]<={outcome_in[30:0],outcome};
add_in[31:0]<={add_in[30:0],button_add};
minus_in[31:0]<={minus_in[30:0],button_minus};
button1_in[31:0]<={button1_in[30:0],button1};
button0_in[31:0]<={button0_in[30:0],button0};
end
assign outcome_in_pos=outcome_in[31]&~outcome_in[30]&~outcome_in[0];
assign add_in_pos=add_in[31]&~add_in[30]&~add_in[0];
assign minus_in_pos=minus_in[31]&~minus_in[30]&~minus_in[0];
assign button1_in_pos=button1_in[31]&~button1_in[30]&~button1_in[0];
assign button0_in_pos=button0_in[31]&~button0_in[30]&~button0_in[0];
always@(posedge clk)//一个随时钟而增加的值,便于控制数码管显示
cln=cln+1;
always@(posedge clk)//控制显示符号的部分
if(clr)
lattice=8'b00000000;
else if(button_add_state&&~outcome_state)
lattice=8'b11000000;
else if(button_minus_state&&~outcome_state)
lattice=8'b00110000;
else if(outcome_state)
lattice=8'b00001111;
else
lattice=8'b00000000;
/**/
always@(posedge clk)//控制显示数码管
if(clr)
tmp<=0;
else
begin
if(detector1==4'b1111&&detector2==4'b1111&&outcome_state==1)// 两 个 数 字 都 已
输入有效且按下了等号输出结果
begin
if(!sum[4])//溢出
begin
case(cln[13:12])
0:begin tmp=sum[0];
lead=4'b1000;end
1:begin tmp=sum[1];
lead=4'b0100;end
2:begin tmp=sum[2];
lead=4'b0010;end
3:begin tmp=sum[3];
lead=4'b0001;end
endcase
end
else//非溢出
begin
case(cln[13:12])
0:begin tmp=3;
lead=4'b1000;end
1:begin tmp=3;
lead=4'b0100;end
2:begin tmp=3;
lead=4'b0010;end
3:begin tmp=3;
lead=4'b0001;end
endcase
end
end
else if(detector1==4'b0000)//两个数字均未输入
case(cln[13:12])
0:begin tmp=0;
lead=4'b1000;end
1:begin tmp=0;
lead=4'b0100;end
2:begin tmp=0;
lead=4'b0010;end
3:begin tmp=0;
lead=4'b0001;end
endcase
else if(detector1==4'b0001)//第一个数字已输入一位
begin tmp=num1[3];
lead=4'b1000;end
else if(detector1==4'b0011)//第一个数字已输入两位
case(cln[13:12])
0:begin tmp=num1[2];
lead=4'b1000;end
1:begin tmp=num1[3];
lead=4'b0100;end
endcase
else if(detector1==4'b0111)//第一个数字已输入三位
case(cln[13:12])
0:begin tmp=num1[1];
lead=4'b1000;end
1:begin tmp=num1[2];
lead=4'b0100;end
2:begin tmp=num1[3];
lead=4'b0010;end
endcase
else if(detector1==4'b1111&&detector2==4'b0000)//第一个数字已输入完成且第二位
数字未输入
case(cln[13:12])
0:begin tmp=num1[0];
lead=4'b1000;end
1:begin tmp=num1[1];
lead=4'b0100;end
2:begin tmp=num1[2];
lead=4'b0010;end
3:begin tmp=num1[3];
lead=4'b0001;end
endcase
else if(detector2==4'b0001)//第二个数字输入 1 位
begin tmp=num2[3];
lead=4'b1000;end
else if(detector2==4'b0011)//第二个数字输入两位
case(cln[13:12])
0:begin tmp=num2[2];
lead=4'b1000;end
1:begin tmp=num2[3];