设为首页收藏本站淘宝杂货铺

从F到0 - From F to 0

 找回密码
 注册已关闭
搜索
查看: 247|回复: 1
收起左侧

Quartus Verilog HDL/FPGA 状态机实现驱动 TM1637 带冒号的4位共阳动态扫描数码管模块

[复制链接]
发表于 2023-3-30 08:23:20 | 显示全部楼层 |阅读模式
main.png
  1. `define IIC_START        3'd1
  2. `define IIC_ACK        3'd2
  3. `define IIC_STOP        3'd3
  4. `define IIC_WRITE 3'd4
  5. module tm1637(                        //带冒号的4位共阴动态扫描数码管模块
  6.         input clk,                        //50Mhz 时钟输入 (clk与CLK大小写敏感)
  7.         input colon,                //冒号 1:点亮 0:熄灭
  8.         input [6:0] A,                //[7位宽] 千位段码 (七段段码,没有小数点)
  9.         input [6:0] B,                //[7位宽] 百位段码
  10.         input [6:0] C,                //[7位宽] 十位段码
  11.         input [6:0] D,                //[7位宽] 个位段码
  12.         input [2:0] LM,        //[3位宽] 亮度:0~7 (0最暗,7最亮)
  13.         output OK,                        //发送成功置1 失败清0,表示未检测到TM1637
  14.         inout DIO,                        //TM1637双向数据
  15.         output reg CLK                //TM1637时钟
  16. );
  17. reg IO = 1'b1;                //DIO 1:输入 0:输出
  18. reg OUT = 1'b1;                //DIO 输出电平

  19. reg [2:0] order = 3'd0;                //指令
  20. reg [1:0] step = 2'd0;                //步骤
  21. reg [4:0] pc = 5'd0;                        //程序指针
  22. reg [15:0] acktime = 16'd0;        //ACK应答超时计数器
  23. reg [7:0] delay = 8'd0;                //延时时钟数
  24. reg [7:0] dat = 8'd0;                //IIC待发数据:0~255
  25. reg [2:0] bpc = 3'd0;                //IIC字节位指针:0~7
  26. reg over = 1'b0;                                //指令结束标志

  27. reg [6:0] ack = 7'b0;                //7个ACK应答信号
  28. assign OK = &ack;                                //ACK信号全部到位

  29. wire [31:0] new = {colon,A,B,C,D,LM};        //32位宽导线 {冒号亮灭,7位宽A,7位宽B,7位宽C,7位宽D,亮度}
  30. reg [31:0] old = 29'd0;                                                //32位宽寄存器 (用于检测线网 new 的值是否发生改变)
  31. reg run = 1'b0;                                //运行标志 置1开始发送,完成后清0

  32. assign DIO = IO ? 1'bz : OUT;
  33. reg clkB = 1'b0;
  34. always @(posedge clk) begin                //50Mhz分频25Mhz
  35.         clkB <= !clkB;
  36. end
  37. always @(posedge clkB) begin
  38.         old <= new;
  39.         if(old != new) run <= 1'b1;                //显示的数据发生改变,开始发送!
  40.         if(run) begin
  41.                 if(|delay) begin                //有延时
  42.                         delay <= delay - 8'd1;
  43.                 end else begin
  44.                         over = 1'b0;
  45.                         case(order)                                                //有指令
  46.                                 `IIC_START:case(step)                //IIC开始
  47.                                         2'd0:begin                        //CLK与DIO拉高
  48.                                                 {CLK,IO,OUT} <= 3'b101;       
  49.                                                 step <= 2'd1;
  50.                                                 delay <= 8'd1000;                //延时100个时钟即4us
  51.                                         end
  52.                                         2'd1:begin
  53.                                                 OUT <= 1'b0;                //DIO拉低
  54.                                                 order <= 3'd0;                //指令执行完毕
  55.                                                 step <= 2'd0;
  56.                                                 over = 1'b1;
  57.                                         end
  58.                                 endcase
  59.                                 `IIC_ACK:case(step)                        //IIC应答
  60.                                         2'd0:begin
  61.                                                 {CLK,IO} <= 2'b01;                //CLK拉低,DIO输入模式
  62.                                                 delay <= 8'd250;        //延时10us
  63.                                                 step <= 2'd1;
  64.                                                 acktime <= 16'd0;
  65.                                         end
  66.                                         2'd1:begin                                //等待应答
  67.                                                 if(DIO) begin                //DIO高电平等待
  68.                                                         acktime = acktime + 16'd1;
  69.                                                         if(&acktime) begin                //超时
  70.                                                                 ack <= (ack << 1'b1);
  71.                                                                 step <= 2'd2;
  72.                                                         end
  73.                                                 end else begin
  74.                                                         ack <= (ack << 1'b1) | 1'b1;
  75.                                                         step <= 2'd2;
  76.                                                 end
  77.                                         end
  78.                                         2'd2:begin                //CLK拉高并延时2us
  79.                                                 CLK <= 1'b1;
  80.                                                 delay <= 8'd100;
  81.                                                 step <= 2'd3;
  82.                                         end
  83.                                         2'd3:begin
  84.                                                 CLK <= 1'b0;                //CLK拉低
  85.                                                 over = 1'b1;
  86.                                                 order <= 3'd0;                //指令执行完毕
  87.                                                 step <= 2'd0;
  88.                                         end
  89.                                 endcase
  90.                                 `IIC_STOP:case(step)                //IIC停止
  91.                                         2'd0:begin                        //CLK拉低并延时2us
  92.                                                 CLK <= 1'b0;
  93.                                                 delay <= 8'd100;
  94.                                                 step <= 2'd1;
  95.                                         end
  96.                                         2'd1:begin                        //DIO拉低并延时2us
  97.                                                 {IO,OUT} <= 2'b00;
  98.                                                 delay <= 8'd100;
  99.                                                 step <= 2'd2;
  100.                                         end
  101.                                         2'd2:begin                        //CLK拉高并延时2us
  102.                                                 CLK <= 1'b1;
  103.                                                 delay <= 8'd50;
  104.                                                 step <= 2'd3;                               
  105.                                         end
  106.                                         2'd3:begin                        //DIO拉高并延时2us
  107.                                                 {IO,OUT} <= 2'b01;
  108.                                                 delay <= 8'd100;
  109.                                                 step <= 2'd0;
  110.                                                 order <= 3'd0;                //指令执行完毕
  111.                                                 over = 1'b1;       
  112.                                         end
  113.                                 endcase
  114.                                 `IIC_WRITE:case(step)        //写数据函数
  115.                                         2'd0:begin
  116.                                                 bpc <= 3'd0;
  117.                                                 step <= 2'd1;
  118.                                         end
  119.                                         2'd1:begin
  120.                                                 {CLK,IO,OUT} <= {1'b0,dat[bpc],1'b0};
  121.                                                 delay <= 8'd150;                //延时6us
  122.                                                 step <= 2'd2;
  123.                                         end
  124.                                         2'd2:begin                        //CLK拉高并延时6us
  125.                                                 CLK <= 1'b1;
  126.                                                 delay <= 8'd150;
  127.                                                 step <= (&bpc) ? 2'd3 : 2'd1;
  128.                                                 bpc <= bpc + 3'd1;
  129.                                         end
  130.                                         2'd3:begin
  131.                                                 bpc <= 3'd0;
  132.                                                 step <= 2'd0;
  133.                                                 order <= 3'd0;
  134.                                                 over = 1'b1;
  135.                                         end
  136.                                 endcase
  137.                                 default:order <= 3'd0;                //没有指令
  138.                         endcase
  139.                         if(!order) begin
  140.                                 case(pc)
  141.                                         5'd0:order <= `IIC_START;
  142.                                         5'd1:{order,dat} <= {`IIC_WRITE,8'h40};                //写数据+自动地址加1+普通模式
  143.                                         5'd2:order <= `IIC_ACK;
  144.                                         5'd3:order <= `IIC_STOP;
  145.                                         5'd4:order <= `IIC_START;
  146.                                         5'd5:{order,dat} <= {`IIC_WRITE,8'hC0};                //设置显示首地址即第一个LED
  147.                                         5'd6:order <= `IIC_ACK;
  148.                                         5'd7:{order,dat} <= {`IIC_WRITE,1'b0,A};
  149.                                         5'd8:order <= `IIC_ACK;
  150.                                         5'd9:{order,dat} <= {`IIC_WRITE,colon,B};
  151.                                         5'd10:order <= `IIC_ACK;
  152.                                         5'd11:{order,dat} <= {`IIC_WRITE,1'b0,C};
  153.                                         5'd12:order <= `IIC_ACK;
  154.                                         5'd13:{order,dat} <= {`IIC_WRITE,1'b0,D};
  155.                                         5'd14:order <= `IIC_ACK;
  156.                                         5'd15:order <= `IIC_STOP;
  157.                                         5'd16:order <= `IIC_START;
  158.                                         5'd17:{order,dat} <= {`IIC_WRITE,5'h11,LM};                //开显示
  159.                                         5'd18:order <= `IIC_ACK;
  160.                                         5'd19:order <= `IIC_STOP;
  161.                                         default:order <= 3'd0;
  162.                                 endcase
  163.                         end
  164.                         if(over) begin
  165.                                 pc = pc + 5'd1;
  166.                                 if(pc > 19) begin
  167.                                         pc = 5'd0;
  168.                                         run <= 1'b0;
  169.                                 end
  170.                         end
  171.                 end
  172.         end else begin                        //run为0
  173.                 {CLK,IO,OUT} <= 3'b111;       
  174.         end
  175. end
  176. endmodule

  177. module main(
  178.         input clk,                //50Mhz Pin17
  179.         inout DIO,                //TM1637 Pin40
  180.         output CLK,                //TM1637 Pin42
  181.         output led                //LED Pin3(低电平点亮) 初始化正常点亮,否则熄灭
  182. );

  183. function [6:0] display;                        //16进制数码管段码查询
  184.         input [3:0] hex;
  185.         begin
  186.         case(hex)
  187.                 4'h0:display = 7'h3F;
  188.                 4'h1:display = 7'h06;
  189.                 4'h2:display = 7'h5B;
  190.                 4'h3:display = 7'h4F;
  191.                 4'h4:display = 7'h66;
  192.                 4'h5:display = 7'h6D;
  193.                 4'h6:display = 7'h7D;
  194.                 4'h7:display = 7'h07;
  195.                 4'h8:display = 7'h7F;
  196.                 4'h9:display = 7'h6F;
  197.                 4'hA:display = 7'h77;
  198.                 4'hB:display = 7'h7C;
  199.                 4'hC:display = 7'h39;
  200.                 4'hD:display = 7'h5E;
  201.                 4'hE:display = 7'h79;
  202.                 4'hF:display = 7'h71;       
  203.         endcase
  204.         end
  205. endfunction
  206. reg colon;
  207. integer i;
  208. always @(posedge clk) begin
  209.         i = i + 1;
  210.         if(i >= 25000000) begin
  211.                 i = 0;
  212.                 colon <= !colon;                //冒号1HZ闪烁
  213.         end
  214. end
  215. reg [13:0] sec = 14'd0;                //秒:0~9999
  216. always @(negedge colon) begin
  217.         sec = sec + 14'd1;
  218.         if(sec > 9999) begin
  219.                 sec = 14'd0;
  220.         end
  221. end

  222. wire OK;
  223. assign led = !OK;

  224. tm1637 tm1637(
  225.         .clk(clk),
  226.         .colon(colon),
  227.         .A(display((sec/1000)%10)),
  228.         .B(display((sec/100)%10)),
  229.         .C(display((sec/10)%10)),
  230.         .D(display(sec%10)),
  231.         .LM(sec&7),
  232.         .OK(OK),
  233.         .DIO(DIO),
  234.         .CLK(CLK)
  235. );
  236. endmodule
复制代码

相关帖子

您需要登录后才可以回帖 登录 | 注册已关闭

本版积分规则

QQ|手机版|Archiver|从F到0 ( 蒙ICP备17002595号-1 )
蒙公网安备15010402000325号

腾讯云安全认证

GMT+8, 2024-4-26 04:13 , Processed in 1.459083 second(s), 23 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表