2021寒假一起练项目4——宋雨晴
该项目基于小脚丫FPGA的综合技能训练板制作一个能够计时、测温、定时报警、串口控制的系统
标签
FPGA
显示
网络与通信
SYQ
更新2021-02-25
926

项目需求

      该项目基于小脚丫FPGA的综合技能训练板,制作一个能够计时、测温、定时报警、串口控制的系统,具体功能如下:

  1. 实现一个可定时时钟的功能,用小脚丫FPGA核心模块的4个按键设置当前的时间,OLED显示数字钟的当前时间,精确到分钟即可,到整点的时候比如8:00,蜂鸣器报警,播放音频信号,最长可持续30秒;
  2. 实现温度计的功能,小脚丫通过板上的温度传感器实时测量环境温度,并同时间一起显示在OLED的屏幕上;
  3. 定时时钟整点报警的同时,将温度信息通过UART传递到电脑上,电脑上能够显示当前板子上的温度信息(任何显示形式都可以),要与OLED显示的温度值一致;
  4. PC收到报警的温度信号以后,将一段音频文件(自己制作,持续10秒钟左右)通过UART发送给小脚丫FPGA,蜂鸣器播放收到的这段音频文件,OLED屏幕上显示的时间信息和温度信息都停住不再更新;
  5. 音频文件播放完毕,OLED开始更新时间信息和当前的温度信息

设计思路

      使用板载的12MHz时钟、温度传感器、OLED显示屏、按键、蜂鸣器和uart串口完成该项目,总体框图如下:

图1  总体设计框图

图1  总体设计框图

      分频产生不同频率的时钟信号输出到各个模块,通过1s的时钟进行计时,四个按键控制显示的时间,通过DS18B20Z芯片测温并转换成摄氏度,并把时间和温度输出到OLED显示出来;在整点时,输出一个脉冲到串口发送模块,通过uart发送温度信息到PC;在整点或接收到PC的数据时,通过PWM信号驱动蜂鸣器模块响,播放相应的音乐。

实现方式

      1. 用计数的方式产生时钟,以12M的频率计数,每计满n次,输出发生翻转,则输出频率为12M/(n×2),以此产生所需要的时钟,以产生1MHz的时钟为例:

module clk_1MHz(clk,clk_1MHz);
input clk;
output clk_1MHz;
reg clk_1MHz;
reg[2:0] num;
always @(posedge clk)
    begin
	 if(num < 6)
	     num = num+1;
	 else
	     begin
		  clk_1MHz = ~clk_1MHz;
		  num = 0;
		  end
	 end
endmodule

      2. 使用FPGA驱动底板上的DS18B20Z单总线温度传感器进行温度数据的采集,输出16位的温度数据,将其转换为摄氏度的方法为:前5位为标志位,为1表示温度<0,为0表示温度>0,温度>0的情况下,后11位转化为十进制后乘以0.0625即用摄氏度表示的温度。温度采集的代码如下:

module temperature(clk,rst,bus,data_out);
localparam	IDLE	=	3'd0;
localparam	MAIN	=	3'd1;
localparam	INIT	=	3'd2;
localparam	WRITE	=	3'd3;
localparam	READ	=	3'd4;
localparam	DELAY	=	3'd5;
input clk;            //1MHz时钟
input rst;
inout bus;            //DS18B20Z传感器单总线,双向管脚
output[15:0] data_out;//DS18B20Z有效温度数据输出
reg[15:0] data_out;
reg bus_output;
reg io_link;

reg[3:0] cnt_main;
reg[7:0] data_wr;
reg[7:0] data_wr_buffer;
reg[2:0] cnt_init;
reg[19:0] cnt_delay,num_delay;
reg[5:0] cnt_write,cnt_read;
reg[15:0] temperature;
reg[7:0] temperature_buffer;
reg[2:0] state,state_back;

initial
    begin
	 state = IDLE;
	 state_back = IDLE;
	 end

assign
    bus = io_link?bus_output:1'bz;
	 
always @(posedge clk or negedge rst)
    begin
	 if(!rst)
	     begin
		  state <= IDLE;
		  state_back <= IDLE;
		  cnt_main <= 4'd0;
		  cnt_init <= 3'd0;
		  cnt_write <= 6'd0;
		  cnt_read <= 6'd0;
		  cnt_delay <= 20'd0;
		  io_link <= 1'b0;
		  temperature <= 16'h0;
		  end
    else
	     begin
		  case(state)
		      IDLE:
				begin
				state <= MAIN;
				state_back <= MAIN;
				cnt_main <= 4'd0;
				cnt_init <= 3'd0;
				cnt_write <= 6'd0;
				cnt_read <= 6'd0;
				cnt_delay <= 20'd0;
				io_link <= 1'b0;
				end
				MAIN:
				begin
				if(cnt_main >= 11)
				    cnt_main <= 0;
				else
				    cnt_main <= cnt_main+1;
				case(cnt_main)
				    4'd0:
					 begin
					 state <= INIT;
					 end
					 4'd1:
					 begin
					 data_wr <= 8'hcc;
					 state <= WRITE;
					 end
					 4'd2:
					 begin
					 data_wr <= 8'h44;
					 state <= WRITE;
					 end
					 4'd3:
					 begin
					 num_delay <= 20'd750000;
					 state <= DELAY;
					 state_back <= MAIN;
					 end
					 4'd4:
					 begin
					 state <= INIT;
					 end
					 4'd5:
					 begin
					 data_wr <= 8'hcc;
					 state <= WRITE;
					 end
					 4'd6:
					 begin
					 data_wr <= 8'hbe;
					 state <= WRITE;
					 end
					 4'd7:
					 begin
					 state <= READ;
					 end
					 4'd8:
					 begin
					 temperature[7:0] <= temperature_buffer;
					 end
					 4'd9:
					 begin
					 state <= READ;
					 end
					 4'd10:
					 begin
					 temperature[15:8] <= temperature_buffer;
					 end
					 4'd11:
			       begin
			       state <= IDLE;
			       data_out <= temperature;
			       end
			       default:
			       state <= IDLE;
            endcase
            end
            INIT:
	         begin
				if(cnt_init >= 3'd6)
				    cnt_init <= 0;
				else
				    cnt_init <= cnt_init+1;
				case(cnt_init)
				    3'd0:
					 begin
					 io_link <= 1;
					 bus_output <= 0;
					 end
					 3'd1:
					 begin
					 num_delay <= 20'd500;
					 state <= DELAY;
					 state_back <= INIT;
					 end
					 3'd2: 
					 begin 
					 io_link = 0; 
					 end
					 3'd3: 
					 begin 
					 num_delay <= 20'd100;
					 state <= DELAY;
					 state_back <= INIT; 
					 end
					 3'd4: 
					 begin 
					 if(bus) 
					     state <= IDLE; 
					 else 
					     state <= INIT; 
					 end
					 3'd5: 
					 begin 
					 num_delay <= 20'd400;
					 state <= DELAY;
					 state_back <= INIT; 
					 end
					 3'd6: 
					 begin 
					 state <= MAIN; 
					 end
					 default: 
					 state <= IDLE;
				endcase
				end
				WRITE:
				begin
				if(cnt_write >= 6'd50) 
				    cnt_write <= 1'b0;
				else 
				    cnt_write <= cnt_write + 1'b1;
				case(cnt_write)
				    6'd0: 
					 begin 
					 data_wr_buffer <= data_wr; 
					 end
					 //bit0
					 6'd1: 
					 begin 
					 io_link <= 1;
					 bus_output <= 0; 
					 end
					 6'd2: 
					 begin 
					 num_delay <= 20'd2;
					 state <= DELAY;
					 state_back <= WRITE; 
					 end
					 6'd3: 
					 begin 
					 bus_output <= data_wr_buffer[0]; 
					 end
					 6'd4: 
					 begin 
					 num_delay <= 20'd80;
					 state <= DELAY;
					 state_back <= WRITE; 
					 end
					 6'd5: 
					 begin 
					 io_link <= 0; 
					 end
					 6'd6:
					 begin
					 num_delay <= 20'd2;
					 state <= DELAY;
					 state_back <= WRITE;
					 end
					 //bit1
					 6'd7: 
					 begin
                io_link <= 1;
					 bus_output <= 0;
					 end
					 6'd8:
					 begin
					 num_delay <= 20'd2;
					 state <= DELAY;
					 state_back <= WRITE;
					 end
					 6'd9:
					 begin
					 bus_output <= data_wr_buffer[1]; 
					 end
					 6'd10: 
					 begin 
					 num_delay <= 20'd80;
					 state <= DELAY;
					 state_back <= WRITE;
					 end
					 6'd11: 
					 begin 
					 io_link <= 0; 
					 end
					 6'd12: 
					 begin 
					 num_delay <= 20'd2;
					 state <= DELAY;
					 state_back <= WRITE;
					 end
					 //bit2
					 6'd13: 
					 begin 
					 io_link <= 1;
					 bus_output <= 0; 
					 end
					 6'd14: 
					 begin 
					 num_delay <= 20'd2;
					 state <= DELAY;
					 state_back <= WRITE; 
					 end
					 6'd15: 
					 begin 
					 bus_output <= data_wr_buffer[2]; 
					 end
					 6'd16: 
					 begin 
					 num_delay <= 20'd80;
					 state <= DELAY;
					 state_back <= WRITE; 
					 end
					 6'd17: 
					 begin 
					 io_link  <= 0; 
					 end
					 6'd18:
					 begin
					 num_delay <= 20'd2;
					 state <= DELAY;
					 state_back <= WRITE;
					 end
					 //bit3
					 6'd19: 
					 begin 
					 io_link <= 1;
					 bus_output <= 0; 
					 end
					 6'd20: 
					 begin 
					 num_delay <= 20'd2;
					 state <= DELAY;
					 state_back <= WRITE; 
					 end
					 6'd21: 
					 begin 
					 bus_output <= data_wr_buffer[3];
					 end
					 6'd22:
					 begin
					 num_delay <= 20'd80;
					 state <= DELAY;
					 state_back <= WRITE; 
					 end
					 6'd23:
					 begin 
					 io_link  <= 0; 
					 end
					 6'd24: 
					 begin 
					 num_delay <= 20'd2;
					 state <= DELAY;
					 state_back <= WRITE; 
					 end
					 //bit4
					 6'd25: 
					 begin 
					 io_link <= 1;
					 bus_output <= 0; 
					 end
					 6'd26:
					 begin num_delay <= 20'd2;
					 state <= DELAY;
					 state_back <= WRITE;
					 end
					 6'd27: 
					 begin
					 bus_output <= data_wr_buffer[4];
					 end
					 6'd28:
					 begin
					 num_delay <= 20'd80;
					 state <= DELAY;
					 state_back <= WRITE;
					 end
					 6'd29:
					 begin
					 io_link <= 0;
					 end
					 6'd30:
					 begin
					 num_delay <= 20'd2;
					 state <= DELAY;
					 state_back <= WRITE;
					 end
					 //bit5
					 6'd31: 
					 begin
					 io_link <= 1;
					 bus_output <= 0; 
					 end
					 6'd32: 
					 begin 
					 num_delay <= 20'd2;
					 state <= DELAY;
					 state_back <= WRITE; 
					 end
					 6'd33: 
					 begin 
					 bus_output <= data_wr_buffer[5]; 
					 end
					 6'd34: 
					 begin 
					 num_delay <= 20'd80;
					 state <= DELAY;
					 state_back <= WRITE; 
					 end
					 6'd35: 
					 begin 
					 io_link <= 0; 
					 end
					 6'd36:
					 begin 
					 num_delay <= 20'd2;
					 state <= DELAY;
					 state_back <= WRITE; 
					 end
					 //bit6
					 6'd37: 
					 begin 
					 io_link <= 1;
					 bus_output <= 0;
					 end
					 6'd38:
					 begin
					 num_delay <= 20'd2;
					 state <= DELAY;
					 state_back <= WRITE;
					 end
					 6'd39:
					 begin 
					 bus_output <= data_wr_buffer[6]; 
					 end
					 6'd40: 
					 begin 
					 num_delay <= 20'd80;
					 state <= DELAY;
					 state_back <= WRITE; 
					 end
					 6'd41: 
					 begin 
					 io_link <= 0; 
					 end
					 6'd42:
					 begin
					 num_delay <= 20'd2;
					 state <= DELAY;
					 state_back <= WRITE;
					 end
					 //bit7
					 6'd43: 
					 begin 
					 io_link <= 1;
					 bus_output <= 0;
					 end
					 6'd44:
					 begin num_delay <= 20'd2;
					 state <= DELAY;
					 state_back <= WRITE;
					 end
					 6'd45:
					 begin
					 bus_output <= data_wr_buffer[7];
					 end
					 6'd46:
					 begin
					 num_delay <= 20'd80;
					 state <= DELAY;
					 state_back <= WRITE; 
					 end
					 6'd47:
					 begin
					 io_link  <= 0;
					 end
					 6'd48:
					 begin
					 num_delay <= 20'd2;
					 state <= DELAY;
					 state_back <= WRITE;
					 end
					 //
					 6'd49: 
					 begin 
					 num_delay <= 20'd80;
					 state <= DELAY;
					 state_back <= WRITE; 
					 end
					 6'd50:
					 begin state <= MAIN;
					 end
					 default:
					 state = IDLE;
            endcase
				end
				READ:
				begin
				if(cnt_read >= 6'd48) 
				    cnt_read <= 1'b0;
				else 
				    cnt_read <= cnt_read + 1'b1;
				case(cnt_read)
				    //read bit 0
					 6'd0:
					 begin
					 io_link <= 1;
					 bus_output <= 0;
					 end
					 6'd1:
					 begin
					 num_delay <= 20'd2;
					 state <= DELAY;
					 state_back <= READ;
					 end
					 6'd2: 
					 begin 
					 io_link <= 0; 
					 end
					 6'd3: 
					 begin 
					 num_delay <= 20'd10;
					 state <= DELAY;
					 state_back <= READ; 
					 end
					 6'd4: 
					 begin 
					 temperature_buffer[0] <= bus; 
					 end
					 6'd5:
					 begin num_delay <= 20'd55;
					 state <= DELAY;
					 state_back <= READ;
					 end
					 //read bit 1
					 6'd6: 
					 begin 
					 io_link <= 1;
					 bus_output <= 0;
					 end
					 6'd7: 
					 begin 
					 num_delay <= 20'd2;
					 state <= DELAY;
					 state_back <= READ; 
					 end
				 	 6'd8: 
					 begin 
					 io_link <= 0; 
					 end
					 6'd9: 
					 begin 
					 num_delay <= 20'd10;
					 state <= DELAY;
					 state_back <= READ; 
					 end
					 6'd10: 
					 begin 
					 temperature_buffer[1] <= bus; 
					 end
					 6'd11: 
					 begin 
					 num_delay <= 20'd55;
					 state <= DELAY;
					 state_back <= READ; 
					 end
					 //read bit 2
					 6'd12: 
					 begin 
					 io_link <= 1;
					 bus_output <= 0; 
					 end
					 6'd13: 
					 begin 
					 num_delay <= 20'd2;
					 state <= DELAY;
					 state_back <= READ; 
					 end
					 6'd14: 
					 begin 
					 io_link <= 0; 
					 end
					 6'd15: 
					 begin 
					 num_delay <= 20'd10;
					 state <= DELAY;
					 state_back <= READ; 
					 end
					 6'd16: 
					 begin 
					 temperature_buffer[2] <= bus; 
					 end
					 6'd17: 
					 begin num_delay <= 20'd55;
					 state <= DELAY;
					 state_back <= READ; 
					 end
					 //read bit 3
					 6'd18: 
					 begin 
					 io_link <= 1;
					 bus_output <= 0;  
					 end
					 6'd19: 
					 begin 
					 num_delay <= 20'd2;
					 state <= DELAY;
					 state_back <= READ; 
					 end
					 6'd20: 
					 begin 
					 io_link <= 0; 
					 end
					 6'd21: 
					 begin 
					 num_delay <= 20'd10;
					 state <= DELAY;
					 state_back <= READ; 
					 end
					 6'd22: 
					 begin 
					 temperature_buffer[3] <= bus; 
					 end
					 6'd23: 
					 begin 
					 num_delay <= 20'd55;
					 state <= DELAY;
					 state_back <= READ; 
					 end
					 //read bit 4
					 6'd24:
					 begin
					 io_link <= 1;
					 bus_output <= 0;   
					 end
					 6'd25:
					 begin
					 num_delay <= 20'd2;
					 state <= DELAY;
					 state_back <= READ; 
					 end
					 6'd26:
					 begin
					 io_link <= 0; 
					 end
					 6'd27:
					 begin
					 num_delay <= 20'd10;
					 state <= DELAY;
					 state_back <= READ; 
					 end
					 6'd28:
					 begin
					 temperature_buffer[4] <= bus; 
					 end
					 6'd29:
					 begin
					 num_delay <= 20'd55;
					 state <= DELAY;
					 state_back <= READ;
					 end
					 //read bit 5
					 6'd30:
					 begin
					 io_link <= 1;
					 bus_output <= 0;
					 end
					 6'd31:
					 begin
					 num_delay <= 20'd2;
					 state <= DELAY;
					 state_back <= READ;
					 end
					 6'd32:
					 begin
					 io_link <= 0;
					 end
					 6'd33:
					 begin
					 num_delay <= 20'd10;
					 state <= DELAY;
					 state_back <= READ;
					 end
					 6'd34:
					 begin
					 temperature_buffer[5] <= bus; 
					 end
					 6'd35:
					 begin
					 num_delay <= 20'd55;
					 state <= DELAY;
					 state_back <= READ;
					 end
					 //read bit 6
					 6'd36:
					 begin
					 io_link <= 1;
					 bus_output <= 0;
					 end
					 6'd37: 
					 begin 
					 num_delay <= 20'd2;
					 state <= DELAY;
					 state_back <= READ; 
					 end
					 6'd38: 
					 begin 
					 io_link <= 0; 
					 end
					 6'd39: 
					 begin 
					 num_delay <= 20'd10;
					 state <= DELAY;
					 state_back <= READ; 
					 end
					 6'd40: 
					 begin 
					 temperature_buffer[6] <= bus; 
					 end
					 6'd41: 
					 begin 
					 num_delay <= 20'd55;
					 state <= DELAY;
					 state_back <= READ; 
					 end
					 //read bit 7
					 6'd42:
					 begin
					 io_link <= 1;
					 bus_output <= 0;
					 end
					 6'd43:
					 begin
					 num_delay <= 20'd2;
					 state <= DELAY;
					 state_back <= READ;
					 end
					 6'd44:
					 begin
					 io_link <= 1;
					 end
					 6'd45:
					 begin
					 num_delay <= 20'd10;
					 state <= DELAY;
					 state_back <= READ;
					 end
					 6'd46:
					 begin
					 temperature_buffer[7] <= bus; 
					 end
					 6'd47: 
					 begin 
					 num_delay <= 20'd55;
					 state <= DELAY;
					 state_back <= READ;
					 end
					 //back to main
					 6'd48:
					 begin
					 state <= MAIN;
					 end
					 default:
					 state <= IDLE;
            endcase
				end
				DELAY:
				begin
				if(cnt_delay >= num_delay) 
				    begin
					 cnt_delay <= 1'b0;
					 state <= state_back; 
					 end
				else
				    cnt_delay <= cnt_delay + 1'b1;
				end
        endcase
		  end
    end
endmodule

      3. 通过USB端口来进行UART数据的传输,采用异步协议,数据的发送是这样处理的:

      ①收、发两端采用事先约定好的同样的通信参数(速率、格式。。。),这要在通信之前手动设定;

      ②只要是线路闲置,发送端就发出“idle” (=“1”);
      ③每一次要发送一个字节的数据,发送端都要先发一个“start” (=“0”),这样接收端就可以判别出有一个字节要来了;
      ④然后发送一个字节的8个位;
      ⑤每发完一个字节以后发送端就发“stop” (=“1”);
      数据的接收是这样处理的:从RxD线上收集数据,当接收到一个字节时,它出现在“数据”总线上,一旦接收到一个完整的字节,“dataready”就会被拉高一个时钟,此时“data”才有效。UART通信的代码如下:
//串口发送程序
module uart_tx(tem_0,tem_1,clk,en,uart_out);
localparam IDLE = 2'b0;
localparam SEND = 2'b1;
input[7:0] tem_0,tem_1;
input clk,en;
output uart_out;
reg uart_out,flag_1,flag_2,state;
reg[101:0] uart_data;
reg[7:0] tab[9:0];
reg[6:0] i;

initial
    begin
	 tab[0] = 8'h30;
	 tab[1] = 8'h31;
	 tab[2] = 8'h32;
	 tab[3] = 8'h33;
	 tab[4] = 8'h34;
	 tab[5] = 8'h35;
	 tab[6] = 8'h36;
	 tab[7] = 8'h37;
	 tab[8] = 8'h38;
	 tab[9] = 8'h39;
	 uart_data = 1;
	 flag_1 = 0;
	 flag_2 = 0;
	 i = 0;
	 state = IDLE;
	 end
always @(posedge en)
    begin
	 uart_data = {1'd1,8'h43,1'd0,1'd1,8'he3,1'd0,1'd1,8'ha1,1'd0,1'd1,tab[tem_0],1'd0,1'd1,tab[tem_1],1'd0,
	              1'd1,8'h3a,1'd0,1'd1,8'h70,1'd0,1'd1,8'h6d,1'd0,1'd1,8'h65,1'd0,1'd1,8'h54,1'd0,1'd1,1'd1};
	//1'd1,8'h20,1'd0,1'd1,8'h43,1'd0,1'd1,8'ha1,1'd0, 
	 flag_1 = ~flag_1;
	 end
always @(posedge clk)
    begin
	 case(state)
	     IDLE:
	     if(flag_2 != flag_1)
		      begin
				flag_2 = flag_1;
				state = SEND;
				end
		  SEND:
		  if(i < 102)
		      begin
				uart_out = uart_data[i];
				i = i+1;
				end
		  else
		      begin
				i = 0;
				state = IDLE;
				end
    endcase
	 end
endmodule

//串口接收程序
module uart_rx(uart_in,clk,receive,tri_uart);
localparam IDLE = 2'b00;
localparam CHEC = 2'b01;
localparam RECE = 2'b11;
localparam TIMES = 1250;
input uart_in,clk;
output tri_uart;
output[231:0] receive;
reg[231:0] receive;
reg[1:0] state;
reg[10:0] times,times_zero;
reg[3:0] num;
reg[5:0] B;
reg tri_uart;
initial
    begin
    times = 0;
	 times_zero = 0;
	 state = 0;
	 num = 0;
	 B = 0;
	 receive = 0;
	 end
always @(posedge clk)
    begin
	 if(tri_uart == 1)
	     tri_uart = 0;
	 case(state)
	     IDLE:
		  begin
		  if(uart_in == 0)
				state = CHEC;
		  end
		  CHEC:
		  begin
		  if(uart_in == 0)
		      times_zero = times_zero+1;
		  times = times+1;
		  if(times >= TIMES)
		      begin
				if(times_zero >= (TIMES>>1))
				    begin
					 state = RECE;
					 times = 0;
					 times_zero = 0;
					 end
			   else
				    begin
					 state = IDLE ;
					 times = 0;
					 times_zero = 0;
					 end
				end
        end
		  RECE:
		  begin
		  times = times+1;
		  if(uart_in == 0)
		      begin
				times_zero = times_zero+1;
				end
		  if(times >= TIMES)
		      begin
				if(times_zero >= (TIMES>>1))
				    begin
					 receive[B*8+num] = 0;
					 end
				else
				    begin
					 receive[B*8+num] = 1;
					 end
				num = num+1;
				times = 0;
				times_zero = 0;
			   end
		  if(num > 7)
			   begin
				state = IDLE;
				num = 0;
				times = 0;
				times_zero = 0;
				if(B > 27)
				    begin
				    B = 0;
					 tri_uart = 1;
					 end
				else
				    B = B+1;
				end
        end
    endcase
	 end
endmodule
      4. OLED的显示:输入clk为时钟信号,rst为复位信号,hour为小时数据,min为分钟数据,tem为温度数据,输出csn,rst,dcn,clk,dat 5个信号控制OLED的显示,在MAIN状态下显示,INIT为初始化状态,SCAN为刷屏状态,WRITE为写状态,将数据按照SPI时序发送给屏幕。
      5. 蜂鸣器模块:通过PWM信号控制蜂鸣器发声的频率,在整点报时时,通过预设的一段数据控制蜂鸣器发出“L6 L7 M1 M3 M6”的声音,通过PC传来的数据控制蜂鸣器发出天空之城的一段音乐。
//tri_time整点脉冲  用于报警
//tri_uart上位机脉冲  用于报警
//data_uart接收到的数据
//clk系统时钟12M
//clk_buzzer 0.2s时钟
//out输出到蜂鸣器
module buzzer(tri_time,tri_uart,data_uart,clk,clk_buzzer,stop,out);
input tri_time,tri_uart,clk,clk_buzzer;
input[231:0] data_uart;
output stop,out;
localparam size = 29;
localparam IDLE = 2'b00;
localparam LOAD_1 = 2'b01;
localparam LOAD_2 = 2'b10;
localparam MAIN = 2'b11;
reg stop,out;
reg[3:0] tone;
reg[5:0] num;
reg[15:0] time_end;
reg[17:0] time_cnt;
reg[size*8-1:0] music;
reg[1:0] state;
reg flag_1,flag_2;
reg[2:0] judge;
reg[23:0] num_delay;
initial
    begin
	 stop = 1;
	 music = 0;
	 flag_1 = 0;
	 flag_2 = 0;
	 num = size-1;
	 time_cnt = 0;
	 state = 2'b00;
	 end
always @(posedge clk_buzzer)
    begin
	 case(state)
	     IDLE:
		  begin
		  music = 0;
		  case(judge)
		      2'b01:state = LOAD_1;
				2'b10:state = LOAD_2;
				default:state = IDLE;
		  endcase
		  end
	     LOAD_1://整点报警
		  begin
		  music = 120'h0606070708080a0a0d0d00;//16进制  1234567
		  num = 12;//14个音符+末尾两个0
		  state = MAIN;
		  end
		  LOAD_2://uart接收到音乐数据后报警
		  begin
		  music = data_uart;
		  num = 28;//28个音符+末尾两个0
		  state = MAIN;
		  stop = 0;
		  end
		  MAIN:
		  begin
		  
	     if(num == 0)
		      begin
	         num <= 0;
				state <= IDLE;
				stop <= 1; 
				end
		  else
		      begin
		      tone <= music[num*8+:8];
	         num <= num - 1;
				end
		  end
		  default:state = IDLE;
    endcase
	 end
always @(posedge clk)
    begin
	 case(tone)
	     5'd1:	time_end =	16'd22935;	//L1,01
		  5'd2:	time_end =	16'd20428;	//L2,02
		  5'd3:	time_end =	16'd18203;	//L3,03
		  5'd4:	time_end =	16'd17181;	//L4,04
		  5'd5:	time_end =	16'd15305;	//L5,05
		  5'd6:	time_end =	16'd13635;	//L6,06
		  5'd7:	time_end =	16'd12147;	//L7,07
		  5'd8:	time_end =	16'd11464;	//M1,08
		  5'd9:	time_end =	16'd10215;	//M2,09
		  5'd10:	time_end =	16'd9100;	//M3,0a
		  5'd11:	time_end =	16'd8589;	//M4,0b
		  5'd12:	time_end =	16'd7652;	//M5,0c
		  5'd13:	time_end =	16'd6817;	//M6,0d
		  5'd14:	time_end =	16'd6073;	//M7,0e
		  5'd15:	time_end =	16'd5740;	//H1,0f
		  5'd16:	time_end =	16'd5107;	//H2,11
		  5'd17:	time_end =	16'd4549;	//H3,12
		  5'd18:	time_end =	16'd4294;	//H4,13
		  5'd19:	time_end =	16'd3825;	//H5,14
		  5'd20:	time_end =	16'd3408;	//H6,15
		  5'd21:	time_end =	16'd3036;	//H7,16
		  default: time_end = 16'd0;
	 endcase
	 if(time_end == 0||num == 0)
	     out <= 0;
	 else if(time_cnt >= time_end) //蜂鸣器发声
	     begin
		  out <= ~out;
		  time_cnt <= 0;
		  end
	 else
	     time_cnt <= time_cnt + 1;
	 end
always @(posedge clk)
    begin
	 if(num_delay != 0)
	     begin
		  num_delay = num_delay - 1;
		  end
	 else
	     begin
		  judge[0] = tri_time;
		  judge[1] = tri_uart;
		  if(judge != 0)
		      num_delay = 7000000;
		  else
		      num_delay = 0;
		  end
    end
endmodule
		  
 
资源占用情况
 
      如下图所示,该项目共占用2226个逻辑单元、692个寄存器、14个引脚,由于判断语句、if语句、组合逻辑等用的较多,使得逻辑单元和寄存器占用较多。
图2  资源占用情况
图2  资源占用情况
 
总结与体会
 
      项目已基本完成,在做项目的过程中,遇到了软件编程不熟练、不熟悉OLED显示、uart通信的困难,通过查找数据手册和代码示例解决了困难,学到了很多,提起了兴趣,受益匪浅!
      在有需要时,我希望在计时和测温的功能上进行改进,在整点报警时不停止时间和温度的更新,这样该系统就可以作为一个更加精准的电子表来使用。
 
附件下载
FPGA_project.rar
完整的设计文件
团队介绍
哈尔滨工业大学 电信学院
团队成员
宋雨晴
探索中... ...
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号