寒假在家一起练--项目四(小脚丫)
基于小脚丫FPGA的综合技能训练平台的带有温度测控预警功能的数字钟系统,通过DS18b20Z采集温度,OLED显示时间及温度,UART实现与PC通信,蜂鸣器实现整点报时和温度预警。
标签
嵌入式系统
FPGA
数字逻辑
Sophia
更新2021-02-28
1037

项目需求

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

设计思路

      该系统由时钟模块,温度采集模块,温度格式转换模块,OLED显示模块,蜂鸣器(音乐播放)模块,UART通信模块组成,具体如下图:FhqXfjzQz3VAbXnMWd1LffLzhcmS

时钟模块

      输入:系统内部12MHz的时钟,系统复位信号,设置时间点的按键

      输出:为时分秒的数字

   该模块比较简单,首先通过时钟分频得到1Hz的时钟,然后在其触发下确定秒的变化,以此类推得到分针和时针。具体代码如下:

  •  
module clock(

	input clk,
	input rst_n,
	input hour,//时钟+
	input minutes_up,//分针+
	input minutes_down,//分针-
	input fresh_flag,
	output reg clk_1Hz,
	output [3:0] hour1,//时针十位
	output [3:0] hour0,//时针个位
	output [3:0] minutes1,//分针十位
	output [3:0] minutes0,//分针个位
	output [3:0] second1,//秒针十位
	output [3:0] second0//秒针个位
);
reg [3:0] hour1_now,hour0_now,minutes1_now,minutes0_now,second1_now,second0_now;
reg [3:0] hour1_next,hour0_next,minutes1_next,minutes0_next,second1_next,second0_next;
//时钟分频,得到周期为1s的时钟clk_1Hz
reg [23:0] cnt;
parameter N = 12_000_000;
always@(posedge clk or negedge rst_n)begin
	if(!rst_n) begin
	   clk_1Hz<=1'b0;
		cnt<=0;
		end
	else if (cnt==N/2) begin
		cnt<=24'd0;
		clk_1Hz<=~clk_1Hz;
		end	
	else
		cnt<=cnt+1'b1;
	end
	/***************************
	wire clk1Hz_down;
reg clk1Hz_d1,clk1Hz_d0;
	//捕获接下降沿,得到一个时钟周期的脉冲信号
    assign  clk1Hz_down = clk1Hz_d1 & (~clk1Hz_d0);    

    //对clk_1Hz延迟两个时钟周期
    always @(posedge clk or negedge rst_n) begin 
        if (!rst_n) begin 
            clk1Hz_d0 <= 1'b0;
            clk1Hz_d1 <= 1'b0;          
        end
        else begin
            clk1Hz_d0  <= clk_1Hz;                   
            clk1Hz_d1  <= clk1Hz_d0;
        end   
    end	
	此段未用,本想提高改变时间的反应速度,但发现1s也还可以
	****************************************/
	assign hour1  =  hour1_now;
	assign hour0  =  hour0_now;
	assign minutes1 = minutes1_now;
	assign minutes0 = minutes0_now;
	assign second1 = second1_now;
	assign second0 = second0_now;

					
always @(posedge clk_1Hz or negedge rst_n) begin
	if(!rst_n)begin //复位为00:00:00
		hour1_now<=4'd0;
		hour0_now<=4'd0;
		minutes1_now<=4'd0;
		minutes0_now<=4'd0;
		second1_now<=4'd0;
		second0_now<=4'd0;
		end	
	else if(!fresh_flag) begin
	    second0_now<=second0_now;
		second1_now<=second1_now;
		hour1_now<=hour1_now;
		hour0_now<=hour0_now;
		minutes1_now<=minutes1_now;
		minutes0_now<=minutes1_now;
	end
	else begin
		hour1_now<=hour1_next;
		hour0_now<=hour0_next;
		minutes1_now<=minutes1_next;
		minutes0_now<=minutes0_next;
		second1_now<=second1_next;
		second0_now<=second0_next;
		end
		
	end
	
always@(posedge clk_1Hz or negedge rst_n)// or hour or minutes_up or minutes_down ) 
begin
    if(!rst_n) 
    begin
		second0_next<=1'b0;
		second1_next<=1'b0;
		hour1_next<=4'd0;
		hour0_next<=4'd0;
		minutes1_next<=4'd0;
		minutes0_next<=4'd0;
	end
	else begin
	//else if(fresh_flag) 
	//begin
        if(!hour) 
        begin
            if(hour1_now==4'd2&&hour0_now==4'd3) 
            begin
                hour1_next<=4'd0;
                hour0_next<=4'd0;
            end
            else if(hour0_now==4'd9) 
            begin
                hour0_next<=4'd0;
                hour1_next<=hour1_now+1'b1;
            end
            else
                hour0_next<=hour0_now+1'b1;
        end
        else if(!minutes_up) 
        begin
            if(minutes1_now==4'd5&&minutes0_now==4'd9) 
            begin
                minutes1_next<=4'd0;
                minutes0_next<=4'd0;
                if(hour1_now==4'd2&&hour0_now==4'd3) 
                begin
                    hour1_next<=4'd0;
                    hour0_next<=4'd0;
                end
                else if(hour0_now==4'd9) 
                begin
                    hour0_next<=4'd0;
                    hour1_next<=hour1_now+1'b1;
                end
                else
                    hour0_next<=hour0_now+1'b1;
            end
            else if(minutes0_now==4'd9&&minutes1_now<4'd5) 
            begin
                minutes0_next<=4'd0;
                minutes1_next<=minutes1_now+1'b1;
            end
            else 
            begin
                minutes0_next<=minutes0_now+1'b1;
            end			
        end
        else if(!minutes_down) 
        begin
            if(minutes1_now==4'd0&&minutes0_now==4'd0) 
            begin
                minutes1_next<=4'd5;
                minutes0_next<=4'd9;
            end
            else if(minutes1_now>4'd0&&minutes0_now==4'd0) 
            begin
                minutes1_next<=minutes1_now-1'b1;
                minutes0_next<=4'd9;
            end
            else 
            begin
                minutes0_next<=minutes0_now-1'b1;
            end			
        end
        else 
        begin //每秒钟秒+1
            if(second0_next==4'd9)//若秒的个位是9 
            begin
                second0_next<=4'd0;//个位变为0,十位+1
                if(second1_next==5&&second0_next==4'd9) 
                begin//若十位是5,即现在是59s				
                    second1_next<=4'd0;//十位变为为0,即现在秒为00s,分钟+1
                    if(minutes0_next==4'd9) 
                    begin//若分的个位是9 
                        minutes0_next<=4'd0;//个位变为0,十位+1
                        if(minutes1_next==4'd5) 
                        begin//若十位是5,即现在是59min	
                            minutes1_next<=4'd0;//十位变为为0,即现在秒为00min,小时+1
                            if(hour0_next==4'd9) 
                            begin//若小时的个位是9 
                                hour0_next<=4'd0;//个位变为0,十位+1
                                hour1_next<=hour1_next+1'b1;
                            end
                            else if(hour0_next==4'd3&&hour1_next==4'd2 ) 
                            begin//若现在是23h,则下一小时为00
                                hour0_next<=4'd0;
                                hour1_next<=4'd0;
                            end
                            else 
                            begin//否则小时个位+1
                                hour0_next<=hour0_next+1'b1;
                            end	
                        end
                        else //否则分钟十位+1
                            minutes1_next<=minutes1_next+1'b1;			
                    end
                    else //否则分钟个位+1
                        minutes0_next<=minutes0_next+1'b1;					
                end
                else //否则秒十位+1
                    second1_next <= second1_next+1'b1;
            end
            else//否则秒个位+1
                second0_next <= second0_next+1'b1;
        end	
   end	
end
	
		
endmodule

温度采集模块

      此模块包括DS18B20Z信号采集转换为有效的温度信号,采用平台已给代码( https://www.eetree.cn/wiki/temp_sensor_verilog )得到16位二进制有效温度,再将二进制转换成bcd码的二进制传给显示屏和数码管进行显示(参考 https://blog.csdn.net/li200503028/article/details/19507061 )。

FpoocBARH6vYG1TkUWr0Y50A-DgJFjFA_QYJ1obB7MN6_4FenaiV68DY

采集温度的代码在平台上,此处不再粘贴,数据格式转换主要代码如下:

       // judge sign of temperature
	wire temperature_flag ;
	assign temperature_flag=dataout[15:11]? 1'b0:1'b1;
        //temperature_flag==0:负温度; temperature_flag==1:正温度
	// complement if negative
	wire [10:0] temperature_code;
	assign temperature_code = temperature_flag? dataout[10:0]:(~dataout[10:0])+1'b1; 
	// translate temperature_code to real temperature
	wire [20:0] bin_code;
	assign bin_code = temperature_code * 16'd625;
	//reg [24:0] bcd_code; //十位[23:20],个位[19:16],小数位[14:12]parameter B_SIZE=21;
       //Translate binary code to bcd code
       reg		[2*B_SIZE+3:0]		shift_reg;   
always@(bin_code or rst_n)begin      
    shift_reg= {25'h0,bin_code};          
    if(!rst_n) bcd_code <= 0;      
    else begin         
repeat(B_SIZE)//repeat B_SIZE times
begin                                
if (shift_reg[24:21] >= 5) shift_reg[24:21] = shift_reg[24:21] + 2'b11;
if (shift_reg[28:25] >= 5) shift_reg[28:25] = shift_reg[28:25] + 2'b11;
if (shift_reg[32:29] >= 5) shift_reg[32:29] = shift_reg[32:29] + 2'b11;
if (shift_reg[36:33] >= 5) shift_reg[36:33] = shift_reg[36:33] + 2'b11;
if (shift_reg[40:37] >= 5) shift_reg[40:37] = shift_reg[40:37] + 2'b11;
if (shift_reg[44:41] >= 5) shift_reg[44:41] = shift_reg[44:41] + 2'b11;
shift_reg = shift_reg << 1; 
end         
bcd_code<=shift_reg[45:21];   
end  
end

OLED显示模块

      此处也是采用平台给的代码,只是将显示内容改为了温度和时间,其他均未修改,在此不再贴出代码。

蜂鸣器模块

      蜂鸣器通过改变振动频率发出不同的音调,我们通过改变一个周期内(这里是250ms)的震动次数来改变音调。整点报时的音乐是欢乐颂(虽然听起来并没有那么壮阔)。具体如下:

module	Beeper(
	input	   	clk,					//系统时钟12MHz
	input		clk_1Hz,
	input		rst_n,	
	input		tone_en,			//蜂鸣器使能
	
	input		uart_done,			//串口使能
	
	
	input[7:0]	uart_data,
	
	input[3:0]		second1,				//时间
	input[3:0]		minutes0,
	input[3:0]		minutes1,
	
	output	 fresh_flag,
	
	output		beeper					//蜂鸣器输出端
);	

reg		uart_done_cnt;		//uart_done计数
reg		beeper_reg;				//寄存器

reg[16:0] count,count_end,count_end1;
reg[23:0] count1;
reg[7:0] state;
reg fresh;

//乐谱参数:D=F/2K  (D:参数,F:时钟频率,K:音高频率)
	parameter   L_1 = 16'd22935,
				L_2 = 16'd20428,  //低音2
				L_3 = 16'd18203,  //低音3
				L_5 = 16'd15305,  //低音5
				L_6 = 16'd13635,	//低音6
				L_7 = 16'd12147,	//低音7
				M_1 = 16'd11464,	//中音1
				M_2 = 16'd10215,	//中音2
				M_3 = 16'd9100,	//中音3
				M_4 = 16'd8589,
				M_5 = 16'd7652,	//中音5
				M_6 = 16'd6817,	//中音6
				H_1 = 16'd5740;	//高音1			
	parameter	TIME = 3_000_000;	//控制每一个音的长短(250ms)	

	assign beeper = beeper_reg;			//输出音乐
	assign fresh_flag = fresh;


always@(posedge clk) 
begin
	if(tone_en && minutes1 == 0 && minutes0 == 0 && second1 < 3)//整点才响铃,并且响铃时间为30s
	begin
		count <= count + 1'b1;		//计数器加1
		if(count == count_end)
		begin	
			count <= 17'h0;			//计数器清零
			beeper_reg <= !beeper_reg;		//输出取反
		end
	end
	else if(tone_en && !fresh)
	begin
		count <= count + 1'b1;		//计数器加1
		if(count == count_end1) 
		begin	
			count <= 17'h0;			//计数器清零
			beeper_reg <= !beeper_reg;		//输出取反
		end
	end
	// else
		// count <= 0;
end

//自动温度报警:产生分频的系数并描述出曲谱
always @(posedge clk) 
begin
	if(count1 < TIME)             //一个节拍250mS
      count1 = count1 + 1'b1;
	else 
	begin
		count1 = 24'd0;
		if(state == 8'd63)
			state = 8'd0;
		else
			state = state + 1'b1;
			case(state)
				8'd0,8'd1:count_end = M_3;  
				8'd2:count_end=M_4;
				8'D3,8'd4:count_end=M_5;
				8'D5:count_end=M_4;
				8'D6:count_end=M_3;
				8'D7:count_end=M_2;
			   
				8'D8,8'D9:count_end=M_1;
				8'D10:count_end=M_2;
				8'D11:count_end=M_3;
				8'D12:count_end=L_3;
				8'D13,8'D14:count_end=L_2;
				
				8'D15:count_end=M_3;
				8'D16:count_end=M_3;
				8'D17:count_end=M_4;
				8'D18:count_end=M_5;
				8'D19:count_end=M_5;
				8'D20:count_end=M_4;
				8'D21:count_end=M_3;
				8'D22:count_end=M_2;
				8'D23,8'D24:count_end=M_1;		
				8'D25:count_end=M_2;
				8'D26:count_end=M_3;
				8'D27:count_end=L_2;
				8'D28,8'D29:count_end=L_1;
				
				8'D30,8'D31:count_end=M_2;
				8'd32:count_end = M_3;  
				8'd33:count_end=M_1;
				8'd34:count_end=M_2;
				8'D35:count_end=M_3;
				8'D36:count_end=M_4;
				8'D37:count_end=M_3;
				8'D38:count_end=M_1;
				8'D39:count_end=M_2;
				8'D40:count_end=M_3;
				8'D41:count_end=M_4;
				8'D42:count_end=M_3;
				8'D43:count_end=M_2;
				8'D44:count_end=M_1;
				8'D45:count_end=M_2;
				8'D46:count_end=L_5;
				8'D47,8'D48,8'D49:count_end=M_3;
				8'D50:count_end=M_4;
				8'D51,8'D52:count_end=M_5;
				8'D53:count_end=M_4;
				8'D54:count_end=M_3;
				8'D55:count_end=M_4;
				8'D56:count_end=M_2;
				8'D57,8'D58:count_end=M_1;
				8'D59:count_end=M_2;
				8'D60:count_end=M_3;
				8'D61:count_end=L_2;
				8'D62:count_end=M_1;
				8'D63:count_end=M_1;
				default: count_end = 16'h0;
			endcase
	end
end

//串口控制 曲谱 产生分频的系数并描述出曲谱
always @(posedge clk)
begin
	if(uart_done)
	begin

		case(uart_data)
			8'h1:count_end1 <=16'd22935;	//L1,
			8'h2:count_end1 <=16'd20428;	//L2,
			8'h3:count_end1 <=16'd18203;	//L3,
			8'h4:count_end1 <=16'd17181;	//L4,
			8'h5:count_end1 <=16'd15305;	//L5,
			8'h6:count_end1 <=16'd13635;	//L6,
			8'h7:count_end1 <=16'd12147;	//L7,
			8'h8:count_end1 <=16'd11464;	//M1,
			8'h9:count_end1 <=16'd10215;	//M2,
			8'ha:count_end1 <=16'd9100;		//M3,
			8'hb:count_end1 <=16'd8589;		//M4,
			8'hc:count_end1  <=16'd7652;	//M5,
			8'hd:count_end1 <=16'd6817;		//M6,
			8'he:count_end1 <=16'd6073;		//M7,
			8'hf:count_end1 <=16'd5740;		//H1,
			8'h10:count_end1 <=16'd5107;	//H2,
			8'h11:count_end1 <=16'd4549;	//H3,
			8'h12:count_end1 <=16'd4294;	//H4,
			8'h13:count_end1 <=16'd3825;	//H5,
			8'h14:count_end1 <=16'd3408;	//H6,
			8'h15:count_end1 <=16'd3036;	//H7,
			default:count_end1 <=16'd65535;//	无声
		endcase
	end
		
end

always@(posedge uart_done or posedge clk_1Hz)
begin
	if(uart_done)
	begin
		uart_done_cnt <= 1'b1;
	end
	else
		if(uart_done_cnt)
		begin
			fresh  <= 1'b0;
			uart_done_cnt <= 1'b0;
		end	
		else
			fresh <= 1'b1;
			
end

endmodule

UART通信模块

  • 串口发送

      借鉴平台上叶开同学的代码:https://www.eetree.cn/project/detail/113

module uart_tx(
   input           clk_in,
   
   input			uart_en,//发送串口开关
   
   input   [3:0]   temperature2,
   input   [3:0]   temperature1,
   input   [3:0]   temperature0,
   
   input   [3:0]   hour1,
   input   [3:0]   hour0,
   input   [3:0]   minutes1,
   input   [3:0]   minutes0,
   input   [3:0]   second1,
   input   [3:0]   second0,
   
   output reg		uart_out
);

localparam IDLE = 2'b0;
localparam SEND = 2'b1;

reg flag_1,flag_2,state;
reg [120:0] uart_data;


reg clk_uart;
reg[9:0] times;
//分频的到串口始终
always @(posedge clk_in) begin
    if(times < 625)
        times <= times+1;
    else begin
        clk_uart <= ~clk_uart;
        times <= 0;
    end
end

reg clk_en;
reg [23:0] clk_en_cnt;
always @(posedge clk_in) begin
   if (clk_en_cnt <= 12_000_000) begin
       clk_en_cnt <= clk_en_cnt + 1;
   end else begin
       clk_en_cnt <= 0;
       clk_en <= ~clk_en;
   end
end
 //enter = \r\n 
always @(posedge clk_en) 
begin
	if (temperature2*10+temperature1 >= 40)// 温度超过40° => 开始向pc发送时间和温度数据
		begin
			uart_data <= {  
            1'd1,8'd10,1'd0,                   //return
            1'd1,8'd33,1'd0,                   //!
            1'd1,8'd33,1'd0,                   //!
            1'd1,8'd109,1'd0,                  //m
            1'd1,8'd114,1'd0,                  //r
            1'd1,8'd97,1'd0,                   //a
            1'd1,8'd108,1'd0,                  //l
            1'd1,8'd65,1'd0,                   //A
            1'd1,8'd112,1'd0,                  //p
            1'd1,8'd109,1'd0,                  //m
            1'd1,8'd101,1'd0,                  //e
            1'd1,8'd84,1'd0,                   //T
            1'd1,1'd1
        };
			
			end
	else if(second0 == 1 && second1 == 0 &&minutes0 == 0 && minutes1 == 0 && uart_en)//整点
	begin	
		uart_data <= {  
			  1'd1,8'd10,1'd0,                   //回车
			  1'd1,4'd3,minutes0,1'd0,       //分钟低位
			  1'd1,4'd3,minutes1,1'd0,      //分钟高位
			  1'd1,8'd58,1'd0,                   //:
			  1'd1,4'd3,hour0,1'd0,      //小时低位
			  1'd1,4'd3,hour1,1'd0,     //小时高位
			  1'd1,8'd32,1'd0,                   //space
			  1'd1,8'd67,1'd0,                   //C
			  1'd1,4'd3,temperature0,1'd0,         	 //温度小数位
			  1'd1,8'd46,1'd0,                   //point
			  1'd1,4'd3,temperature1,1'd0,           //温度个位
			  1'd1,4'd3,temperature2,1'd0,           //温度十位
			  1'd1,1'd1
		  };
		flag_1 <= ~flag_1;
	end
end 
reg [7:0] i;
always @(posedge clk_uart) begin
    case(state)
        IDLE: begin
            if(flag_2 != flag_1) begin
                flag_2 <=   flag_1;
                state <= SEND;
            end
        end
        SEND: begin
            if(i < 122) begin
                uart_out <= uart_data[i];
                i <= i+1;
            end 
			else begin
                i <= 0;
                state <= IDLE;
            end
        end  
    endcase
end

endmodule

 

  • 串口接收

      找了网上一个通用的uart模板,仅修改波特率和内部时钟晶振频率https://blog.csdn.net/weifengdq/article/details/103168587 

module uart_rx(
    input			  clk,                  //系统时钟
    input             rst_n,                //系统复位,低电平有效   
    input             uart_rxd,                 //UART接收端口
    output  reg       uart_done,                //接收一帧数据完成标志信号
    output  reg [7:0] uart_data                 //接收的数据
    );
    
    //parameter define
    parameter  CLK_FREQ = 12_000_000;                 //系统时钟频率12MHz
    parameter  UART_BPS = 9600;                     //串口波特率
    localparam BPS_CNT  = CLK_FREQ/UART_BPS;        //为得到指定波特率,需要对系统时钟计数BPS_CNT次
    //reg define
    reg        uart_rxd_d0;
    reg        uart_rxd_d1;
    reg [15:0] clk_cnt;                             //系统时钟计数器
    reg [ 3:0] rx_cnt;                              //接收数据计数器
    reg        rx_flag;                             //接收过程标志信号
    reg [ 7:0] rxdata;                              //接收数据寄存器

    //wire define
    wire       start_flag;

    //*****************************************************
    //**                    main code
    //*****************************************************
    //捕获接收端口下降沿(起始位),得到一个时钟周期的脉冲信号
    assign  start_flag = uart_rxd_d1 & (~uart_rxd_d0);    

    //对UART接收端口的数据延迟两个时钟周期
    always @(posedge clk or negedge rst_n) begin 
        if (!rst_n) begin 
            uart_rxd_d0 <= 1'b0;
            uart_rxd_d1 <= 1'b0;          
        end
        else begin
            uart_rxd_d0  <= uart_rxd;                   
            uart_rxd_d1  <= uart_rxd_d0;
        end   
    end

    //当脉冲信号start_flag到达时,进入接收过程           
    always @(posedge clk or negedge rst_n) begin         
        if (!rst_n)                                  
            rx_flag <= 1'b0;
        else begin
            if(start_flag)                          //检测到起始位
                rx_flag <= 1'b1;                    //进入接收过程,标志位rx_flag拉高
            else if((rx_cnt == 4'd9)&&(clk_cnt == BPS_CNT/2))
                rx_flag <= 1'b0;                    //计数到停止位中间时,停止接收过程
            else
                rx_flag <= rx_flag;
        end
    end

    //进入接收过程后,启动系统时钟计数器与接收数据计数器
    always @(posedge clk or negedge rst_n) begin         
        if (!rst_n) begin                             
            clk_cnt <= 16'd0;                                  
            rx_cnt  <= 4'd0;
        end                                                      
        else if ( rx_flag ) begin                   //处于接收过程
                if (clk_cnt < BPS_CNT - 1) begin
                    clk_cnt <= clk_cnt + 1'b1;
                    rx_cnt  <= rx_cnt;
                end
                else begin
                    clk_cnt <= 16'd0;               //对系统时钟计数达一个波特率周期后清零
                    rx_cnt  <= rx_cnt + 1'b1;       //此时接收数据计数器加1
                end
            end
            else begin                              //接收过程结束,计数器清零
                clk_cnt <= 16'd0;
                rx_cnt  <= 4'd0;
            end
    end

    //根据接收数据计数器来寄存uart接收端口数据
    always @(posedge clk or negedge rst_n) begin 
        if ( !rst_n)  
            rxdata <= 8'd0;                                     
        else if(rx_flag)                            //系统处于接收过程
            if (clk_cnt == BPS_CNT/2) begin         //判断系统时钟计数器计数到数据位中间
                case ( rx_cnt )
                4'd1 : rxdata[0] <= uart_rxd_d1;   //寄存数据位最低位
                4'd2 : rxdata[1] <= uart_rxd_d1;
                4'd3 : rxdata[2] <= uart_rxd_d1;
                4'd4 : rxdata[3] <= uart_rxd_d1;
                4'd5 : rxdata[4] <= uart_rxd_d1;
                4'd6 : rxdata[5] <= uart_rxd_d1;
                4'd7 : rxdata[6] <= uart_rxd_d1;
                4'd8 : rxdata[7] <= uart_rxd_d1;   //寄存数据位最高位
                default:;                                    
                endcase
            end
            else 
                rxdata <= rxdata;
        else
            rxdata <= 8'd0;
    end

    //数据接收完毕后给出标志信号并寄存输出接收到的数据
    always @(posedge clk or negedge rst_n) begin        
        if (!rst_n) begin
            uart_data <= 8'd0;                               
            uart_done <= 1'b0;
        end
        else if(rx_cnt == 4'd9) begin               //接收数据计数器计数到停止位时           
            uart_data <= rxdata;                    //寄存输出接收到的数据
            uart_done <= 1'b1;                      //并将接收完成标志位拉高
        end
        else begin
            uart_data <= 8'd0;                                   
            uart_done <= 1'b0; 
        end    
    end

endmodule	

学习心得:

硬禾这个平台的资源实在是太丰富了,这次的项目最大的体会是站在前人的肩膀上,路会好走很多,感谢做开源项目的人,为初学者提供了一个个向上的台阶。

遗憾:很多模块都是调用平台已有的代码,自己仅处于看懂阶段,有时间自己还是要自己写代码实现。感觉Diamond软件使用不太方便,也可能是自己不习惯,每个模块的仿真都是copy到vivado找问题再copy回来。

 

附件下载
digital_clock.rar
团队介绍
北京理工大学 信息与电子学院
团队成员
王婷
站在巨人肩膀上的小麻雀
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号