FPGA16 串口接收

串口接收

  • I 保证串口数据的稳定接收
  • II 设计电路模块
  • III 代码
  • IV 仿真
  • V testbench
  • VI 前仿真

I 保证串口数据的稳定接收

FPGA16 串口接收_第1张图片

II 设计电路模块

FPGA16 串口接收_第2张图片

III 代码

module uartrx(clk,rst,baudset,rx,rx_done,rx_state,thedata);
        input clk;
        input rst;
        input [2:0]baudset;
        input rx;
        output reg[7:0]thedata;
        output reg rx_done;
        output reg rx_state;
        
    wire xjy;
    reg signal1,signal2;
    reg data1,data2;   //服务于下降沿检测器
    
    reg[15:0] biggest; //服务于波特率字典
    
    reg[15:0] cnt;
    reg geduan;   //服务于时间隔断产生器
    
    reg [8:0] cnt160; //服务于160隔断提取器
    
    reg [2:0]START_BIT;
    reg [2:0]STOP_BIT;
    reg [2:0] regdata[7:0]; //八位数据regdata 每位数据有三位
                             //服务于60次采样器
    
    //下降沿检测器:用于检测起始位那个下降沿
   always@(posedge clk or negedge rst)
        if(!rst)
        begin
        signal1 <= 1'b0;
        signal2 <= 1'b0;
        end
        
        else
        begin
        signal1 <= rx;
        signal2 <= signal1;
        end
        
   always@(posedge clk or negedge rst)
        if(!rst)
        begin
        data1 <= 1'b0;
        data2 <= 1'b0;
        end
        
        else
        begin
        data1 <= signal2;
        data2 <= data1;
        end
        
   assign xjy = !data1 && data2;
   
   
   //波特率字典,用于设置波特率,产生计数最大值
   always@(posedge clk or negedge rst)
        if(!rst)
            biggest <= 16'd324;
        else begin
            case(baudset)
            0:biggest <= 16'd324;
            1:biggest <= 16'd162;
            2:biggest <= 16'd80;
            3:biggest <= 16'd53;
            4:biggest <= 16'd26;
            default: biggest <= 16'd324;
            endcase
            end
            
    //时间隔断产生器,用于产生 (波特率计数周期÷系统周期÷16)这样的时间隔断
    //当然 计算的过程已经在字典中实现了 这里只需要计数就行了
    always@(posedge clk or negedge rst)
        if(!rst)
        cnt <= 16'b0;
        else if(rx_state)begin
            if(cnt == biggest)
                cnt <= 16'd0;
            else  
                cnt <= cnt + 16'd1;
            end
        else
            cnt <= 16'd0;
            
    always@(posedge clk or negedge rst)
        if(!rst)
            geduan <= 1'b0;
        else if(cnt == 16'd1)
            geduan <= 1'b1;
        else
            geduan <= 1'b0;
            
                
    //隔断提取器,循环提取10*16=160个时间隔断            
    always@(posedge clk or negedge rst)
        if(!rst)
            cnt160 <= 8'd0;
        else if(cnt160 == 8'd159 || (cnt160 == 8'd12 && START_BIT > 2 ))    
            //检验是否计满 或 出现起始位出错的情况
            cnt160 <= 8'd0;
        else if(geduan)
            cnt160 <= cnt160 + 1'd1;
        else 
            cnt160 <= cnt160;
            
    //采样器 采集十位输入数据 应每位10次 共160次,但只采集稳定部分每位六次共60次
     always@(posedge clk or negedge rst)
        if(!rst) begin
            START_BIT <= 3'd0;
            regdata[0] <= 3'd0;
            regdata[1] <= 3'd0;
            regdata[2] <= 3'd0;
            regdata[3] <= 3'd0;
            regdata[4] <= 3'd0;
            regdata[5] <= 3'd0;
            regdata[6] <= 3'd0;
            regdata[7] <= 3'd0;
            STOP_BIT <= 3'd0;
            end
        else if(geduan)
            case(cnt160)
                0:begin
                    START_BIT <= 3'd0;
                    regdata[0] <= 3'd0;
                    regdata[1] <= 3'd0;
                    regdata[2] <= 3'd0;
                    regdata[3] <= 3'd0;
                    regdata[4] <= 3'd0;
                    regdata[5] <= 3'd0;
                    regdata[6] <= 3'd0;
                    regdata[7] <= 3'd0;
                    STOP_BIT <= 3'd0;
                  end
           6,7,8,9,10,11:START_BIT <= START_BIT + signal2;
           22,23,24,25,26,27:regdata[0] <= regdata[0] + signal2;
           38,39,40,41,42,43:regdata[1] <= regdata[1] + signal2;
           54,55,56,57,58,59:regdata[2] <= regdata[2] + signal2;
           70,71,72,73,74,75:regdata[3] <= regdata[3] + signal2;
           86,87,88,89,90,91:regdata[4] <= regdata[4] + signal2;
           102,103,104,105,106,107:regdata[5] <= regdata[5] + signal2;
           118,119,120,121,122,123:regdata[6] <= regdata[6] + signal2;
           134,135,136,137,138,139:regdata[7] <= regdata[7] + signal2;
           150,151,152,153,154,155:STOP_BIT <= STOP_BIT + signal2;
           default:
              begin
                    START_BIT <= START_BIT;
                    regdata[0] <= regdata[0];
                    regdata[1] <= regdata[1];
                    regdata[2] <= regdata[2];
                    regdata[3] <= regdata[3];
                    regdata[4] <= regdata[4];
                    regdata[5] <= regdata[5];
                    regdata[6] <= regdata[6];
                    regdata[7] <= regdata[7];
                    STOP_BIT <= STOP_BIT;
              end
              endcase
            
     always@(posedge clk or negedge rst)
            if(!rst)
                thedata <= 8'd0;
            else if(cnt160 == 8'd159)
                begin 
                thedata[0] <= regdata[0][2]; //第0位的第2位
                thedata[1] <= regdata[1][2]; 
                thedata[2] <= regdata[2][2];
                thedata[3] <= regdata[3][2];
                thedata[4] <= regdata[4][2];
                thedata[5] <= regdata[5][2];
                thedata[6] <= regdata[6][2];
                thedata[7] <= regdata[7][2];
            end    
     
     //接收完成标志发生器
     always@(posedge clk or negedge rst)
        if(!rst)
            rx_done <= 1'd0;
        else if(cnt160 == 8'd159)
            rx_done <= 1'd1;
        else 
            rx_done <= 1'd0;
    
    //接收状态跟随器:判断是否处于接收状态,并输出
	always@(posedge clk or negedge rst)
	if(!rst)
		rx_state <= 1'b0;
	else if(xjy)
		rx_state <= 1'b1;
	else if(rx_done || (cnt160 == 8'd12 && (START_BIT > 2)))
		rx_state <= 1'b0;
	else
		rx_state <= rx_state;		
          
endmodule

IV 仿真

仿真的思路是 引入前面的串口发送模块,将发送端与接收端连接在一起,通过给发送模块的输入端写入数据,来观察接收模块的输出端的输出数据

V testbench

`timescale 1ns/1ns
`define clk_period 20
module uartrx_tb;
            reg[2:0] baudset; 
            reg[7:0] indata; //(tx的输入)
            reg send_en; //(tx)
            reg clk;
            reg rst;
            
            wire tx_rx;
            wire tx_done;
            wire  uart_state;//(tx)
            
        wire [7:0]thedata;//rx的接收
        wire rx_done;   
        wire  rx_state; //(rx)

   uart uart1(
           .baudset(baudset),
           .indata(indata),
           .send_en(send_en),
           .clk(clk),
           .rst(rst),
           .tx(tx_rx),
           .tx_done(tx_done),
           .uart_state(uart_state)
           );


           
           
           
  uartrx uartrx1(
            .clk(clk),
            .rst(rst),
            .baudset(baudset),
            .rx(tx_rx),
            .rx_done(rx_done),
            .rx_state(rx_state),
            .thedata(thedata)
            );
 
 
 
 

	initial clk = 1;
	always#(`clk_period/2)clk = ~clk;
	
	initial begin
		rst = 1'b0;
		indata = 8'd0;
		send_en = 1'd0;
		baudset = 3'd4;
		#(`clk_period*20 + 1 );
		rst = 1'b1;
		#(`clk_period*50);
		indata = 8'haa;
		send_en = 1'd1;
		#`clk_period;
		send_en = 1'd0;
		
		@(posedge tx_done)
		
		#(`clk_period*5000);
		indata = 8'h55;
		send_en = 1'd1;
		#`clk_period;
		send_en = 1'd0;
		@(posedge tx_done)
		#(`clk_period*5000);
		$stop;	
	end


endmodule 
            

VI 前仿真

我这里出现了错误,始终我也没找到为什么没有找到设计单元 ,我明明都已经加载了
在这里插入图片描述
渴望得到帮助 (等好了我在回来改)

你可能感兴趣的:(FPGA从硬件描述到删核跑路)