论坛» DIY与开源设计» 电子DIY

菜鸟
2012-11-11 19:16 22楼
电子琴程序,不懂音乐,所以,频率不知道是多少,就弄了几个频率,实现了这个功能。。
module organ(clk,rst_n,key,beep);
input clk,rst_n;
input [7:0] key;
output beep;

//计数,2^24=16*10^6;即16*10^6*20ns=0.32s=320ms
reg [24:0] cnt;
reg beep;

reg tmp;

always @(posedge clk or negedge rst_n)
if(!rst_n)
begin
tmp<=1'b0;
end
else
case(key)
8'b1111_1110: tmp <= cnt[16];
8'b1111_1101: tmp <= cnt[17];
8'b1111_1011: tmp <= cnt[18];
8'b1111_0111: tmp <= cnt[19];
8'b1110_1111: tmp <= cnt[20];
8'b1101_1111: tmp <= cnt[21];
8'b1011_1111: tmp <= cnt[22];
8'b0111_1111: tmp <= cnt[23];
default:tmp<=1'b0;
endcase


always @(posedge clk or negedge rst_n)
if(!rst_n)
cnt<=25'b0;
else
cnt<=cnt+1'b1;

always @(posedge clk or negedge rst_n)
if(!rst_n)
beep<=1'b0;
else if(tmp)
beep <= 1'b1;
else
beep <= 1'b0;

endmodule
菜鸟
2012-11-18 16:54 24楼
硬件乐曲自动演奏程序
从网上看到了一段VHDL的程序,改为了Verilog HDL程序,看了看,有些明白,不过,还有一些不是特别懂,比如那些数据的由来、时钟为什么这么分频等。以后有时间一定要写个自己的。
module song(clk,rst_n,beep);
input clk,rst_n;
output beep; reg speaker;

reg [12:0] driver,origin; reg [7:0] counter;
reg [1:0] counter1;
reg [23:0] counter2; reg [6:0] DIGIT;
reg [1:0] count;
reg carrier,clk_4MHZ,clk_4HZ;

//FPGA开发板上使用50MHz的时钟源
//感觉clk_4MHZ是4分频后得到的。而不是4MHz
always @(posedge clk or negedge rst_n)
if(!rst_n)
begin
clk_4MHZ <= 0;
counter1 <= 1;
clk_4HZ <= 0;
counter2 <= 1;
end
else
begin
if(counter1 == 1)
begin
clk_4MHZ <= 1;
counter1 <= 2;
end
else if(counter1 == 3)
begin
clk_4MHZ <= 0;
counter1 <= 0;
end
else
counter1 <= counter1 +1;

//50MHz:50 000 000 这里的5 000 000,得到的是10Hz
if(counter2 == 5000000)
begin
clk_4HZ <= 1;
counter2 <= 5000001;
end
else if(counter2 == 10000000)
begin
clk_4HZ <= 0;
counter2 <= 1;
end
else
counter2 <= counter2 +1;
end always @(posedge clk_4MHZ)
if(driver == 13'b1111111111111)
begin
carrier <= 1;
driver <= origin;
end
else
begin
driver <= driver + 1;
carrier <= 0;
end always @(posedge carrier)
begin
count <= count + 1;
if(count == 0)
speaker <= 1;
else
speaker <= 0;
end

always @(posedge clk_4HZ)
if(counter == 140)
counter <= 0;
else
begin
counter <= counter +1;
case(counter)
0 :DIGIT<=7'b0000011; 1 :DIGIT<=7'b0000011;
2 :DIGIT<=7'b0000011; 3 :DIGIT<=7'b0000011;
4 :DIGIT<=7'b0000101; 5 :DIGIT<=7'b0000101;
6 :DIGIT<=7'b0000101; 7 :DIGIT<=7'b0000110;
8 :DIGIT<=7'b0001000; 9 :DIGIT<=7'b0001000;
10 :DIGIT<=7'b0001000; 11 :DIGIT<=7'b0010000;
12 :DIGIT<=7'b0000110; 13 :DIGIT<=7'b0001000;
14 :DIGIT<=7'b0000101; 15 :DIGIT<=7'b0000101;
16 :DIGIT<=7'b0101000; 17 :DIGIT<=7'b0101000;
18 :DIGIT<=7'b0101000; 19 :DIGIT<=7'b1000000;
20 :DIGIT<=7'b0110000; 21 :DIGIT<=7'b0101000;
22 :DIGIT<=7'b0011000; 23 :DIGIT<=7'b0101000;
24 :DIGIT<=7'b0010000; 25 :DIGIT<=7'b0010000;
26 :DIGIT<=7'b0010000; 27 :DIGIT<=7'b0010000;
28 :DIGIT<=7'b0010000; 29 :DIGIT<=7'b0010000;
30 :DIGIT<=7'b0000011; 31 :DIGIT<=7'b0000000;
32 :DIGIT<=7'b0010000; 33 :DIGIT<=7'b0010000;
34 :DIGIT<=7'b0010000; 35 :DIGIT<=7'b0011000;
36 :DIGIT<=7'b0000111; 37 :DIGIT<=7'b0000111;
38 :DIGIT<=7'b0000110; 39 :DIGIT<=7'b0000110;
40 :DIGIT<=7'b0000101; 41 :DIGIT<=7'b0000101;
42 :DIGIT<=7'b0000101; 43 :DIGIT<=7'b0000110;
44 :DIGIT<=7'b0001000; 45 :DIGIT<=7'b0001000;
46 :DIGIT<=7'b0010000; 47 :DIGIT<=7'b0010000;
48 :DIGIT<=7'b0000011; 49 :DIGIT<=7'b0000011;
50 :DIGIT<=7'b0001000; 51 :DIGIT<=7'b0001000;
52 :DIGIT<=7'b0000110; 53 :DIGIT<=7'b0000101;
54 :DIGIT<=7'b0000110; 55 :DIGIT<=7'b0001000;
56 :DIGIT<=7'b0000101; 57 :DIGIT<=7'b0000101;
58 :DIGIT<=7'b0000101; 59 :DIGIT<=7'b0000101;
60 :DIGIT<=7'b0000101; 61 :DIGIT<=7'b0000101;
62 :DIGIT<=7'b0000101; 63 :DIGIT<=7'b0000101;
64 :DIGIT<=7'b0011000; 65 :DIGIT<=7'b0011000;
66 :DIGIT<=7'b0011000; 67 :DIGIT<=7'b0101000;
68 :DIGIT<=7'b0000111; 69 :DIGIT<=7'b0000111;
70 :DIGIT<=7'b0010000; 71 :DIGIT<=7'b0010000;
72 :DIGIT<=7'b0000110; 73 :DIGIT<=7'b0001000;
74 :DIGIT<=7'b0000101; 75 :DIGIT<=7'b0000101;
76 :DIGIT<=7'b0000101; 77 :DIGIT<=7'b0000101;
78 :DIGIT<=7'b0000101; 79 :DIGIT<=7'b0000101;
80 :DIGIT<=7'b0000011; 81 :DIGIT<=7'b0000101;
82 :DIGIT<=7'b0000011; 83 :DIGIT<=7'b0000011;
84 :DIGIT<=7'b0000101; 85 :DIGIT<=7'b0000110;
86 :DIGIT<=7'b0000111; 87 :DIGIT<=7'b0010000;
88 :DIGIT<=7'b0000110; 89 :DIGIT<=7'b0000110;
90 :DIGIT<=7'b0000110; 91 :DIGIT<=7'b0000110;
92 :DIGIT<=7'b0000110; 93 :DIGIT<=7'b0000110;
94 :DIGIT<=7'b0000101; 95 :DIGIT<=7'b0000110;
96 :DIGIT<=7'b0001000; 97 :DIGIT<=7'b0001000;
98 :DIGIT<=7'b0001000; 99 :DIGIT<=7'b0010000;
100:DIGIT<=7'b0101000; 101:DIGIT<=7'b0101000;
102:DIGIT<=7'b0101000; 103:DIGIT<=7'b0011000;
104:DIGIT<=7'b0010000; 105:DIGIT<=7'b0010000;
106:DIGIT<=7'b0011000; 107:DIGIT<=7'b0010000;
108:DIGIT<=7'b0001000; 109:DIGIT<=7'b0001000;
110:DIGIT<=7'b0000110; 111:DIGIT<=7'b0000101;
112:DIGIT<=7'b0000011; 113:DIGIT<=7'b0000011;
114:DIGIT<=7'b0000011; 115:DIGIT<=7'b0000011;
116:DIGIT<=7'b0001000; 117:DIGIT<=7'b0001000;
118:DIGIT<=7'b0000110; 119:DIGIT<=7'b0001000;
120:DIGIT<=7'b0000110; 121:DIGIT<=7'b0000011;
122:DIGIT<=7'b0000011; 123:DIGIT<=7'b0010000;
124:DIGIT<=7'b0000011; 125:DIGIT<=7'b0000101;
126:DIGIT<=7'b0000110; 127:DIGIT<=7'b0001000;
128:DIGIT<=7'b0000101; 129:DIGIT<=7'b0000101;
130:DIGIT<=7'b0000101; 131:DIGIT<=7'b0000101;
132:DIGIT<=7'b0000101; 133:DIGIT<=7'b0000101;
134:DIGIT<=7'b0000101; 135:DIGIT<=7'b0000101;
136:DIGIT<=7'b0000000; 137:DIGIT<=7'b0000000;
138:DIGIT<=7'b0000000; 139:DIGIT<=7'b0000000;
default:DIGIT<=7'b0000000;
endcase
case(DIGIT)
7'b0000011:origin<=13'b0100001001100;
7'b0000101:origin<=13'b0110000010001;
7'b0000110:origin<=13'b0111000111110;
7'b0000111:origin<=13'b1000000101101;
7'b0001000:origin<=13'b1000100010001;
7'b0010000:origin<=13'b1001010110010;
7'b0011000:origin<=13'b1010000100101;
7'b0101000:origin<=13'b1011000001000;
7'b0110000:origin<=13'b1011100011110;
7'b1000000:origin<=13'b1100010001000;
default:origin<=13'b1111111111111;
endcase
end

assign beep = speaker;

endmodule
菜鸟
2012-11-18 16:57 26楼

PS2键盘控制程序:
顶层程序:
module keyboard(clk,rst_n,sm_cs,sm_db,ps2_clk,ps2_data,key);
//功能说明:根据PS2协议,将 PS2键盘上按键的信息提取处理,并转换为asic码,将asic码输出到LED和数码管上显示出来。。
input clk,rst_n,ps2_clk,ps2_data;
output [3:0] sm_cs;
output [6:0] sm_db;
output [7:0] key;

wire [7:0] ps2_byte;

// 实例化数码管
digitron digitron
(
.clk(clk),
.rst_n(rst_n),
.sm_cs(sm_cs),
.sm_db(sm_db),
.ps2_byte(ps2_byte)
);
// 实例化键盘
ps2 instance_name
(
.clk(clk),
.rst_n(rst_n),
.ps2_clk(ps2_clk),
.ps2_data(ps2_data),
.ps2_byte(ps2_byte)
);

assign key = ps2_byte;

endmodule

PS2协议程序:
module ps2(clk,rst_n,ps2_clk,ps2_data,ps2_byte);
input clk,rst_n,ps2_clk,ps2_data;
output [7:0] ps2_byte;

//捕捉下降沿
reg ps2_clk0,ps2_clk1,ps2_clk2;
wire neg_ps2_clk;

always @(posedge clk or negedge rst_n)
if(!rst_n)
begin
ps2_clk0 <= 1'b0;
ps2_clk1 <= 1'b0;
ps2_clk2 <= 1'b0;
end
else
begin
ps2_clk0 <= ps2_clk;
ps2_clk1 <= ps2_clk0;
ps2_clk2 <= ps2_clk1;
end
assign neg_ps2_clk = ps2_clk2 & ~ps2_clk1;

//按照时序进行取数
reg [7:0] ps2_byte_r; //ouput ps2_byte对应的寄存器变量
reg [7:0] temp_data; //数??缓冲变量
reg [3:0] num;

always @(posedge clk or negedge rst_n)
if(!rst_n)
begin
temp_data <= 8'b0;
num <= 1'b0;
end
else if(neg_ps2_clk) //当下降沿时,出发事件
begin
case(num)
4'd0: num <= num + 1; //开始状态
4'd1:
begin
num <= num + 1;
temp_data[0] <= ps2_data;
end
4'd2:
begin
num <= num + 1;
temp_data[1] <= ps2_data;
end
4'd3:
begin
num <= num + 1;
temp_data[2] <= ps2_data;
end
4'd4:
begin
num <= num + 1;
temp_data[3] <= ps2_data;
end
4'd5:
begin
num <= num + 1;
temp_data[4] <= ps2_data;
end
4'd6:
begin
num <= num + 1;
temp_data[5] <= ps2_data;
end
4'd7:
begin
num <= num + 1;
temp_data[6] <= ps2_data;
end
4'd8:
begin
num <= num + 1;
temp_data[7] <= ps2_data;
end
4'd9: num <= num + 1;
4'd10: num <= 0;
default: ;
endcase
end

//检测是否松手
reg key_f0;

always @(posedge clk or negedge rst_n)
if(!rst_n)
key_f0 <= 0;
else if(num == 4'd10) //刚传完一个字节的数据
begin
if(temp_data == 8'hf0)
key_f0 <= 1;
else
begin
if(!key_f0) //??
ps2_byte_r <= temp_data;
else //??
key_f0 <= 0;
end
end

//找出对应的ASCII码
reg [7:0] ps2_asc;

always @(ps2_byte_r)
case(ps2_byte_r)
8'h15: ps2_asc <= 8'h51; //Q
8'h1d: ps2_asc <= 8'h57; //W
8'h24: ps2_asc <= 8'h45; //E
8'h2d: ps2_asc <= 8'h52; //R
8'h2c: ps2_asc <= 8'h54; //T
8'h35: ps2_asc <= 8'h59; //Y
8'h3c: ps2_asc <= 8'h55; //U
8'h43: ps2_asc <= 8'h49; //I
8'h44: ps2_asc <= 8'h4f; //O
8'h4d: ps2_asc <= 8'h50; //P
8'h1c: ps2_asc <= 8'h41; //A
8'h1b: ps2_asc <= 8'h53; //S
8'h23: ps2_asc <= 8'h44; //D
8'h2b: ps2_asc <= 8'h46; //F
8'h34: ps2_asc <= 8'h47; //G
8'h33: ps2_asc <= 8'h48; //H
8'h3b: ps2_asc <= 8'h4a; //J
8'h42: ps2_asc <= 8'h4b; //K
8'h4b: ps2_asc <= 8'h4c; //L
8'h1a: ps2_asc <= 8'h5a; //Z
8'h22: ps2_asc <= 8'h58; //X
8'h21: ps2_asc <= 8'h43; //C
8'h2a: ps2_asc <= 8'h56; //V
8'h32: ps2_asc <= 8'h42; //B
8'h31: ps2_asc <= 8'h4e; //N
8'h3a: ps2_asc <= 8'h4d; //M
endcase
//将对应的ASCII码送出
assign ps2_byte = ps2_asc;
endmodule

数码管显示程序
module digitron(clk,rst_n,sm_cs,sm_db,ps2_byte);
input clk,rst_n;
input [7:0] ps2_byte;
output [3:0] sm_cs;
output [6:0] sm_db;

//计数,2^24=16*10^6;即16*10^6*20ns=0.32s=320ms
reg [24:0] cnt;

always @(posedge clk or negedge rst_n)
if(!rst_n) cnt<=25'b0;
else cnt<=cnt+1'b1;

reg [3:0] shi,ge;
always @(posedge clk or negedge rst_n)
if(!rst_n)
begin
shi = 4'd0;
ge = 4'd0;
end
else if(cnt==25'h1ff_ffff)
begin
shi = ps2_byte/16;
ge = ps2_byte%16;
end

parameter
seg0 = 7'hc0,
seg1 = 7'hf9,
seg2 = 7'ha4,
seg3 = 7'hb0,
seg4 = 7'h99,
seg5 = 7'h92,
seg6 = 7'h82,
seg7 = 7'hf8,
seg8 = 7'h80,
seg9 = 7'h90,
sega = 7'h88,
segb = 7'h83,
segc = 7'hc6,
segd = 7'ha1,
sege = 7'h86,
segf = 7'h8e;
//segf =7'hff;
reg [3:0] num;
reg [6:0] sm_dbr;
always @(num)
case(num)
4'h0:sm_dbr<=seg0;
4'h1:sm_dbr<=seg1;
4'h2:sm_dbr<=seg2;
4'h3:sm_dbr<=seg3;
4'h4:sm_dbr<=seg4;
4'h5:sm_dbr<=seg5;
4'h6:sm_dbr<=seg6;
4'h7:sm_dbr<=seg7;
4'h8:sm_dbr<=seg8;
4'h9:sm_dbr<=seg9;
4'hA:sm_dbr<=sega;
4'hB:sm_dbr<=segb;
4'hC:sm_dbr<=segc;
4'hD:sm_dbr<=segd;
4'hE:sm_dbr<=sege;
4'hF:sm_dbr<=segf;
default:;
endcase

reg sm_cs2_r,sm_cs1_r;
always @(clk or shi or ge)
begin
if(cnt[20])
begin
sm_cs2_r = 0;
sm_cs1_r = 1;
num = shi;
end
else
begin
sm_cs2_r = 1;
sm_cs1_r = 0;
num = ge;
end
end

assign sm_db = sm_dbr;
assign sm_cs[1:0] = 2'b11;
assign sm_cs[3] = sm_cs1_r;
assign sm_cs[2] = sm_cs2_r;

endmodule

管教配置程序:
#------------------GLOBAL--------------------#
set_global_assignment -name RESERVE_ALL_UNUSED_PINS "AS INPUT TRI-STATED"
set_global_assignment -name ENABLE_INIT_DONE_OUTPUT OFF

set_location_assignment PIN_27 -to clk
set_location_assignment PIN_112 -to rst_n

set_location_assignment PIN_5 -to ps2_data
set_location_assignment PIN_3 -to ps2_clk

set_location_assignment PIN_195 -to sm_cs[3]
set_location_assignment PIN_192 -to sm_cs[2]
set_location_assignment PIN_189 -to sm_cs[1]
set_location_assignment PIN_188 -to sm_cs[0]

#set_location_assignment PIN_201 -to sm_db[7]
set_location_assignment PIN_206 -to sm_db[6]
set_location_assignment PIN_193 -to sm_db[5]
set_location_assignment PIN_198 -to sm_db[4]
set_location_assignment PIN_200 -to sm_db[3]
set_location_assignment PIN_205 -to sm_db[2]
set_location_assignment PIN_197 -to sm_db[1]
set_location_assignment PIN_191 -to sm_db[0]

set_location_assignment PIN_128 -to key[0]
set_location_assignment PIN_127 -to key[1]
set_location_assignment PIN_134 -to key[2]
set_location_assignment PIN_133 -to key[3]
set_location_assignment PIN_137 -to key[4]
set_location_assignment PIN_135 -to key[5]
set_location_assignment PIN_139 -to key[6]
set_location_assignment PIN_138 -to key[7]

菜鸟
2012-11-18 17:01 27楼
菜鸟
2012-11-18 17:02 28楼
VGA显示程序:
module vga2(clk,rst_n,vsync,hsync,r,g,b);
input clk,rst_n;
output vsync,hsync;
output[2:0] r;
output[2:0] g;
output[1:0] b;
reg vsync,hsync;
reg[10:0] x_cnt;
reg[9:0] y_cnt;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////// 水平扫描参数的设定
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
parameter LinePeriod =12'd1040; //行同步周期
parameter H_SyncPulse=10'd120; //?型叫藕?
parameter H_BackPorch=10'd61; //行同步后肩
parameter H_ActivePix=10'd806; //行同步数据有效
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////// 垂直扫描参数的设定
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
parameter FramePeriod=10'd666;
parameter V_SyncPulse=10'd6;
parameter V_BackPorch=10'd21;
parameter V_ActivePix=10'd604;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////// 水平扫描计数x_cnt只负责计数从0计数计到1040
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
always @ (posedge clk or negedge rst_n)
if(!rst_n) x_cnt <= 1;
else if(x_cnt == LinePeriod) x_cnt <= 1;
else x_cnt <= x_cnt+ 1;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////// 水平扫描信号vsync产生 在0到120时为低电平
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
always @ (posedge clk or negedge rst_n)
if(!rst_n) hsync <= 1'b1;
else if(x_cnt == 1) hsync <= 1'b0; //产生hsync信号
else if(x_cnt == H_SyncPulse+1) hsync <= 1'b1;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////// 垂直扫描计数
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
always @ (posedge clk or negedge rst_n)
if(!rst_n) y_cnt <= 1;
else if(y_cnt == FramePeriod) y_cnt <= 1;
else if(x_cnt == LinePeriod) y_cnt <= y_cnt+1;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////// 垂直扫描信号hsync产生
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
always @ (posedge clk or negedge rst_n)
if(!rst_n) vsync <= 1'b1;
else if(y_cnt == 1) vsync <= 1'b0; //产生vsync信号
else if(y_cnt == V_SyncPulse+1) vsync <= 1'b1;

wire valid; //有效显示区标志
assign valid =
(x_cnt >= (H_SyncPulse+H_BackPorch)) &&
(x_cnt < (H_SyncPulse+H_BackPorch+H_ActivePix)) &&
(y_cnt >= (V_SyncPulse+V_BackPorch)) &&
(y_cnt < (V_SyncPulse+V_BackPorch+V_ActivePix));

wire[9:0] x_pos=x_cnt-H_SyncPulse-H_BackPorch;
wire[9:0] y_pos=y_cnt-V_SyncPulse-V_BackPorch;

//显示256种颜色
reg[7:0] vga_rgb;

always @(posedge clk)
if(!valid)
vga_rgb <= 8'h00;
else
begin
case(x_pos)
10'd0:
if(y_pos >= 10'd0 && y_pos < 10'd37) vga_rgb <= 8'd0;
else if(y_pos >= 10'd37 && y_pos < 10'd74) vga_rgb <= 8'd16;
else if(y_pos >= 10'd74 && y_pos < 10'd111) vga_rgb <= 8'd32;
else if(y_pos >= 10'd111 && y_pos < 10'd148) vga_rgb <= 8'd48;
else if(y_pos >= 10'd148 && y_pos < 10'd185) vga_rgb <= 8'd64;
else if(y_pos >= 10'd185 && y_pos < 10'd222) vga_rgb <= 8'd80;
else if(y_pos >= 10'd222 && y_pos < 10'd259) vga_rgb <= 8'd96;
else if(y_pos >= 10'd259 && y_pos < 10'd296) vga_rgb <= 8'd112;
else if(y_pos >= 10'd296 && y_pos < 10'd333) vga_rgb <= 8'd128;
else if(y_pos >= 10'd333 && y_pos < 10'd370) vga_rgb <= 8'd144;
else if(y_pos >= 10'd370 && y_pos < 10'd407) vga_rgb <= 8'd160;
else if(y_pos >= 10'd407 && y_pos < 10'd444) vga_rgb <= 8'd176;
else if(y_pos >= 10'd444 && y_pos < 10'd481) vga_rgb <= 8'd192;
else if(y_pos >= 10'd481 && y_pos < 10'd518) vga_rgb <= 8'd208;
else if(y_pos >= 10'd518 && y_pos < 10'd555) vga_rgb <= 8'd224;
else vga_rgb <= 8'd240;
10'd50,10'd100,10'd150,10'd200,10'd250,10'd300,10'd350,10'd400,
10'd450,10'd500,10'd550,10'd600,10'd650,10'd700,10'd750,10'd800:vga_rgb <= vga_rgb + 1'b1;
default: ;
endcase
end

assign r = vga_rgb[7:5];
assign g = vga_rgb[4:2];
assign b = vga_rgb[1:0];

endmodule
助工
2012-11-26 20:04 30楼
kankan
共31条 3/4 1 2 3 4 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册]