2021寒假在家练项目——刘腾渊
2021年利用寒假时间,使用小脚丫平台对FPGA进行学习与开发,实现了可计时、控制、测温、报警的一个小项目
标签
嵌入式系统
FPGA
数字逻辑
GoTimeZ
更新2021-03-09
931

项目的功能目标:

  

  1. 实现一个可定时时钟的功能,用小脚丫FPGA核心模块的4个按键设置当前的时间,OLED显示数字钟的当前时间,精确到分钟即可,到整点的时候比如8:00,蜂鸣器报警,播放音频信号,最长可持续30秒;

  2. 实现温度计的功能,小脚丫通过板上的温度传感器实时测量环境温度,并同时间一起显示在OLED的屏幕上;

  3. 定时时钟整点报警的同时,将温度信息通过UART传递到电脑上,电脑上能够显示当前板子上的温度信息(任何显示形式都可以),要与OLED显示的温度值一致;

  4. PC收到报警的温度信号以后,将一段音频文件(自己制作,持续10秒钟左右)通过UART发送给小脚丫FPGA,蜂鸣器播放收到的这段音频文件,OLED屏幕上显示的时间信息和温度信息都停住不再更新;(视频中忘记展示了)

  5. 音频文件播放完毕,OLED开始更新时间信息和当前的温度信息

项目设想:

   每一个模块首先应当有自己的封装,然后用更加上级的模块对这些底层的封装进行调用,在代码上尽量简洁。

   使用状态机的编写方法,精准的掌握各种时序,避免数据上的错误。

   尽量整合重复的语句,避免资源过多的浪费。

Fj66taUN_4gaFnQv5GlDInYLAlba

大体架构

FuEKUZ3MaVdFHzlXxJEzH4wspoX-

引脚图

FsS19FIr0MjtvZ3h6nJTRJhMZLnL

资源报告

代码展示:

时钟分频,通过对clk_p和clk_n与运算得到正确的时钟信号。

module MyClkDevide(clk, rst_n, clk_out);
	input clk;
	input rst_n;
	output clk_out;
	
	parameter width = 1;
	parameter n = 1;
	
	reg [width-1:0] cnt_p, cnt_n;
	reg clk_p, clk_n;
	
	initial
	begin
		clk_p <= 0;
		clk_n <= 0;
	end
	
	always @ (posedge clk or negedge rst_n)
	begin
		if(!rst_n)
			cnt_p = 0;
		else if (cnt_p == n - 1)
			cnt_p = 0;
		else
			cnt_p = cnt_p + 1;

		if(!rst_n)
			clk_p <= 0;	
		else if(cnt_p < n >> 1)
			clk_p <= 0;
		else
			clk_p <= 1;
	end
	
	always @ (negedge clk or negedge rst_n)
	begin
		if(!rst_n)
			cnt_n = 0;
		else if(cnt_n == n - 1)
			cnt_n = 0;
		else
			cnt_n = cnt_n + 1;
			
		if(!rst_n)
			clk_n <= 0;	
		else if(cnt_n < n >> 1)
			clk_n <= 0;
		else
			clk_n <= 1;
	end
	
	assign clk_out = n == 1 ? clk : clk_p & clk_n;
	
endmodule

 

MyClock模块,用于记录时间。该模块为上面模块的升级封装。

module MyClock(clk, rst_n, key1, key2, mytime, time_sig);
	input clk;
	input rst_n;
	input key1;
	input key2;
	output reg [15:0] mytime;
	output time_sig;
	
	MyClkDevide # (.width(24), .n(12000000)) u_clk (clk, rst_n, clk_out);
	
	reg [11:0] cnt;
	reg [7:0] second;
	reg [7:0] minute;
	reg [7:0] hour;
	
	initial
	begin
		mytime = 0;
		cnt = 0;
		second = 0;
		minute = 0;
		hour = 0;
	end
	
	always @ (posedge clk_out or negedge rst_n)
	begin
		if(!rst_n)
		begin
			mytime = 0;
			cnt = 0;
			second = 0;
			minute = 0;
			hour = 0;
		end
		else
		begin
			if(second == 59)
			begin
				second = 0;
				if(minute == 59)
				begin
					minute = 0;
					if(hour == 23)
						hour = 0;
					else
						hour = hour + 1;
				end
				else
					minute = minute + 1;
			end
			else
				second = second + 1;
				
			if(!key1)
				if(minute == 59)
					begin
						minute = 0;
						if(hour == 23)
							hour = 0;
						else
							hour = hour + 1;
					end
					else
						minute = minute + 1;
			
			if(!key2)
				if(hour == 23)
							hour = 0;
						else
							hour = hour + 1;
			
			mytime[15:12] = hour / 10;
			mytime[11:8] = hour % 10;
			mytime[7:4] = minute / 10;
			mytime[3:0] = minute % 10;
		end
	end
	
	assign time_sig = !second && !minute;
	
endmodule

 

MyPWM模块,同样也是简单的封装。

module MyPWM(clk, p_cnt, out);
	input clk;
	input [7:0] p_cnt;
	output out;
	
	parameter width = 8;
	parameter total_cnt = 100;
	
	reg [width-1:0] cnt;
	
	initial
		cnt = 0;
	
	always @ (posedge clk)
	begin
		if(cnt == total_cnt - 1)
			cnt = 0;
		else
			cnt = cnt + 1;
	end
	
	assign out = cnt < p_cnt ? 1 : 0;
	
endmodule
	

 

MyUartTX模块,相对于RX比较好写,只需要对应好时序即可。

module MyUartTX(clk, data_buffer, send_sig, rst_n, txport, busy);
	input clk;
	input [7:0] data_buffer;
	input send_sig;
	input rst_n;
	output reg txport;
	output reg busy;
	
	reg [3:0] cnt;
	reg state_r;
	
	initial
	begin
		txport = 1;
		cnt = 0;
		busy = 0;
		state_r = 0;
	end
	
	always @ (posedge clk or negedge rst_n)
	begin
		if(!rst_n)
		begin
			txport = 1;
			cnt = 0;
			busy = 0;
			state_r = 0;
		end
		else
		begin
			if(state_r != send_sig && send_sig)
				busy = 1;
			if(busy)
				case(cnt)
					0: begin txport = 0; cnt = cnt + 1; end
					9: begin txport = 1; cnt = 0; busy = 0; end
					default: begin txport = data_buffer[cnt-1]; cnt = cnt + 1; end
				endcase
			state_r = send_sig;
		end
	end

endmodule

 

接着是MyUartRX,因为需要采样的原因时钟频率比TX大。本示例是疯狂的1250次采样。

module MyUartRX(clk, rst_n, rxport, data_buffer, busy);
	input clk;
	input rst_n;
	input rxport;
	output reg [7:0] data_buffer;
	output reg busy;
	
	localparam Sampling = 2'b00;
	localparam Idle = 2'b01;
	localparam Read = 2'b10;
	
	reg [1:0] state;
	reg [1:0] state_r;
	
	reg [5:0] cnt;
	
	reg [11:0] s_cnt;
	reg [11:0] sampling;
	reg data;
	
	initial
	begin
		state = Sampling;
		state_r = Idle;
	
		cnt = 0;
		s_cnt = 0;
		sampling = 0;
		
		data = 0;
		
		busy = 0;
	end
	
	always @ (posedge clk or negedge rst_n)
	begin
		if(!rst_n)
		begin
			state = Sampling;
			state_r = Idle;
	
			cnt = 0;
			s_cnt = 0;
			sampling = 0;
			
			data = 0;
			
			busy = 0;
		end
		else
		begin
			case(state)
				Sampling:
					if(s_cnt < 1249)
					begin
						sampling = sampling + rxport;
						s_cnt = s_cnt + 1;
					end
					else
					begin
						sampling = sampling + rxport;
						state = state_r;
						s_cnt = 0;
						data = sampling >= 625;
						sampling = 0;
					end
				
				Read:
				begin
					case(cnt)
						8: begin state_r = Idle; cnt = 0; busy = 0; end
						default: begin data_buffer[cnt] = data; state_r = Read; cnt = cnt + 1; end
					endcase
					state = Sampling;
				end
				
				Idle:
				begin
					if(data == 0)
					begin
						state_r = Read;
						busy = 1;
					end
					state = Sampling;
				end
			endcase
		end
	end
endmodule

 

Uart之后的通讯协议都比较难,比如这个SPI(还算可以的吧)。记得上电时序,仔仔细细对着英文文档做,原版小脚丫因为有出厂程序所以对上电时序没啥要求。但是一旦抹除了出厂程序,你原来的上电时序可能会出问题。

module MyOLed(clk, rst_n, mytime, tempe, cs, dc, sdin, oledrst);
	input clk;
	input rst_n;
	input [15:0] mytime;
	input [11:0] tempe;
	output reg cs;
	output reg dc;
	output reg sdin;
	output reg oledrst;
	
	localparam Init = 3'b000;
	localparam Delay = 3'b001;
	localparam Write = 3'b010;
	localparam Main = 3'b011;
	localparam Character = 3'b100;
	localparam Clear = 3'b101;
	
	localparam CMD = 1'b0;
	localparam DATA = 1'b1;
	localparam CMD_NUM = 23;
	
	reg[39:0] mem[11:0];
	
	reg [7:0] cmd [CMD_NUM-1:0];
	reg [5:0] cmd_cnt;
	
	reg [2:0] state;
	reg [2:0] state_r;
	
	reg [3:0] init_cnt;
	
	reg [5:0] delay_num;
	reg [5:0] delay_cnt;
	
	reg [5:0] write_cnt;
	reg [7:0] write_buffer;
	reg write_mode;
	
	reg [5:0] main_cnt;
	
	reg [5:0] character_cnt;
	reg [3:0] character_num;
	
	reg [10:0] clear_cnt;
	
	initial
	begin
		oledrst = 1;
		
		state = Init;
		
		cmd_cnt = 0;
		init_cnt = 0;
		delay_cnt = 0;
		write_cnt = 0;
		main_cnt = 0;
		character_cnt = 0;
		
		cs = 1;
		 
		cmd[0] = 8'h00; 
		cmd[1] = 8'h10; 
		cmd[2] = 8'hb0; 
		
		cmd[3] = 8'h81; 
		cmd[4] = 8'hff; 
		
		cmd[5] = 8'ha1; 
		cmd[6] = 8'ha6; 
		cmd[7] = 8'ha8; 
		cmd[8] = 8'h1f; 
		
		cmd[9] = 8'hc8;
		
		cmd[10] = 8'hd3;
		cmd[11] = 8'h00;
		cmd[12] = 8'hd5;
		cmd[13] = 8'h80;
		cmd[14] = 8'hd9;
		cmd[15] = 8'h1f;
		
		cmd[16] = 8'hda;
		cmd[17] = 8'h00;
		
		cmd[18] = 8'hdb;
		cmd[19] = 8'h40;
		
		cmd[20] = 8'h8d;
		cmd[21] = 8'h14;
		
		cmd[22] = 8'haf;
		
		mem[0] = {8'h3E, 8'h51, 8'h49, 8'h45, 8'h3E};   //   0
		mem[1] = {8'h00, 8'h42, 8'h7F, 8'h40, 8'h00};   //   1
		mem[2] = {8'h42, 8'h61, 8'h51, 8'h49, 8'h46};   //   2
		mem[3] = {8'h21, 8'h41, 8'h45, 8'h4B, 8'h31};   //   3
		mem[4] = {8'h18, 8'h14, 8'h12, 8'h7F, 8'h10};   //   4
		mem[5] = {8'h27, 8'h45, 8'h45, 8'h45, 8'h39};   //   5
		mem[6] = {8'h3C, 8'h4A, 8'h49, 8'h49, 8'h30};   //   6
		mem[7] = {8'h01, 8'h71, 8'h09, 8'h05, 8'h03};   //   7
		mem[8] = {8'h36, 8'h49, 8'h49, 8'h49, 8'h36};   //   8
		mem[9] = {8'h06, 8'h49, 8'h49, 8'h29, 8'h1E};   //   9
		mem[10] = {8'h00, 8'h60, 8'h60, 8'h00, 8'h00};  //   .
		mem[11] = {8'h00, 8'h36, 8'h36, 8'h00, 8'h00};  //   :
	end
	
	always @ (negedge clk or negedge rst_n)
	begin
		if(!rst_n)
		begin
			oledrst = 1;
		
			state = Init;
		
			cmd_cnt = 0;
			init_cnt = 0;
			delay_cnt = 0;
			write_cnt = 0;
			main_cnt = 0;
			character_cnt = 0;
		
			cs = 1;
		end
		else
			case(state)
				Init:
				begin
					case(init_cnt)
						0: begin oledrst = 0; state = Delay; delay_num = 5; state_r = Init; init_cnt = init_cnt + 1; end
						1: begin oledrst = 1; state = Delay; delay_num = 5; state_r = Init; init_cnt = init_cnt + 1; end
						2: begin 
								write_mode = CMD; 
								if(cmd_cnt < CMD_NUM)
								begin
									write_buffer = cmd[cmd_cnt];
									state = Write;
									state_r = Init;
									if(cmd_cnt == CMD_NUM - 1)
									begin
										cmd_cnt = 0;
										init_cnt = init_cnt + 1;
									end
									cmd_cnt = cmd_cnt + 1;
								end
							end
						3: begin state = Main; init_cnt = 0; end
					endcase
				end
				
				Delay:
				begin
					if(delay_cnt == delay_num - 1)
					begin
						delay_cnt = 0;
						state = state_r;
					end
					else
						delay_cnt = delay_cnt + 1;
				end
				
				Write:
				begin
					case(write_cnt)
						0: begin cs = 0; dc = write_mode; sdin = write_buffer[7]; write_cnt = write_cnt + 1; end
						8: begin cs = 1; state = state_r; write_cnt = 0; end
						default: begin sdin = write_buffer[7-write_cnt]; write_cnt = write_cnt + 1; end
					endcase
				end
				
				Main:
				begin
					case(main_cnt)
						0: begin state = Write; write_mode = CMD; write_buffer = 8'h00; state_r = Main; main_cnt = main_cnt + 1; end
						1: begin state = Write; write_mode = CMD; write_buffer = 8'h10; state_r = Main; main_cnt = main_cnt + 1; end
						2: begin state = Write; write_mode = CMD; write_buffer = 8'hb0; state_r = Main; main_cnt = main_cnt + 1; end
						3: begin state = Clear; state_r = Main; main_cnt = main_cnt + 1; end
						4: begin state = Character; character_num = mytime[15:12]; main_cnt = main_cnt + 1; end
						5: begin state = Character; character_num = mytime[11:8]; main_cnt = main_cnt + 1; end
						6: begin state = Character; character_num = 11; main_cnt = main_cnt + 1; end
						7: begin state = Character; character_num = mytime[7:4]; main_cnt = main_cnt + 1; end
						8: begin state = Character; character_num = mytime[3:0]; main_cnt = main_cnt + 1; end
						9: begin state = Write; write_mode = CMD; write_buffer = 8'h00; state_r = Main; main_cnt = main_cnt + 1; end
						10: begin state = Write; write_mode = CMD; write_buffer = 8'h10; state_r = Main; main_cnt = main_cnt + 1; end
						11: begin state = Write; write_mode = CMD; write_buffer = 8'hb1; state_r = Main; main_cnt = main_cnt + 1; end
						12: begin state = Clear; state_r = Main; main_cnt = main_cnt + 1; end
						13: begin state = Character; character_num = tempe[11:8]; main_cnt = main_cnt + 1; end
						14: begin state = Character; character_num = tempe[7:4]; main_cnt = main_cnt + 1; end
						15: begin state = Character; character_num = tempe[3:0]; main_cnt = main_cnt + 1; end
						16: begin state = Main; main_cnt = 0; end
					endcase
				end
				
				Character:
				begin
					case(character_cnt)
						0: 
						begin 
							state = Write;
							state_r = Character; 
							write_mode = DATA; 
							write_buffer = mem[character_num][39:32];
							character_cnt = character_cnt + 1; 
						end
						1: 
						begin 
							state = Write;
							state_r = Character; 
							write_mode = DATA; 
							write_buffer = mem[character_num][31:24];
							character_cnt = character_cnt + 1; 
						end
						2: 
						begin 
							state = Write;
							state_r = Character; 
							write_mode = DATA; 
							write_buffer = mem[character_num][23:16];
							character_cnt = character_cnt + 1; 
						end
						3: 
						begin 
							state = Write;
							state_r = Character; 
							write_mode = DATA; 
							write_buffer = mem[character_num][15:8];
							character_cnt = character_cnt + 1; 
						end
						4: 
						begin 
							state = Write;
							state_r = Character; 
							write_mode = DATA; 
							write_buffer = mem[character_num][7:0];
							character_cnt = character_cnt + 1; 
						end
						5: begin state = Main; character_cnt = 0; end
						
					endcase
				end
				
				Clear:
					begin
						write_mode = DATA; 
						write_buffer = 8'h00;;
						state = Write;
						state_r = Clear;
						if(clear_cnt == 128)
						begin
							clear_cnt = 0;
							state = Main;
						end
						else
							clear_cnt = clear_cnt + 1;
					end
				
			endcase
	end
	
endmodule

 

剩下一个18B20,1-wire通讯协议简直是方便自己痛苦他人(我的主观臆断)。多说无益,可以多看看芯片的手册,按照标准严格做一定行。

module My18B20(clk, rst_n, bus, data_out_d, sig);
	input clk;
	input rst_n;
	inout bus;
	output reg [11:0] data_out_d;
	output reg sig;
	
	localparam Read = 3'b000;
	localparam Write = 3'b001;
	localparam Delay = 3'b010;
	localparam Sampling = 3'b011;
	localparam Main = 3'b100;
	localparam ReadData = 3'b101;
	localparam WriteCmd = 3'b110;
	localparam Init = 3'b111;
	
	localparam HIGH = 1'b1;
	localparam HIZ = 1'bz;
	localparam LOW = 1'b0;
	
	reg [15:0] data_out;
	
	reg bus_output;
	
	reg data_buffer;
	
	reg [7:0] cmd_buffer;
	
	reg [2:0] state;
	reg [2:0] state_r;
	
	reg [5:0] init_cnt;
	
	reg [25:0] delay_cnt;
	reg [25:0] delay_num;
	
	reg [5:0] sampling_cnt;
	reg [5:0] sampling_num;
	reg [5:0] sampling_result;
	reg sampling_data;
	
	reg [5:0] read_cnt;
	
	reg [5:0] write_cnt;
	
	reg [10:0] main_cnt;
	
	reg [5:0] readdata_cnt;
	
	reg [5:0] writecmd_cnt;
	
	initial
	begin
		bus_output = HIZ;
		state = Main;
		init_cnt = 0;
		delay_cnt = 0;
		sampling_cnt = 0;
		sampling_result = 0;
		read_cnt = 0;
		write_cnt = 0;
		main_cnt = 0;
		readdata_cnt = 0;
		writecmd_cnt = 0;
		sig = 0;
	end
	
	
	always @ (posedge clk or negedge rst_n)
	begin
		if(!rst_n)
		begin
			bus_output = HIZ;
			state = Main;
			init_cnt = 0;
			delay_cnt = 0;
			sampling_cnt = 0;
			sampling_result = 0;
			read_cnt = 0;
			write_cnt = 0;
			main_cnt = 0;
			readdata_cnt = 0;
			writecmd_cnt = 0;
			sig = 0;
		end
		else
			case(state)
				Init:
					case(init_cnt)
						0: begin bus_output = LOW; state = Delay; delay_num = 500; state_r = Init; init_cnt = init_cnt + 1; end
						1: begin bus_output = HIZ; state = Delay; delay_num = 500; state_r = Init; init_cnt = init_cnt + 1; end
						2: begin state = Main; init_cnt = 0; end
					endcase
					
				Delay:
					begin
						if(delay_cnt == delay_num - 1)
						begin
							delay_cnt = 0;
							state = state_r;
						end
						else
							delay_cnt = delay_cnt + 1;
					end

				Sampling:
					begin
						if(sampling_cnt == sampling_num - 1)
						begin
							sampling_result = sampling_result + bus;
							sampling_data = sampling_result > sampling_num >> 1 ? 1 : 0;
							sampling_result = 0;
							sampling_cnt = 0;
							state = Read;
						end
						else
						begin
							sampling_result = sampling_result + bus;
							sampling_cnt = sampling_cnt + 1;
						end
					end
				
				Read: 
					case(read_cnt)
						0: begin bus_output = LOW; state = Delay; delay_num = 4; state_r = Read; read_cnt = read_cnt + 1; end
						1: begin bus_output = HIZ; state = Delay; delay_num = 4; state_r = Read; read_cnt = read_cnt + 1; end
						2: begin state = Sampling; sampling_num = 4; read_cnt = read_cnt + 1; end
						3: begin state = Delay; delay_num = 45; state_r = Read; read_cnt = read_cnt + 1; end
						4: begin state = ReadData; read_cnt = 0; end
					endcase
					
				Write:
					case(write_cnt)
						0: begin bus_output = LOW; state = Delay; delay_num = 4; state_r = Write; write_cnt = write_cnt + 1; end
						1: begin bus_output = data_buffer; state = Delay; delay_num = 54; state_r = Write; write_cnt = write_cnt + 1; end
						2: begin bus_output = HIZ; state = WriteCmd; write_cnt = 0; end
					endcase
				
				Main:
					case(main_cnt)
						0: begin state = Init; main_cnt = main_cnt + 1; sig = 0; end
						1: begin state = WriteCmd; cmd_buffer = 8'hcc; main_cnt = main_cnt + 1; end
						2: begin state = WriteCmd; cmd_buffer = 8'h44; main_cnt = main_cnt + 1; end
						3: begin state = Delay; delay_num = 750000; state_r = Main; main_cnt = main_cnt + 1; end
						4: begin state = Init; main_cnt = main_cnt + 1; end
						5: begin state = WriteCmd; cmd_buffer = 8'hcc; main_cnt = main_cnt + 1; end
						6: begin state = WriteCmd; cmd_buffer = 8'hbe; main_cnt = main_cnt + 1; end
						7: begin state = ReadData; main_cnt = main_cnt + 1; end
						8: 
						begin 
							data_out_d[11:8] = data_out[11:4] / 100;
							data_out_d[7:4] = data_out[11:4] / 10;
							data_out_d[3:0] = data_out[11:4] % 10;
							
						
							state = Main; 
							bus_output = HIZ;
							init_cnt = 0;
							delay_cnt = 0;
							sampling_cnt = 0;
							sampling_result = 0;
							read_cnt = 0;
							write_cnt = 0;
							main_cnt = 0;
							readdata_cnt = 0;
							writecmd_cnt = 0;
							sig = 1;
						end
					endcase
						
				ReadData:
					case(readdata_cnt)
						0: begin state = Read; readdata_cnt = readdata_cnt + 1; end
						16: begin data_out[readdata_cnt-1] = sampling_data; state = Main; readdata_cnt = 0; end
						default: begin data_out[readdata_cnt-1] = sampling_data; state = Read; readdata_cnt = readdata_cnt + 1; end
					endcase
						
				WriteCmd:
					case(writecmd_cnt)
						8: begin state = Main; writecmd_cnt = 0; end
						default: begin state = Write; data_buffer = cmd_buffer[writecmd_cnt]; writecmd_cnt = writecmd_cnt + 1; end
					endcase
			endcase
	end
	
	assign bus = bus_output;
	
endmodule
	

 

封装模块姑且目前就这些,剩下的就是统筹所有模块的Top级别模块了(干杂活)。记得东西多了一定打好分割线,避免混乱。

module MyTop(clk, rst_n, rxport, m_key, h_key, bus, cs, dc, sdin, oledrst, oledclk, txport, beeper);
	input clk;
	input rst_n;
	input rxport;
	input m_key;
	input h_key;
	inout bus;
	output cs;
	output dc;
	output sdin;
	output oledrst;
	output oledclk;
	output txport;
	output beeper;
	
	localparam Main = 3'b000;
	localparam TimeAlert = 3'b001;
	localparam TempeAlert = 3'b010;
	localparam Delay = 3'b011;
	localparam Init = 3'b100;
	localparam Beeper = 3'b101;
	
	
	wire [7:0] rx_wire;
	wire [11:0] tempe_wire;
	wire [15:0] mytime;
	
	reg [11:0] mytime_r;
	reg [15:0] tempe_buffer_r;
	
	reg [5:0] rx_cnt;
	
	reg [7:0] uart_rx_buffer [4:0];
	reg [7:0] uart_tx_buffer;
	
	reg [11:0] tempe_buffer;
	
	reg [7:0] p_cnt;
	
	reg [3:0] state;
	reg [3:0] state_r;
	
	reg [25:0] delay_num;
	reg [25:0] delay_cnt;
	
	reg [3:0] timealert_cnt;
	
	reg send_sig;
	
	reg [3:0] tempealert_cnt;
	
	reg [20:0] beeper_cnt;
	reg [20:0] beeper_num;
	reg [20:0] beeper_cnt2;
	reg beeper_2;
	
	reg music_in;
	
	initial
	begin
		rx_cnt = 0;
		p_cnt = 0;
		state = Init;
		delay_cnt = 0;
		timealert_cnt = 0;
		tempealert_cnt = 0;
		beeper_cnt = 0;
		beeper_cnt2 = 0;
		beeper_2 = 0;
		music_in = 0;
	end
	
// ---------------------------------------------------- CLK
	MyClkDevide # (.width(4), .n(12)) u_clk_1 (clk, rst_n, clk_1_out);
	
	MyClkDevide # (.width(12), .n(1250)) u_clk_2 (clk, rst_n, clk_2_out);
	
// ---------------------------------------------------- OLed
	MyOLed u_oled (clk_1_out, rst_n, mytime_r, tempe_buffer_r, cs, dc, sdin, oledrst);
	
	assign oledclk = clk_1_out;
// ---------------------------------------------------- Uart
	MyUartTX u_uart_tx (clk_2_out, uart_tx_buffer, send_sig, rst_n, txport, t_busy);
	
	MyUartRX u_uart_rx (clk, rst_n, rxport, rx_wire, r_busy);
	
	always @ (negedge r_busy)
	begin
		uart_rx_buffer[rx_cnt] = rx_wire;
		rx_cnt  = rx_cnt + 1;
		music_in = 1;
			
	end
// ---------------------------------------------------- 18B20
	My18B20 u_18b20 (clk_1_out, rst_n, bus, tempe_wire, sig);
	
	always @ (posedge sig)
	begin
		tempe_buffer = tempe_wire;
	end
	
	assign overheat_sig = tempe_buffer[7:4] >= 3;
	
// ---------------------------------------------------- Clock
	MyClock u_clock (clk, rst_n, m_key, h_key, mytime, time_sig);
	
// ---------------------------------------------------- Beeper
	MyPWM u_beeper (clk_1_out, p_cnt, beeper_1);
	
	assign beeper = beeper_1 || beeper_2;
// ----------------------------------------------------

	always @ (posedge clk_1_out or negedge rst_n)
	begin
		if(!rst_n)
		begin
			p_cnt = 0;
			state = Init;
			delay_cnt = 0;
			timealert_cnt = 0;
			tempealert_cnt = 0;
			beeper_cnt = 0;
			beeper_cnt2 = 0;
			beeper_2 = 0;
		end
		else
		begin
			if(state != TempeAlert)
			begin					
				mytime_r = mytime;
				tempe_buffer_r = tempe_buffer;
			end
		
			case(state)
				Delay:
				begin
					if(delay_cnt == delay_num - 1)
					begin
						delay_cnt = 0;
						state = state_r;
					end
					else
						delay_cnt = delay_cnt + 1;
				end
				
				Main:
				begin
					if(time_sig)
						state = TimeAlert;
					else if(overheat_sig)
						state = TempeAlert;
					
				end
				
				TimeAlert:
				begin
					case(timealert_cnt)
						0: begin p_cnt = 50; uart_tx_buffer = tempe_buffer[7:0]; send_sig = 1; timealert_cnt = timealert_cnt + 1; end
						1: begin state = Delay; delay_num = 100000; state_r = TimeAlert; timealert_cnt = timealert_cnt + 1; end
						2: begin p_cnt = 0; if(!time_sig) timealert_cnt = timealert_cnt + 1; end
						3: begin send_sig = 0; state = Main; timealert_cnt = 0; end
					endcase
				end
				
				Init:
				begin
					state = Delay; 
					delay_num = 1000; 
					state_r = Main; 
				end
				
				TempeAlert:
				begin
					case(tempealert_cnt)
						0: begin uart_tx_buffer = 8'hFF; send_sig = 1; tempealert_cnt = tempealert_cnt + 1; end
						1: begin state = Delay; delay_num = 1000; state_r = TempeAlert; tempealert_cnt = tempealert_cnt + 1; end
						2: begin if(music_in) tempealert_cnt = tempealert_cnt + 1; end
						8: begin if(!overheat_sig) tempealert_cnt = tempealert_cnt + 1; end
						9: begin p_cnt = 0; state = Main; tempealert_cnt = 0; send_sig = 0; end
						default: 
						begin 
							state = Beeper;
							state_r = TempeAlert;
							beeper_num = uart_rx_buffer[tempealert_cnt-3];
							tempealert_cnt = tempealert_cnt + 1; end
					endcase
				end
				
				Beeper:
				begin
					if(beeper_cnt2 == 1000000 / beeper_num)
					begin
						beeper_cnt = 0;
						beeper_cnt2 = 0;
						state = state_r;
					end
					else if(beeper_cnt == beeper_num - 1)
					begin
						beeper_cnt = 0;
						beeper_cnt2 = beeper_cnt2 + 1;
					end
					else
						beeper_cnt = beeper_cnt + 1;
						
					beeper_2 = beeper_cnt > beeper_num >> 1 ? 1 : 0;
				end
				
			endcase
		end
	end
		
endmodule

 

遇到的困难:

   这项目是我昨天刚刚推倒重做的,彻夜未眠。印象最深的就是晃眼睛的垃圾界面,还有不带提示的编程方式,自动排版都没有...

   Verilog是一门神奇的语言,可能是因为我刚刚接触的原因,我觉得他特别能藏错。一开始我忘接线不报错整个人都是懵逼的。还有仿真这个东西,本以为是准确的,结果居然有一次出现了仿真和实际输出不一样的事情,害得我瞎改了半天(错的是真的离谱)。

   此外,虽说Verilog挺像C语言,但感觉限制超多。对于我这种大一数电都没摸过的人来说简直要命。

   好在撑过来了,尤其是最后一天的彻夜通宵,很过瘾。

 

展望:

   这次项目的代码说实在的有很多冗余,是因为我不熟悉Verilog造成的。

   Beeper其实可以独立出一个模块,但是因为时间原因没有做成。

 

   貌似上面把心得体会都说了?没关系

心得体会:

多看文档

附件下载
First310.7z.001
First310.7z.002
First310.7z.003
团队介绍
哈尔滨工业大学
团队成员
刘腾渊
哈尔滨工业大学本科20级
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号