实验基于FPGA黑金开发平台AX301,此款开发板使用的是 ALTERA 公司的 Cyclone IV 系列 FPGA,型号为 EP4CE6F17C8
本文内容基于电子设计自动化老师发的 实验报告模板
实验报告可以参考 博客园 - 电子设计自动化实验报告 或 飞书 - 电子设计自动化-实验报告
实验一:LED流水灯设计
codes
led_test.v
`timescale 1ns / 1ps
module led_test
(
input clk, // system clock 50Mhz on board
input rst_n, // reset ,low active
output reg[3:0] led // LED,use for control the LED signal on board
);
//define the time counter
reg [31:0] timer;
// cycle counter:from 0 to 4 sec
always@(posedge clk or negedge rst_n)
begin
if (rst_n == 1'b0)
timer <= 32'd0; //when the reset signal valid,time counter clearing
else if (timer == 32'd199_999_999) //4 seconds count(50M*4-1=199999999)
timer <= 32'd0; //count done,clearing the time counter
else
timer <= timer + 32'd1; //timer counter = timer counter + 1
end
// LED control
always@(posedge clk or negedge rst_n)
begin
if (rst_n == 1'b0)
led <= 4'b0000; //when the reset signal active
else if (timer == 32'd49_999_999) //time counter count to 1st sec,LED1 lighten
led <= 4'b0001;
else if (timer == 32'd99_999_999) //time counter count to 2nd sec,LED2 lighten
led <= 4'b0010;
else if (timer == 32'd149_999_999) //time counter count to 3rd sec,LED3 lighten
led <= 4'b0100;
else if (timer == 32'd199_999_999) //time counter count to 4th sec,LED4 lighten
led <= 4'b1000;
end
endmodule
实验二:数码管动态显示
codes
seg_test.v
module seg_test(
input clk,
input rst_n,
output[5:0]seg_sel,
output[7:0]seg_data
);
reg[31:0] timer_cnt;
reg en_1hz; //1 second , 1 counter enable
always@(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
en_1hz <= 1'b0;
timer_cnt <= 32'd0;
end
else if(timer_cnt >= 32'd49_999_999)
begin
en_1hz <= 1'b1;
timer_cnt <= 32'd0;
end
else
begin
en_1hz <= 1'b0;
timer_cnt <= timer_cnt + 32'd1;
end
end
wire[3:0] count0;
wire t0;
count_m10 count10_m0(
.clk (clk),
.rst_n (rst_n),
.en (en_1hz),
.clr (1'b0),
.data (count0),
.t (t0)
);
wire[3:0] count1;
wire t1;
count_m6 count6_m1( //oringin: count_m10 count10_m1
.clk (clk),
.rst_n (rst_n),
.en (t0),
.clr (1'b0),
.data (count1),
.t (t1)
);
wire[3:0] count2;
wire t2;
count_m10 count10_m2(
.clk (clk),
.rst_n (rst_n),
.en (t1),
.clr (1'b0),
.data (count2),
.t (t2)
);
wire[3:0] count3;
wire t3;
count_m10 count10_m3(
.clk (clk),
.rst_n (rst_n),
.en (t2),
.clr (1'b0),
.data (count3),
.t (t3)
);
wire[3:0] count4;
wire t4;
count_m10 count10_m4(
.clk (clk),
.rst_n (rst_n),
.en (t3),
.clr (1'b0),
.data (count4),
.t (t4)
);
wire[3:0] count5;
wire t5;
count_m10 count10_m5(
.clk (clk),
.rst_n (rst_n),
.en (t4),
.clr (1'b0),
.data (count5),
.t (t5)
);
wire[6:0] seg_data_0;
seg_decoder seg_decoder_m0(
.bin_data (count5),
.seg_data (seg_data_0)
);
wire[6:0] seg_data_1;
seg_decoder seg_decoder_m1(
.bin_data (count4),
.seg_data (seg_data_1)
);
wire[6:0] seg_data_2;
seg_decoder seg_decoder_m2(
.bin_data (count3),
.seg_data (seg_data_2)
);
wire[6:0] seg_data_3;
seg_decoder seg_decoder_m3(
.bin_data (count2),
.seg_data (seg_data_3)
);
wire[6:0] seg_data_4;
seg_decoder seg_decoder_m4(
.bin_data (count1), //attention, this is COUNT1
.seg_data (seg_data_4)
);
wire[6:0] seg_data_5;
seg_decoder seg_decoder_m5(
.bin_data (count0),
.seg_data (seg_data_5)
);
seg_scan seg_scan_m0(
.clk (clk),
.rst_n (rst_n),
.seg_sel (seg_sel),
.seg_data (seg_data),
// .seg_data_0 ({1'b1,seg_data_0}), //The decimal point at the highest bit,and low level effecitve
// .seg_data_1 ({1'b1,seg_data_1}),
// .seg_data_2 ({1'b1,seg_data_2}),
// .seg_data_3 ({1'b1,seg_data_3}),
.seg_data_4 ({1'b1,seg_data_4}),
.seg_data_5 ({1'b1,seg_data_5})
);
endmodule
seg_scan.v
module seg_scan(
input clk,
input rst_n,
output reg[5:0] seg_sel, //digital led chip select
output reg[7:0] seg_data, //eight segment digital tube output,MSB is the decimal point
// input[7:0] seg_data_0,
// input[7:0] seg_data_1,
// input[7:0] seg_data_2,
// input[7:0] seg_data_3,
input[7:0] seg_data_4,
input[7:0] seg_data_5
);
parameter SCAN_FREQ = 200; //scan frequency
parameter CLK_FREQ = 50000000; //clock frequency
parameter SCAN_COUNT = CLK_FREQ /(SCAN_FREQ * 6) - 1;
reg[31:0] scan_timer; //scan time counter
reg[3:0] scan_sel; //Scan select counter
always@(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
scan_timer <= 32'd0;
scan_sel <= 4'd0;
end
else if(scan_timer >= SCAN_COUNT)
begin
scan_timer <= 32'd0;
if(scan_sel == 4'd5)
scan_sel <= 4'd0;
else
scan_sel <= scan_sel + 4'd1;
end
else
begin
scan_timer <= scan_timer + 32'd1;
end
end
always@(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
seg_sel <= 6'b111111;
seg_data <= 8'hff;
end
else
begin
case(scan_sel)
// //first digital led
// 4'd0:
// begin
// seg_sel <= 6'b11_1110;
// seg_data <= seg_data_0;
// end
// //second digital led
// 4'd1:
// begin
// seg_sel <= 6'b11_1101;
// seg_data <= seg_data_1;
// end
// //...
// 4'd2:
// begin
// seg_sel <= 6'b11_1011;
// seg_data <= seg_data_2;
// end
// 4'd3:
// begin
// seg_sel <= 6'b11_0111;
// seg_data <= seg_data_3;
// end
4'd4:
begin
seg_sel <= 6'b10_1111;
seg_data <= seg_data_4;
end
4'd5:
begin
seg_sel <= 6'b01_1111;
seg_data <= seg_data_5;
end
default:
begin
seg_sel <= 6'b11_1111;
seg_data <= 8'hff;
end
endcase
end
end
endmodule
count_m10.v
module count_m10(
input clk,
input rst_n,
input en, //Counter enable
input clr, //Counter synchronous reset
output reg[3:0]data, //counter value
output reg t // carry enable signal
);
always@(posedge clk or negedge rst_n)
begin
if(rst_n==0)
begin
data <= 4'd0;
t <= 1'd0;
end
else if(clr)
begin
data <= 4'd0;
t <= 1'd0;
end
else if(en)
begin
if(data==4'd9)
begin
t<= 1'b1; //Counter to 9 to generate carry
data <= 4'd0;//Counter to 9 reset
end
else
begin
t <= 1'b0;
data <= data + 4'd1;
end
end
else
t <= 1'b0;
end
endmodule
count_m6.v
module count_m6(
input clk,
input rst_n,
input en, //Counter enable
input clr, //Counter synchronous reset
output reg[3:0]data, //counter value
output reg t // carry enable signal
);
always@(posedge clk or negedge rst_n)
begin
if(rst_n==0)
begin
data <= 4'd0;
t <= 1'd0;
end
else if(clr)
begin
data <= 4'd0;
t <= 1'd0;
end
else if(en)
begin
if(data==4'd5)
begin
t<= 1'b1; //Counter to 5 to generate carry
data <= 4'd0;//Counter to 5 reset
end
else
begin
t <= 1'b0;
data <= data + 4'd1;
end
end
else
t <= 1'b0;
end
endmodule
seg_decoder.v
module seg_decoder
(
input[3:0] bin_data, // bin data input
output reg[6:0] seg_data // seven segments LED output //origin: [6:0]
);
always@(*)
begin
case(bin_data)
4'd0:seg_data <= 7'b100_0000;
4'd1:seg_data <= 7'b111_1001;
4'd2:seg_data <= 7'b010_0100;
4'd3:seg_data <= 7'b011_0000;
4'd4:seg_data <= 7'b001_1001;
4'd5:seg_data <= 7'b001_0010;
4'd6:seg_data <= 7'b000_0010;
4'd7:seg_data <= 7'b111_1000;
4'd8:seg_data <= 7'b000_0000;
4'd9:seg_data <= 7'b001_0000;
4'ha:seg_data <= 7'b000_1000;
4'hb:seg_data <= 7'b000_0011;
4'hc:seg_data <= 7'b100_0110;
4'hd:seg_data <= 7'b010_0001;
4'he:seg_data <= 7'b000_0110;
4'hf:seg_data <= 7'b000_1110;
default:seg_data <= 7'b111_1111;
endcase
end
endmodule
实验三 数字时钟(计数器)
codes
在实验二代码的基础上,把前边代码中注释掉的部分取消注释,然后添加下边两个:
count_m24_x.v
module count_m24_x(
input clk,
input rst_n,
input en, //Counter enable
input clr, //Counter synchronous reset
output reg[3:0]data, //counter value
output reg t // carry enable signal
);
always@(posedge clk or negedge rst_n)
begin
if(rst_n==0)
begin
data <= 4'd0;
t <= 1'd0;
end
else if(clr)
begin
data <= 4'd0;
t <= 1'd0;
end
else if(en)
begin
if(data==4'd2)
begin
t<= 1'b1; //Counter to 2 to generate carry
data <= 4'd0;//Counter to 2 reset
end
else
begin
t <= 1'b0;
data <= data + 4'd1;
end
end
else
t <= 1'b0;
end
endmodule
count_m24_y.v
module count_m24_y(
input clk,
input rst_n,
input en, //Counter enable
input clr, //Counter synchronous reset
output reg[3:0]data, //counter value
output reg t // carry enable signal
);
reg[3:0] y_timer; // 24_y timer
always@(posedge clk or negedge rst_n)
begin
if(rst_n==0)
begin
data <= 4'd0;
t <= 1'd0;
y_timer <= 4'd0;
end
else if(clr)
begin
data <= 4'd0;
t <= 1'd0;
y_timer <= 4'd0;
end
else if(en)
begin
if(data==4'd9)
begin
t<= 1'b1; //Counter to 9 to generate carry
data <= 4'd0;//Counter to 9 reset
y_timer <= y_timer + 4'd1;
end
else if(data==4'd3 && y_timer==4'd2)
begin
t <= 1'b1;
data <= 4'd0;
y_timer <= 4'd0;
end
else
begin
t <= 1'b0;
data <= data + 4'd1;
end
end
else
t <= 1'b0;
end
endmodule
然后,在seg_test.v
里边,第89行的wire t3
的count_m10
改成count_m6
,然后把第100行和111行的wire t4
和wire t5
的count_m10
分别改为count_m24_y
和count_m24_x
即可实现。
另外,如果需要加快时钟的速度,可以修改seg_test.v
第45行的32'd49_999_999
为32'd49_999
,这样分钟的十位会按比秒稍微快一点的速度计数。
实验四:正弦信号发生器设计
codes
sinwave1.v
module sinwave1(clk,rst_n,dout);
input clk,rst_n;
output [7:0] dout;
reg[7:0] address;
reg rden;
always@(posedge clk or negedge rst_n)
begin
if (!rst_n)
rden<=0;
else
rden<=1;
end
always@(posedge clk or negedge rst_n)
begin
if (!rst_n)
address<=0;
else
address<=address+1;
end
myrom1 u1(.address(address),.clock(clk),.rden(rden),.q(dout));
endmodule
实验五:任意波形发生器设计
codes
hechengbo.v
module hechengbo(
input clk,
input rst,
output [7:0] q1,
output [7:0] q2,
output [7:0] q3,
output [7:0] q4,
output [8:0] q5,
output [8:0] q6,
output [8:0] q7,
output [8:0] q8,
output [8:0] q9,
output [8:0] q10,
output [9:0] q11,
output [9:0] q12,
output [9:0] q13,
output [9:0] q14,
output [10:0] q15
);
reg [8:0] address;
always @ (negedge clk or negedge rst)
begin
if(!rst)
address <= 1'b0;
else
address <= address+1'b1;
end
sinewave ROM_1
(
.address(address),
.clock (clk),
.q (q1)
);
fangbo ROM_2
(
.address(address),
.clock (clk),
.q (q2)
);
jvchibo ROM_3
(
.address(address),
.clock (clk),
.q (q3)
);
sanjiaobo ROM_4
(
.address(address),
.clock (clk),
.q (q4)
);
assign q5=q1+q2;
assign q6=q1+q3;
assign q7=q1+q4;
assign q8=q3+q2;
assign q9=q4+q2;
assign q10=q1+q3+q4;
assign q11=q1+q2+q3;
assign q12=q1+q2+q4;
assign q13=q2+q3+q4;
assign q14=q3+q4;
assign q15=q1+q2+q3+q4;
endmodule
实验六:硬件消抖电路设计
codes
seg_scan.v
module seg_scan(
input clk,
input rst_n,
output reg[5:0] seg_sel, //digital led chip select
output reg[7:0] seg_data, //eight segment digital tube output,MSB is the decimal point
input[7:0] seg_data_0,
input[7:0] seg_data_1,
input[7:0] seg_data_2,
input[7:0] seg_data_3,
input[7:0] seg_data_4,
input[7:0] seg_data_5
);
parameter SCAN_FREQ = 200; //scan frequency
parameter CLK_FREQ = 50000000; //clock frequency
parameter SCAN_COUNT = CLK_FREQ /(SCAN_FREQ * 6) - 1;
reg[31:0] scan_timer; //scan time counter
reg[3:0] scan_sel; //Scan select counter
always@(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
scan_timer <= 32'd0;
scan_sel <= 4'd0;
end
else if(scan_timer >= SCAN_COUNT)
begin
scan_timer <= 32'd0;
if(scan_sel == 4'd5)
scan_sel <= 4'd0;
else
scan_sel <= scan_sel + 4'd1;
end
else
begin
scan_timer <= scan_timer + 32'd1;
end
end
always@(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
seg_sel <= 6'b111111;
seg_data <= 8'hff;
end
else
begin
case(scan_sel)
//first digital led
4'd0:
begin
seg_sel <= 6'b11_1110;
seg_data <= seg_data_0;
end
//second digital led
4'd1:
begin
seg_sel <= 6'b11_1101;
seg_data <= seg_data_1;
end
//...
4'd2:
begin
seg_sel <= 6'b11_1011;
seg_data <= seg_data_2;
end
4'd3:
begin
seg_sel <= 6'b11_0111;
seg_data <= seg_data_3;
end
4'd4:
begin
seg_sel <= 6'b10_1111;
seg_data <= seg_data_4;
end
4'd5:
begin
seg_sel <= 6'b01_1111;
seg_data <= seg_data_5;
end
default:
begin
seg_sel <= 6'b11_1111;
seg_data <= 8'hff;
end
endcase
end
end
endmodule
seg_decoder.v
module seg_decoder
(
input[3:0] bin_data, // bin data input
output reg[6:0] seg_data // seven segments LED output
);
always@(*)
begin
case(bin_data)
4'd0:seg_data <= 7'b100_0000;
4'd1:seg_data <= 7'b111_1001;
4'd2:seg_data <= 7'b010_0100;
4'd3:seg_data <= 7'b011_0000;
4'd4:seg_data <= 7'b001_1001;
4'd5:seg_data <= 7'b001_0010;
4'd6:seg_data <= 7'b000_0010;
4'd7:seg_data <= 7'b111_1000;
4'd8:seg_data <= 7'b000_0000;
4'd9:seg_data <= 7'b001_0000;
4'ha:seg_data <= 7'b000_1000;
4'hb:seg_data <= 7'b000_0011;
4'hc:seg_data <= 7'b100_0110;
4'hd:seg_data <= 7'b010_0001;
4'he:seg_data <= 7'b000_0110;
4'hf:seg_data <= 7'b000_1110;
default:seg_data <= 7'b111_1111;
endcase
end
endmodule
key_debounce.v
module key_debounce(
input clk,
input rst_n,
input key1,
output [5:0] seg_sel,
output [7:0] seg_data
);
wire button_negedge; //Key falling edge
ax_debounce ax_debounce_m0
(
.clk (clk),
.rst (~rst_n),
.button_in (key1),
.button_posedge (),
.button_negedge (button_negedge),
.button_out ()
);
wire[3:0] count;
wire t0;
count_m10 count10_m0(
.clk (clk),
.rst_n (rst_n),
.en (button_negedge),
.clr (1'b0),
.data (count),
.t (t0)
);
wire[3:0] count1;
wire t1;
count_m6 count10_m1(
.clk (clk),
.rst_n (rst_n),
.en (t0),
.clr (1'b0),
.data (count1),
.t (t1)
);
//Count decoding
wire[6:0] seg_data_0;
seg_decoder seg_decoder_m0(
.bin_data (count),
.seg_data (seg_data_0)
);
wire[6:0] seg_data_1;
seg_decoder seg_decoder_m1(
.bin_data (count1),
.seg_data (seg_data_1)
);
seg_scan seg_scan_m0(
.clk (clk),
.rst_n (rst_n),
.seg_sel (seg_sel),
.seg_data (seg_data),
.seg_data_0 ({1'b1,7'b1111_111}),
.seg_data_1 ({1'b1,7'b1111_111}),
.seg_data_2 ({1'b1,7'b1111_111}),
.seg_data_3 ({1'b1,7'b1111_111}),
.seg_data_4 ({1'b1,seg_data_1}),
.seg_data_5 ({1'b1,seg_data_0})
);
endmodule
count_m10.v
module count_m10(
input clk,
input rst_n,
input en, //Counter enable
input clr, //Counter synchronous reset
output reg[3:0]data, //counter value
output reg t // carry enable signal
);
always@(posedge clk or negedge rst_n)
begin
if(rst_n==0)
begin
data <= 4'd0;
t <= 1'd0;
end
else if(clr)
begin
data <= 4'd0;
t <= 1'd0;
end
else if(en)
begin
if(data==4'd9)
begin
t<= 1'b1; //Counter to 9 to generate carry
data <= 4'd0;//Counter to 9 reset
end
else
begin
t <= 1'b0;
data <= data + 4'd1;
end
end
else
t <= 1'b0;
end
endmodule
ax_debounce.v
`timescale 1 ns / 100 ps
module ax_debounce
(
input clk,
input rst,
input button_in,
output reg button_posedge,
output reg button_negedge,
output reg button_out
);
---------------- internal constants --------------
parameter N = 32 ; // debounce timer bitwidth
parameter FREQ = 50; //model clock :Mhz
parameter MAX_TIME = 20; //ms
localparam TIMER_MAX_VAL = MAX_TIME * 1000 * FREQ;
---------------- internal variables ---------------
reg [N-1 : 0] q_reg; // timing regs
reg [N-1 : 0] q_next;
reg DFF1, DFF2; // input flip-flops
wire q_add; // control flags
wire q_reset;
reg button_out_d0;
------------------------------------------------------
contenious assignment for counter control
assign q_reset = (DFF1 ^ DFF2); // xor input flip flops to look for level chage to reset counter
assign q_add = ~(q_reg == TIMER_MAX_VAL); // add to counter when q_reg msb is equal to 0
combo counter to manage q_next
always @ ( q_reset, q_add, q_reg)
begin
case( {q_reset , q_add})
2'b00 :
q_next <= q_reg;
2'b01 :
q_next <= q_reg + 1;
default :
q_next <= { N {1'b0} };
endcase
end
Flip flop inputs and q_reg update
always @ ( posedge clk or posedge rst)
begin
if(rst == 1'b1)
begin
DFF1 <= 1'b0;
DFF2 <= 1'b0;
q_reg <= { N {1'b0} };
end
else
begin
DFF1 <= button_in;
DFF2 <= DFF1;
q_reg <= q_next;
end
end
counter control
always @ ( posedge clk or posedge rst)
begin
if(rst == 1'b1)
button_out <= 1'b1;
else if(q_reg == TIMER_MAX_VAL)
button_out <= DFF2;
else
button_out <= button_out;
end
always @ ( posedge clk or posedge rst)
begin
if(rst == 1'b1)
begin
button_out_d0 <= 1'b1;
button_posedge <= 1'b0;
button_negedge <= 1'b0;
end
else
begin
button_out_d0 <= button_out;
button_posedge <= ~button_out_d0 & button_out;
button_negedge <= button_out_d0 & ~button_out;
end
end
endmodule
count_m6.v
module count_m6(
input clk,
input rst_n,
input en, //Counter enable
input clr, //Counter synchronous reset
output reg[3:0]data, //counter value
output reg t // carry enable signal
);
always@(posedge clk or negedge rst_n)
begin
if(rst_n==0)
begin
data <= 4'd0;
t <= 1'd0;
end
else if(clr)
begin
data <= 4'd0;
t <= 1'd0;
end
else if(en)
begin
if(data==4'd5)
begin
t<= 1'b1; //Counter to 5 to generate carry
data <= 4'd0;//Counter to 5 reset
end
else
begin
t <= 1'b0;
data <= data + 4'd1;
end
end
else
t <= 1'b0;
end
endmodule