以下是视频与代码
http://v.youku.com/v_show/id_XNDY0OTI1NjE2.html
module Key_led(key,led,clk,rst_n);
input[7:0] key;
output[7:0] led;
input clk;
input rst_n;
reg[19:0] cnt;
reg[7:0] led_r;
reg[7:0] key_t;
reg cnt_sta;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
cnt = 20'b0;
else if(cnt_sta)
cnt = cnt + 1'b1;
end
wire delay_over = cnt == 20'hfffff;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
key_t = 8'b11111111;
cnt_sta = 0;
end
else if((key ^ 8'b11111111) != 8'b0)
begin
key_t = key;
cnt_sta = 1;
if(delay_over == 1'b1)
cnt_sta = 0;
end
else if(delay_over == 1'b1)
begin
cnt_sta = 0;
end
end
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
led_r = 8'b0;
else if(delay_over == 1'b1)
begin
if(key == key_t)
led_r = key_t;
end
end
assign led = led_r;
endmodule
http://v.youku.com/v_show/id_XNDY1MTY2NjMy.html
有一位数码管坏了,检查电路板,发现焊接正常,能演示功能就好!
module Seg7_static(clk,rst_n,dig_t,seg_t);
input clk;
input rst_n;
output[7:0] dig_t;
output[7:0] seg_t;
reg[23:0] cnt;
reg next;
reg[3:0] data;
reg[7:0] dig_t;
reg[7:0] seg_t;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
cnt = 24'b0;
dig_t = 8'b11111111;
end
else
begin
cnt = cnt + 1'b1;
dig_t = 8'b0;
end
end
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
next = 1'b0;
else if(cnt == 24'hffffff)
next = 1'b1;
else
next = 1'b0;
end
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
data = 4'h0;
else if(next)
data = data + 1'b1;
end
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
seg_t = 8'h00;
else
case(data)
4'h0:seg_t = 8'hc0;
4'h1:seg_t = 8'hf9;
4'h2:seg_t = 8'ha4;
4'h3:seg_t = 8'hb0;
4'h4:seg_t = 8'h99;
4'h5:seg_t = 8'h92;
4'h6:seg_t = 8'h82;
4'h7:seg_t = 8'hf8;
4'h8:seg_t = 8'h80;
4'h9:seg_t = 8'h90;
4'ha:seg_t = 8'h88;
4'hb:seg_t = 8'h83;
4'hc:seg_t = 8'hc6;
4'hd:seg_t = 8'ha1;
4'he:seg_t = 8'h86;
4'hf:seg_t = 8'h8e;
endcase
end
endmodule
5、数码管动态显示、蜂鸣器
蜂鸣器代码太少,于是加到数码管动态显示实验了,一起演示,有个数位貌似坏了,本来想显示数字0-7的。大约每隔1.3ms对8位数码管轮流使能,10.5ms一个周期。蜂鸣器大约763Hz,占空比5/16。
http://v.youku.com/v_show/id_XNDY1OTExMjY0.html
module Seg7_dynamic(clk,rst_n,dig,seg,beep);
input clk;
input rst_n;
output[7:0] dig;
output[7:0] seg;
output beep;
reg[15:0] cnt;
reg[2:0] count;
reg[3:0] data;
reg[7:0] dig_t;
reg[7:0] seg_t;
reg beep;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
cnt = 16'b0;
else
cnt = cnt + 1'b1;
end
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
count = 3'b000;
else if(cnt == 16'hffff)
begin
count = count + 1;
end
end
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
data = 4'h0;
dig_t = 8'b11111111;
end
else
case(count)
3'b000:
begin
data = 0;
dig_t = 8'b11111110;
end
3'b001:
begin
data = 1;
dig_t = 8'b11111101;
end
3'b010:
begin
data = 2;
dig_t = 8'b11111011;
end
3'b011:
begin
data = 3;
dig_t = 8'b11110111;
end
3'b100:
begin
data = 4;
dig_t = 8'b11101111;
end
3'b101:
begin
data = 5;
dig_t = 8'b11011111;
end
3'b110:
begin
data = 6;
dig_t = 8'b10111111;
end
3'b111:
begin
data = 7;
dig_t = 8'b01111111;
end
endcase
end
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
seg_t = 8'h00;
else
case(data)
4'h0:seg_t = 8'hc0;
4'h1:seg_t = 8'hf9;
4'h2:seg_t = 8'ha4;
4'h3:seg_t = 8'hb0;
4'h4:seg_t = 8'h99;
4'h5:seg_t = 8'h92;
4'h6:seg_t = 8'h82;
4'h7:seg_t = 8'hf8;
4'h8:seg_t = 8'h80;
4'h9:seg_t = 8'h90;
4'ha:seg_t = 8'h88;
4'hb:seg_t = 8'h83;
4'hc:seg_t = 8'hc6;
4'hd:seg_t = 8'ha1;
4'he:seg_t = 8'h86;
4'hf:seg_t = 8'h8e;
endcase
end
assign dig = dig_t;
assign seg = seg_t;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
beep = 1'b1;
else if(cnt <= 16'hfff && cnt >= 16'h5fff)
beep = 1'b0;
else
beep = 1'b1;
end
endmodule
6、电子琴
第8个按键为功能键,切换中高音,按下键时,LED和数码管同时显示相应音符
http://v.youku.com/v_show/id_XNDY2MzgzMDY4.html
module Elec_organ(clk,rst_n,beep,key,led,seg,dig);
input clk;
input rst_n;
input[7:0] key;
output beep;
output[7:0] led;
output[7:0] seg;
output[7:0] dig;
reg[19:0] cnt,cnt_point;
reg beep;
reg[7:0] dig_t;
reg[7:0] seg_t;
reg[3:0] data;
reg[7:0] key_t;
reg key_flag;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
beep = 1'b1;
dig_t = 8'hff;
end
else if(cnt == cnt_point)
begin
cnt = 20'b0;
if(key_flag)
beep = ~beep;
else
beep = 1'b1;
end
else
begin
cnt = cnt + 1'b1;
dig_t = 8'b0;
end
end
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
key_t = 8'hff;
key_flag = 1'b0;
end
else if(key[6:0] != 7'h7f)
begin
key_t = key;
key_flag = 1'b1;
end
else
key_flag =1'b0;
end
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
cnt_point = 20'hfffff;
data = 4'h0;
end
else
case(key_t)
8'b11111110:
begin
cnt_point = 20'd47774;
data = 4'h1;
end
8'b11111101:
begin
cnt_point = 20'd42568;
data = 4'h2;
end
8'b11111011:
begin
cnt_point = 20'd37919;
data = 4'h3;
end
8'b11110111:
begin
cnt_point = 20'd35791;
data = 4'h4;
end
8'b11101111:
begin
cnt_point = 20'd31888;
data = 4'h5;
end
8'b11011111:
begin
cnt_point = 20'd28409;
data = 4'h6;
end
8'b10111111:
begin
cnt_point = 20'd25309;
data = 4'h7;
end
8'b01111110:
begin
cnt_point = 20'd23912;
data = 4'h1;
end
8'b01111101:
begin
cnt_point = 20'd21282;
data = 4'h2;
end
8'b01111011:
begin
cnt_point = 20'd18961;
data = 4'h3;
end
8'b01110111:
begin
cnt_point = 20'd17897;
data = 4'h4;
end
8'b01101111:
begin
cnt_point = 20'd15944;
data = 4'h5;
end
8'b01011111:
begin
cnt_point = 20'd14205;
data = 4'h6;
end
8'b00111111:
begin
cnt_point = 20'd12655;
data = 4'h7;
end
default:
begin
cnt_point = 20'hfffff;
data = 4'h0;
end
endcase
end
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
seg_t = 8'h00;
else
case(data)
4'h0:seg_t = 8'hc0;
4'h1:seg_t = 8'hf9;
4'h2:seg_t = 8'ha4;
4'h3:seg_t = 8'hb0;
4'h4:seg_t = 8'h99;
4'h5:seg_t = 8'h92;
4'h6:seg_t = 8'h82;
4'h7:seg_t = 8'hf8;
default:seg_t = 8'h86;
endcase
end
assign seg = seg_t;
assign dig = dig_t;
assign led = key_t;
endmodule
7、自动演奏乐曲
本来选的是一首泰坦尼克号的简谱,但是实际效果听不出来,就是一段普通的曲子,后来认真听了原曲,还是人声段有Feeing,曲子感觉比较普通了,简谱可能就打了折扣了!也很有可能是代码的乐曲频率没调好,就不细调了,权当演示功能。
http://v.youku.com/v_show/id_XNDY2NTM2MjY0.html
// 泰坦尼克号主题曲
// 50MHz,每隔大约168ms一个音
//音高与频率的对应关系
//----------------------------------------------------------------------
//| | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
//|低音 |261.6Hz |293.7Hz |329.6Hz |349.2Hz | 392Hz | 440Hz |493.9Hz |
//|中音 |523.3Hz |587.3Hz |659.3Hz |698.5Hz | 784Hz | 880Hz |987.8Hz |
//|高音 |1045.5Hz|1174.7Hz|1318.5Hz|1396.9Hz| 1568Hz | 1760Hz |1975.5Hz|
//----------------------------------------------------------------------
module Beepsong(clk,rst_n,beep);
input clk;
input rst_n;
output beep;
reg[15:0] cnt;
reg[22:0] count;
reg beep;
reg[7:0] state;
reg[15:0] cnt_point;
parameter L_3 = 16'd75850, //低音3
L_5 = 16'd63776, //低音5
L_6 = 16'd56818, //低音6
L_7 = 16'd50618, //低音7
M_1 = 16'd47774, //中音1
M_2 = 16'd42568, //中音2
M_3 = 16'd37919, //中音3
M_4 = 16'd35791, //中音4
M_5 = 16'd31888, //中音5
M_6 = 16'd28409, //中音6
H_1 = 16'd23912; //高音1
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
cnt = 16'b0;
beep = 1'b1;
end
else if(cnt == cnt_point)
begin
cnt = 16'b0;
beep = ~beep;
end
else
cnt = cnt + 1'b1;
end
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
count = 23'b0;
else
count = count + 1'b1;
end
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
state = 8'd0;
else if(count == 23'h7fffff)
begin
state = state + 1'b1;
if(state == 8'd79)
state = 8'd0;
end
end
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
cnt_point = 16'hffff;
else
case(state)
8'd0,8'd1,8'd2,8'd3:cnt_point = M_1;
8'd4,8'd7,8'd16:cnt_point = L_7;
8'd5,8'd6,8'd8:cnt_point = M_1;
8'd9,8'd11:cnt_point = M_2;
8'd10:cnt_point = M_3;
8'd12,8'd13,8'd14,8'd15:cnt_point = M_1;
8'd17,8'd18:cnt_point = M_1;
8'd19:cnt_point = L_5;
8'd20,8'd21,8'd22:cnt_point = M_1;
8'd23,8'd26:cnt_point = L_7;
8'd24,8'd25,8'd27:cnt_point = M_1;
8'd28,8'd30:cnt_point = M_2;
8'd29:cnt_point = M_3;
8'd31,8'd32,8'd33,8'd34:cnt_point = M_1;
8'd36,8'd37:cnt_point = M_1;
8'd38:cnt_point = L_5;
8'd39:cnt_point = M_1;
8'd40:cnt_point = M_2;
8'd41:cnt_point = L_5;
8'd42:cnt_point = M_5;
8'd43:cnt_point = M_4;
8'd44:cnt_point = M_3;
8'd45:cnt_point = M_2;//
8'd46,8'd48:cnt_point = M_3;
8'd47:cnt_point = M_4;
8'd49:cnt_point = M_2;
8'd50:cnt_point = M_1;
8'd51,8'd52:cnt_point = L_7;
8'd53:cnt_point = L_6;
8'd54:cnt_point = L_5;//
8'd55:cnt_point = M_1;
8'd56:cnt_point = M_2;
8'd57:cnt_point = L_5;
8'd58:cnt_point = M_5;
8'd59:cnt_point = M_4;
8'd60:cnt_point = M_3;
8'd61:cnt_point = M_2;//
8'd62,8'd64:cnt_point = M_3;
8'd63:cnt_point = M_4;
8'd65:cnt_point = M_2;
8'd66,8'd68:cnt_point = M_1;
8'd67:cnt_point = L_7;//
8'd69,8'd70:cnt_point = L_7;
8'd71:cnt_point = M_1;
8'd72,8'd76:cnt_point = M_2;
8'd73,8'd75:cnt_point = M_3;
8'd74:cnt_point = M_4;
8'd77,8'd78:cnt_point = M_1;
default:cnt_point = 16'hffff;
endcase
end
endmodule
8、LCD1602显示
静态显示,逐步显示,滚动显示三种效果
以下代码说明:
1.初始化一定要特别注意,不成功就无法正常显示了,模块输出最奥都设为高阻
2.计数器大小可以调,决定了执行状态机的频率,也就影响了显示字符的频率
3.1602寄存器配置,不能马虎,建议改动多试试效果,修改一个寄存器即可滚动显示
4.贴出代码为滚动效果的,稍作修改就可以显示其他效果
PS:1.发给EEPW的视频还没搜索到,暂时展示优酷链接的视频,稍后补上
2.最近忙于其他事,几天没有更新,同时抽空做1602实验时受阻,遇到问题,耽搁了进程,今天终于找到原因,独立搞定,因此请没有做过1602实验的朋友们先认真阅读1602pdf文档
静态显示效果(严格的说应该是视觉上静态)
逐步显示效果(一个字符一个字符的显示)
http://v.youku.com/v_show/id_XNDY5NjY2MTIw.html
滚动显示效果(整体滚动)
http://v.youku.com/v_show/id_XNDY5NjY2NzYw.html
module LCD1602(clk,rst_n,RS,RW,EN,data);
input clk;
input rst_n;
output RS;
output RW;
output EN;
output[7:0] data;
reg[24:0] cnt;
reg[7:0] data;
reg lcd_rs;
reg lcd_rw;
reg lcd_en;
reg[3:0] state;
reg[5:0] address;
reg trig;
parameter IDLE = 4'b0000; //空闲
parameter CLEAR = 4'b0001; //清屏
parameter RETURNCURSOR = 4'b0010; //归home位
parameter SETMODE = 4'b0011;
//输入方式设置,读写数据后ram地址增/减1;画面动/不动
parameter SWITCHMODE = 4'b0100;
//显示状态设置,显示开/关;光标开/关;闪烁开/关
parameter SHIFT = 4'b0101;
//光标画面滚动 画面/光标平移一位;左/右平移一位
parameter SETFUNCTION = 4'b0110;
//工作方式设置 1:8/1:4位数据接口;两行/一行显示;5x10/5x7点阵
parameter SETDDRAM1 = 4'b0111; //设置DDRAM
parameter SETDDRAM2 = 4'b1000; //设置DDRAM
parameter READFLAG = 4'b1001; //读状态
parameter WRITERAM1 = 4'b1010; //写RAM
parameter WRITERAM2 = 4'b1011; //写RAM
function [7:0] strram; //函数调用
input [5:0] n;
begin
case(n)
6'b000000:strram="I"; //显示的字符
6'b000001:strram="'";
6'b000010:strram="m";
6'b000011:strram=" ";
6'b000100:strram="p";
6'b000101:strram="l";
6'b000110:strram="a";
6'b000111:strram="y";
6'b001000:strram="b";
6'b001001:strram="l";
6'b001010:strram="o";
6'b001011:strram="n";
6'b001100:strram="g";
6'b001101:strram="^";
6'b001110:strram="_";
6'b001111:strram="^";
6'b010000:strram="I";
6'b010001:strram="t";
6'b010010:strram="'";
6'b010011:strram="s";
6'b010100:strram=" ";
6'b010101:strram="E";
6'b010110:strram="E";
6'b010111:strram="P";
6'b011000:strram="W";
6'b011001:strram=" ";
6'b011010:strram="D";
6'b011011:strram="I";
6'b011100:strram="Y";
6'b011101:strram="^";
6'b011110:strram="o";
6'b011111:strram="^";
default: strram="X";
endcase
end
endfunction
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
cnt = 25'b0; //cnt可以改变一下,自己试试效果
else
cnt = cnt + 1'b1;
end
/*assign EN = cnt[15]; //lcd enable,keep same time; >1000ns
wire trig = (cnt == 16'h7FFF) ? 1'b1 : 1'b0; //when lcd_en is steady,write a cmd*/
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
trig = 0;
lcd_en = 0;
end
else if(cnt < 25'h0ffffff)
begin
lcd_en = 0;
end
else if(cnt == 25'h0ffffff)
begin
trig = 1'b1; //生成一个触发脉冲,控制1602的操作指令
lcd_en = 1'b1;
end
else
trig = 0;
end
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
data = 8'hzz;
lcd_rs = 1'bz; //这里最好都设置为高阻,以免初始化失败
lcd_rw = 1'bz;
state = IDLE;
address = 6'b0;
end
else if(trig == 1'b1)
begin
case(state)
IDLE: begin
lcd_rs = 0;
lcd_rw = 0;
data = 8'hzz;
state = CLEAR;
end
CLEAR: begin
lcd_rs = 0;
lcd_rw = 0;
data = 8'b00000001; //清屏01
state = SETFUNCTION;
end
SETFUNCTION: begin
lcd_rs = 0;
lcd_rw = 0; //3C
data = 8'b00111100;
state = SWITCHMODE;
end
SWITCHMODE: begin
lcd_rs = 0;
lcd_rw = 0;
data = 8'b00001100; //显示状态开关设置0C
state = SETMODE;
end
SETMODE: begin
lcd_rs = 0;
lcd_rw = 0;
data = 8'b00000111; //输入方式设置06固定,07滚动
state = SHIFT;
end
SHIFT: begin
lcd_rs = 0;
lcd_rw = 0;
data = 8'b00001100; //光标画面滚动
state = SETDDRAM1;
end
SETDDRAM1: begin
lcd_rs = 0;
lcd_rw = 0;
data = 8'b10000000; //显示数据存储器地址80,第一行
state = WRITERAM1;
end
SETDDRAM2: begin
lcd_rs = 0;
lcd_rw = 0;
data = 8'b11000000; //显示数据存储器地址80+40,第二行
state = WRITERAM2;
end
WRITERAM1: begin
if(address <= 6'b001111)
begin
lcd_rs = 1;
lcd_rw = 0;
data = strram(address); //写数据
address = address+1;
state = WRITERAM1;
end
else
begin
lcd_rs = 0;
lcd_rw = 0;
state = SETDDRAM2;
end
end
WRITERAM2: begin
if(address <= 6'b011111)
begin
lcd_rs = 1;
lcd_rw = 0;
data = strram(address); //写数据
address = address+1;
state = WRITERAM2;
end
else
begin
lcd_rs = 0;
lcd_rw = 0;
state = SETDDRAM1;
address = 6'b000000;
end
end
default: state = IDLE;
endcase
end
end
assign RS = lcd_rs;
assign RW = lcd_rw;
assign EN = lcd_en;
endmodule
你的帖子的地址可以在你的帖子里“右键”“属性”查看
回复
有奖活动 | |
---|---|
【有奖活动】分享技术经验,兑换京东卡 | |
话不多说,快进群! | |
请大声喊出:我要开发板! | |
【有奖活动】EEPW网站征稿正在进行时,欢迎踊跃投稿啦 | |
奖!发布技术笔记,技术评测贴换取您心仪的礼品 | |
打赏了!打赏了!打赏了! |