设为首页收藏本站帮助中心
查看: 210|回复: 0
收起左侧

Quartus Verilog HDL/FPGA 判断18位居民身份证号码格式是否有效以及获取出生日期,性别

[复制链接]
发表于 2023-3-11 10:40:31 | 显示全部楼层 |阅读模式
本帖最后由 HDL 于 2023-3-11 10:39 编辑

main.png
  1. `define leap_year(y) (((y)%4 == 0 && (y)%100 != 0) || (y)%400 == 0)                        //是否闰年?

  2. module is_idcard(
  3.         input [59:0] id,                //[60位宽] 18位中国居民身份证号码
  4.         input x,                                        //校验位是否为X
  5.         output reg ok,                        //校验是否正确
  6.         output gender,                        //性别:0女 1男
  7.         output [13:0] year,        //[14位宽] 出生年:0~9999
  8.         output [3:0] month,        //[4位宽] 出生月:1~12
  9.         output [4:0] day                //[5位宽] 出生日:1~31
  10. );
  11. wire [59:0] i [18:1];
  12. wire [3:0] j [18:1];                        //定义18个4位宽线网
  13. assign i[1] = (id / 60'd100000000000000000) % 60'd10;                        //省份代码十位
  14. assign i[2] = (id / 60'd10000000000000000) % 60'd10;                        //省份代码个位
  15. assign i[3] = (id / 60'd1000000000000000) % 60'd10;                        //城市代码十位
  16. assign i[4] = (id / 60'd100000000000000) % 60'd10;                                //城市代码个位
  17. assign i[5] = (id / 60'd10000000000000) % 60'd10;                                //区县代码十位
  18. assign i[6] = (id / 60'd1000000000000) % 60'd10;                                //区县代码个位
  19. assign i[7] = (id / 60'd100000000000) % 60'd10;                                        //出生年千位
  20. assign i[8] = (id / 60'd10000000000) % 60'd10;                                        //出生年百位
  21. assign i[9] = (id / 60'd1000000000) % 60'd10;                                        //出生年十位
  22. assign i[10] = (id / 60'd100000000) % 60'd10;                                        //出生年个位
  23. assign i[11] = (id / 60'd10000000) % 60'd10;                                                //出生月十位
  24. assign i[12] = (id / 60'd1000000) % 60'd10;                                                //出生月个位
  25. assign i[13] = (id / 60'd100000) % 60'd10;                                                //出生日十位
  26. assign i[14] = (id / 60'd10000) % 60'd10;                                                        //出生日个位
  27. assign i[15] = (id / 60'd1000) % 60'd10;                                                        //派出所代码十位
  28. assign i[16] = (id / 60'd100) % 60'd10;                                                        //派出所代码个位
  29. assign i[17] = (id / 60'd10) % 60'd10;                                                                //奇数:男 偶数:女
  30. assign i[18] = x ? 60'd10 : (id % 60'd10);                                                //校验位

  31. genvar k;
  32. generate
  33. for(k=1;k<=18;k=k+1) begin:gen
  34.         assign j[k] = i[k][3:0];
  35. end
  36. endgenerate
  37. wire [13:0] y = j[7]*14'd1000 + j[8]*14'd100 + j[9]*14'd10 + j[10];        //年范围:0~9999
  38. wire [6:0] m = j[11]*7'd10 + j[12];                //月范围:0~99 有效范围:1~12
  39. wire [6:0] d = j[13]*7'd10 + j[14];                //日范围:0~99 有效范围:1~31
  40. function [4:0] ym2d;                        //已知年月 获取该月有多少天
  41.                 input [13:0] y;
  42.                 input [3:0] m;
  43.                 begin
  44.                         case(m)
  45.                                 1:ym2d = 5'd31;
  46.                                 2:ym2d = `leap_year(y) ? 5'd29 : 5'd28;
  47.                                 3:ym2d = 5'd31;
  48.                                 4:ym2d = 5'd30;
  49.                                 5:ym2d = 5'd31;
  50.                                 6:ym2d = 5'd30;
  51.                                 7:ym2d = 5'd31;
  52.                                 8:ym2d = 5'd31;
  53.                                 9:ym2d = 5'd30;
  54.                                 10:ym2d = 5'd31;
  55.                                 11:ym2d = 5'd30;
  56.                                 12:ym2d = 5'd31;
  57.                                 default:ym2d = 5'd0;
  58.                         endcase
  59.                 end
  60. endfunction

  61. assign gender = j[17][0];

  62. assign year = ok ? y : 14'd0;
  63. assign month = ok ? m[3:0] : 4'd0;
  64. assign day = ok ? d[4:0] : 5'd0;
  65. wire [9:0] l =                         //校验码
  66.         (j[1]*10'd7)+
  67.         (j[2]*10'd9)+
  68.         (j[3]*10'd10)+
  69.         (j[4]*10'd5)+
  70.         (j[5]*10'd8)+
  71.         (j[6]*10'd4)+
  72.         (j[7]*10'd2)+
  73.         (j[8]*10'd1)+
  74.         (j[9]*10'd6)+
  75.         (j[10]*10'd3)+
  76.         (j[11]*10'd7)+
  77.         (j[12]*10'd9)+
  78.         (j[13]*10'd10)+
  79.         (j[14]*10'd5)+
  80.         (j[15]*10'd8)+
  81.         (j[16]*10'd4)+
  82.         (j[17]*10'd2);
  83. wire [3:0] n [10:0];

  84. assign n[0] = 4'd1;
  85. assign n[1] = 4'd0;
  86. assign n[2] = 4'd10;                //X
  87. assign n[3] = 4'd9;
  88. assign n[4] = 4'd8;
  89. assign n[5] = 4'd7;
  90. assign n[6] = 4'd6;
  91. assign n[7] = 4'd5;
  92. assign n[8] = 4'd4;
  93. assign n[9] = 4'd3;
  94. assign n[10] = 4'd2;

  95. always @(*) begin
  96.         ok = 1'd1;
  97.         if(y > 9999) begin        //年大于9999
  98.                 ok = 1'd0;
  99.         end else if(m < 1 || m > 12) begin        //月小于1或大于12
  100.                 ok = 1'd0;
  101.         end else if(d < 1 || d > ym2d(y,m[3:0]) || d > 31) begin                //日小于1或大于月天数或大于31
  102.                 ok = 1'd0;
  103.         end else if(n[l%11] != j[18]) begin                //校验位错误
  104.                 ok = 1'd0;
  105.         end
  106. end

  107. endmodule

  108. module main(
  109.         input clk,
  110.         output ok,
  111.         output gender,
  112.         output [13:0] year,
  113.         output [3:0] month,
  114.         output [4:0] day
  115. );
  116. is_idcard U1(
  117.         .id(60'd524288204810248192),
  118.         .x(1'd0),
  119.         .ok(ok),
  120.         .gender(gender),
  121.         .year(year),
  122.         .month(month),
  123.         .day(day)
  124. );
  125. endmodule
复制代码

相关帖子

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 加入我们

本版积分规则