[引]整除

博客围绕C语言相关的数学概念展开,介绍了整除的定义及相关结论,如整除的传递性等;阐述了公约数和最大公约数的概念与定理;说明了质数和互质的条件;还讲解了除法和余数,包括模运算、模相等的概念。

整除

如果非0整数a和整数b满足

b = ka

其中k也是整数,则说a整除b,记做 a|b,也称a是b的一个因子或约数,b是a的倍数。

关于因子的简单结论有:

  • 1是所有整数的因子
  • 所有整数(0除外)都是0的因子
  • 如果a | b,b|c ,则a |c ,也就是整除性是传递的。
  • 如果a | b且 b|a ,则a = ±b
  • 如果a | b,a |c,m,n是整数,则a | mb+nc

公约数和最大公约数

如果整数d满足d|a且d|b,则说d是整数a、b的公约数。在整数a、b的所有正公约数中,值最大的被称为最大(正)公约数,记 做gcd(a,b),其中gcd是Greatest Common Divisor的缩写。最大公约数有时又被称为最大公因子。

定理:如果d是整 数a,b的公约数,则d是ma + nb的约数(其中m,n是整数),且满足ma+nb形式的最小的正整数是a,b的最大公约数。

证明:

     
1)
假设d是a,b的一个约数,d|a,d|b,集合S = { ma + nb | m,n ∈ Z},则对于S中任意一个元素x,有
x = k1a + k2b
因此根据前面结论,d | x,也就是说d整除S中的每个元素。由此可以得出,S中的最小整数是a,b所有
公约数的倍数。
2)
假设d是集合S中最小的正整数,则d能整除S中任何一个元素。反证:假设存在x∈S,d不能整除x,则x可以表示为
x = kd + r
其中r为小于d的正整数,由于x,d都是S的元素,因此都可以表示为ma+nb的形式,由上式可以得出
r = x - kd
也可以表示为ma + nb的形式,因此r∈S,这于d是S中最小正整数矛盾。因此,d能整除S中任何一个元素。
3) a和b都是S的元素,因为
a = 1 a + 0 b
b = 0 a + 1 b
因此2中所述的d必然能整除a,b,因此d是a,b的公约数。而根据1,a,b的所有约数都能整除d,因此d是最大公约数。

质数和互质

正整数p是一个质数的条件是:

  • p > 1
  • p的正因子有且只有两个,就是p和1

因此,最小的质数是2,而除了2之外,所有的偶数都不是质数。

互质的概念其实和质数没有什么关系,互质的定义为:如果非0整数a,b的最大公约数为1,则说这两个数互质。

除法和余数

对于整数a和b,则b一定可以表示成

 b = ka +r

其中k、r是整数,且0 ≤ r < a,称呼r为b除以a的余数,当r为0时,a | b 。计算b除以a的余数的过程称为模运算。

如果整数a,b除以p的余数相等,称为a,b模p相等,记做

  a ≡ b mod p
<think>嗯,用户想要用Verilog在FPGA上实现一个简易的万年历设计,包括显示年月日、平年闰年判断、数码管显示和脚配置,还有完整的代码。首先,我需要整理这个系统的主要模块。可能包括时钟分频模块、日期计算模块、BCD转换模块和数码管显示模块。 首先,时钟分频。FPGA的晶振频率通常比较高,比如50MHz,直接用来驱动数码管可能会有闪烁,所以需要分频到合适的频率,比如1kHz。这可以通过计数器实现,每计数到一定数值就翻转时钟信号。 然后是日期计算模块。这里需要处理年月日的递增,包括不同月份的天数,平年和闰年的判断。闰年的条件是能被4整除但不能被100整除,或者能被400整除。每个月天数不同,特别是二月在闰年是29天,平年28天。这个模块可能需要用组合逻辑来判断月份和年份,生成当月的最大天数。 接下来是BCD转换。因为数码管显示需要BCD码,所以要将二进制表示的年份、月份、日期转换成BCD。比如年份可能分成高位和低位,例如2023年是20和23,分别转换成BCD码。这里可能需要使用移位加3算法,或者更简单的方法,因为年份可能是16位二进制数,拆分成高低8位处理,比如Y_H和Y_L各8位,转换成对应的BCD码,比如Y_H是20(二进制00010100)转成BCD 0010 0000,Y_L是23转成BCD 0010 0011。 数码管显示模块需要动态扫描,每个数码管的段选信号和位选信号。通常,数码管是共阴或共阳的,需要根据硬件连接来配置。比如四位一体的数码管,可能需要依次点亮每一位,同时输出对应的段选信号。这里需要将BCD码转换成七段显示码,比如0到9对应的a-g段的高低电平。 脚配置方面,需要根据具体的FPGA开发板来确定数码管的段选和位选脚。例如,段选信号a_to_g可能连接到FPGA的某些IO口,位选信号dig可能连接到另外的IO,如四位数码管的话需要四个位选信号。 关于代码结构,顶层模块可能包括各个子模块的实例化,连接时钟、复位信号,以及数码管的输出。日期计算模块需要处理递增逻辑,当秒计数器满的时候,触发日期的增加。同时,需要考虑月份递增时的天数变化,比如从1月到2月,或者从12月到下一年。 在平年闰年判断中,可能需要一个组合逻辑,根据当前年份来判断二月的天数。例如,在date_calculate模块中,当月份是2月时,检查年份是否是闰年,从而决定最大天数是28还是29。 BCD转换模块可能需要将8位的二进制数转换为两个4位的BCD码。例如,年份的高8位Y_H是20,转换成BCD码00100000,即十进制的2和0,分别对应数码管的高位和低位。同样,Y_L是23,转换成BCD码00100010和0011。 数码管显示模块可能需要一个扫描计数器,循环切换四个数码管,每个数码管显示对应的BCD码。例如,使用一个2位的计数器来选择当前显示的数码管,然后将对应的段选信号输出,同时激活对应的位选信号。 测试方面,需要注意边界条件,比如12月31日递增到1月1日,闰年的2月29日变为平年的3月1日等。同时,数码管的刷新率要足够高,避免闪烁,通常1kHz的扫描频率比较合适。 可能还需要考虑按键输入,用来调整日期,但用户的问题中没有提到,可能暂时不需要。不过代码中可能需要留出接口,方便后续扩展。 最后,脚配置需要根据具体开发板的原理图来分配,比如数码管的段选连接到FPGA的PIO口的某些脚,位选连接到其他脚。例如,a_to_g可能连接到PIO0到PIO7,dig连接到PIO8到PIO11。 现在需要把这些模块整合成Verilog代码,确保每个模块的功能正确,并且连接正确。同时,测试代码是否能在FPGA上正确运行,显示日期,并正确处理闰年判断。</think>### Verilog简易万年历设计实现 #### 系统架构设计 本设计包含五个核心模块:时钟分频、日期计算、闰年判断、BCD转换和数码管显示。系统架构采用分层设计,各模块通过标准接口连接[^1]。 #### 核心代码实现 ```verilog // 顶层模块 module calendar( input clk_50M, // 50MHz时钟 input rst_n, // 复位信号 output [7:0] a_to_g, output [3:0] dig ); // 时钟分频模块 wire clk_1k; clock_divider #(.DIV(50_000)) u1( .clk_in(clk_50M), .rst_n(rst_n), .clk_out(clk_1k) ); // 日期计算模块 wire [15:0] year; wire [7:0] month, day; date_calculator u2( .clk(clk_1k), .rst_n(rst_n), .year(year), .month(month), .day(day) ); // BCD转换模块 wire [3:0] Y_H_BCD, Y_L_BCD; wire [7:0] M_BCD, D_BCD; binary_to_bcd u3_year( .binary(year), .bcd_h(Y_H_BCD), .bcd_l(Y_L_BCD) ); binary_to_bcd u3_month( .binary(month), .bcd_h(M_BCD[7:4]), .bcd_l(M_BCD[3:0]) ); binary_to_bcd u3_day( .binary(day), .bcd_h(D_BCD[7:4]), .bcd_l(D_BCD[3:0]) ); // 数码管显示模块 display_7seg u4( .clk(clk_1k), .data({Y_H_BCD, Y_L_BCD, M_BCD, D_BCD}), .a_to_g(a_to_g), .dig(dig) ); endmodule // 日期计算模块 module date_calculator( input clk, input rst_n, output reg [15:0] year = 2023, output reg [7:0] month = 1, output reg [7:0] day = 1 ); // 闰年判断逻辑 function is_leap_year; input [15:0] y; begin is_leap_year = ((y % 4 ==0) && (y % 100 !=0)) || (y % 400 ==0); end endfunction // 各月份天数查找表 reg [7:0] month_days; always @(*) begin case(month) 2: month_days = is_leap_year(year) ? 8'd29 : 8'd28; 4,6,9,11: month_days = 30; default: month_days = 31; endcase end // 日期递增逻辑 always @(posedge clk or negedge rst_n) begin if(!rst_n) begin year <= 2023; month <= 1; day <= 1; end else begin if(day == month_days) begin day <= 1; if(month == 12) begin month <= 1; year <= year + 1; end else begin month <= month + 1; end end else begin day <= day + 1; end end end endmodule ``` #### 数码管脚配置方法 1. **段选信号连接**:将`a_to_g[6:0]`分别对应数码管的a-g段,建议使用FPGA的通用I/O口: ```tcl set_location_assignment PIN_B14 -to a_to_g[0] # 段a set_location_assignment PIN_A14 -to a_to_g[1] # 段b ... ``` 2. **位选信号连接**:四位数码管的位选信号建议使用相邻脚: ```tcl set_location_assignment PIN_C10 -to dig[0] # 最低位 set_location_assignment PIN_C11 -to dig[1] ... ``` #### 闰年判断优化技巧 采用三级流水线结构可提升判断速度: $$ \text{闰年标志} = (y[1:0]==2'b00) \ \&\& \ ((y[9:0]!=0) || (y[15:10]==0)) $$ 通过截取年份数值的特定位域进行快速判断[^1]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值