当前位置: 首页 > article >正文

Verilog实现的莫尔斯电码发生器

莫尔斯或者摩尔斯电码(Morse Code),发明于1837年(另有一说是1836年),通过不同的排列顺序来表达不同的英文字母、数字和标点符号,在这里作一简单处理,仅产生点(Dit)和划(Dah),时长在0.25秒之内为点,超过为划,用按键控制时间模拟实现,5个点或划表示一个数字(0-9),通过数码管显示按键发声频率1350Hz。

//莫尔斯代码发生器
module morse(rst_n,clk,key,seg,dg,beep);
input clk,rst_n,key;//clk50M,rst_n低电平有效,key按下为0
output reg beep; //蜂鸣器
output reg[7:0]  seg;//段码
output reg[5:0]  dg;//位码
reg [10:0] ct; //1350Hz分频计数
reg [3:0] cnt,kcnt; //50Hz分频计数,按键计数
reg clk50hz,clk1k; //分频得到的时钟
reg [3:0] num,number; //要显示的数,点划编码数
reg [2:0] i=0;  //要显示的点划序号
reg [9:0] dh=10'b0000000000;  //点划输入,点为10,划为11,不按为00
wire clk5;  //PLL输出的5.4M
reg [2:0] state; //按键状态
localparam S0 = 0; //初始状态
localparam S1 = 1;  //按键按下0-0.25S
localparam S2 = 2; //按键在0.25S内释放
localparam S3 = 3; //按键按下超过0.25S
localparam S4 = 4; //按键在0.25S后释放

clk5m4 PLLA(   //PLL产生5.4M时钟
  .refclk(clk) ,
  .reset(~rst_n),
  .clk0_out(),
  .clk1_out(clk5) 
);

always @ (posedge clk5 or negedge rst_n)  //分频成约1350Hz
 if (!rst_n) 
     ct<=0;
   else if (ct>=2000-1)   //5.4M->1350Hz    
       begin clk1k<=~clk1k; ct<=0; end 
      else ct<=ct+1;

always @ (posedge clk1k or negedge rst_n)  //分频成约52Hz
 if (!rst_n) 
     cnt<=0;
   else if (cnt>=13-1)   //1k->50      
       begin clk50hz<=~clk50hz; cnt<=0; end 
    else cnt<=cnt+1;
    
always @ (posedge clk50hz or negedge rst_n)  //按键检测并计数
  if (!rst_n) begin  state<=S0; kcnt<=0; dh<=10'b0000000000; i<=0; end  //初始状态S0
    else case(state)
      S0:begin if (key) begin  state<=S0; kcnt<=0; end
             else begin i<=(i>=5)?1:i+1; state<=S1; end
         end
      S1:begin 
          if (key) begin  state<=S2; kcnt<=0; end  //短按(0.25S内)按键,S1状态
          else if (kcnt<=13) begin  state<=S1; kcnt<=kcnt+1; end
          else state<=S3; 
        end
      S2: if (key) begin {dh[11-2*i],dh[10-2*i]}<=2'b10; state<=S2; kcnt<=0; end //短按并释放,S2状态
              else begin 
                   state<=S1;
                   if (i>=5)
                    begin 
                     i<=1; dh<=10'b0000000000;
                    end
                   else
                     i<=i+1;
                  end 
      S3:state<=(!key)?S3:S4;                      //长按(>0.25S),S3状态
      S4:
      if (key) begin {dh[11-2*i],dh[10-2*i]}<=2'b11; state<=S4; kcnt<=0; end //长按释放,S4状态
              else  begin 
                   state<=S1;
                   if (i>=5)
                    begin 
                     i<=1; dh<=10'b0000000000;
                    end
                   else
                     i<=i+1;
                  end  
       default:;
   endcase
   
always@(state)   //发声
  case(state)
    S1,S3:beep=clk1k;
    default:beep=0;
  endcase

always@(posedge clk1k or  negedge rst_n) //数码管扫描显示(右5位为点划),最左为点划编码数字
  if (!rst_n) 
    dg<=6'b111111; 
    else case (dg)
       6'b111110:begin num=dh[3:2]+10;  dg<=6'b111101;end
       6'b111101:begin num=dh[5:4]+10;  dg<=6'b111011;end
       6'b111011:begin num=dh[7:6]+10;  dg<=6'b110111;end
       6'b110111:begin num=dh[9:8]+10;  dg<=6'b101111;end
       6'b101111:begin num=number;      dg<=6'b011111;end
       default:begin num=dh[1:0]+10;dg<=6'b111110;end
    endcase 
  
always@(dh)
  case({dh[9:8],dh[7:6],dh[5:4],dh[3:2],dh[1:0]})
   10'b1011111111:number<=1;
   10'b1010111111:number<=2;
   10'b1010101111:number<=3;
   10'b1010101011:number<=4;
   10'b1010101010:number<=5;
   10'b1110101010:number<=6;
   10'b1111101010:number<=7;
   10'b1111111010:number<=8;
   10'b1111111110:number<=9;
   10'b1111111111:number<=0;
   default:if (dh[1:0]==2'b00) number<=14;  //等待输入标示
            else number<=11;  //出错标示
  endcase
 
always @(num)   //数码管译码,共阳极,0点亮,段码顺序:DP,G-A
  case(num)
        0:seg<=8'b11000000;
        1:seg<=8'b11111001;
      	2:seg<=8'b10100100;
		3:seg<=8'b10110000;
    	4:seg<=8'b10011001;
		5:seg<=8'b10010010;
		6:seg<=8'b10000010;
		7:seg<=8'b11111000;
		8:seg<=8'b10000000;
        9:seg<=8'b10010000;
        11:seg<=8'b10000110;//出错标示
        12:seg<=8'b01111111; //点标示
        13:seg<=8'b11110111;//划标示
        14:seg<=8'b10110110; //等待输入标示
		default:seg<=8'b11111111; //全暗不亮
   endcase
    
endmodule

运行时,将首先在左侧数码管显示“三”,表示等待输入,随着按键通过控制时间长短输入点和划,并同步显示在数码管上,键入5次后,译码输出数字,若出错,将显示出错符号“E”。


http://www.kler.cn/a/374699.html

相关文章:

  • centos7之LVS-DR模式传统部署
  • 使用Python进行数据分析入门
  • Java复习27(PTA)
  • 树叶分类竞赛(Baseline)以及kaggle的GPU使用
  • Java基础(8)异常
  • 神经网络进行波士顿房价预测
  • 群控系统服务端开发模式-应用开发-上传配置功能开发
  • 计算机毕业设计 | springboot+vue电影院会员管理系统 影院后台管理(附源码)
  • Python 实现深度学习模型预测控制--预测模型构建
  • ISO 26262与ISO 21434:汽车安全领域的双重保障与交汇探索
  • 开启TikTok直播的全攻略:从网络条件到设备准备
  • API接口开放与安全管控 - 原理与实践
  • 城市交通场景分割系统:Web前端可视化
  • 汽车车辆控制单元SRAM存储解决方案
  • elasticsearch 8.x 插件安装(三)之拼音插件
  • 两个有序链表序列的交集
  • mosh-react-course
  • 计算机毕业设计django+大模型租房推荐系统 租房可视化 租房大屏可视化 租房爬虫 spark 58同城租房爬虫 房源推荐系统
  • 在本地电脑部署属于你的AI大模型
  • 手敲Webpack 5:React + TypeScript项目脚手架搭建实践
  • Java面试题十四
  • C++中的依赖注入
  • 记录一次企业外部通过ssh 连接数据库的事DBeaver
  • Apache Solr 身份认证绕过导致任意文件读取漏洞复现(CVE-2024-45216)
  • Apache paimon表管理
  • 稀土抗菌剂:食品包装中的安全保障