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"。

相关推荐
hahaha60168 小时前
3NRD降噪算法FPGA实现8并行度设计
fpga开发
松小白song8 小时前
一次“载电流显示为 0“的排查经历:负值钳位引发的踩坑
fpga开发
yingheceping12 小时前
复旦微FPGA开发板厂商TOP5甄选榜:2026选型参考
fpga开发·fpga
NamoAmitabha12814 小时前
PL 端的 GPIO IP(AXI GPIO)---PS控制----deepseek
fpga开发·zynq--ps
hahaha601617 小时前
3D降噪算法YUV降噪FPGA实现
fpga开发
Hello-FPGA2 天前
基于RFSOC FPGA ZCU216 的CoaXPress 采集demo
fpga开发
9527华安2 天前
FPGA基于ADV7182解码PAL视频,Video Processing Subsystem去隔行,提供6套工程源码和技术支持
fpga开发·音视频·pal·adv7182
hahaha60162 天前
数字图像时域滤波或者3D降噪算法FPGA实现
算法·计算机视觉·fpga开发
GateWorld2 天前
Xilinx 7系列FPGA时钟网络详解
fpga开发·时钟网络·xilinx 7系列
szxinmai主板定制专家2 天前
X86 工控机 vs RK3588 异构主控:AMR 控制器 BOM、散热、长期运维对比
运维·stm32·单片机·嵌入式硬件·fpga开发·am62x