⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 serial.v

📁 Verilog 经典实例
💻 V
字号:

/*
 本模块的功能是验证实现和PC机进行基本的串口通信的功能。需要在
PC机上安装一个串口调试工具来验证程序的功能。
 程序实现了一个收发一帧10个bit(即无奇偶校验位)的串口控
制器,10个bit是1位起始位,8个数据位,1个结束
位。串口的波特律由程序中定义的div_par参数决定,更改该参数可以实
现相应的波特率。程序当前设定的div_par 的值是27=50M/115200/8,对应的波特率是
115200。用一个8倍波特率的时钟将发送或接受每一位bit的周期时间
划分为8个时隙以使通信同步.
程序的工作过程是:每按一下reset,CPLD向PC发送“welcome"字符串

*/
module serial (
      clk    ,                
      rst    ,                
      rxd    ,                
      txd    ,                                    
      );
input     clk;
input     rst;
input     rxd;
output    txd;

//////////////////inner reg////////////////////
reg [15:0]   div_reg  ;               //分频计数器,分频值由波特率决定。分频后得到频率8倍波特率的时钟   
reg [2:0]    div8_tras_reg  ;         //该寄存器的计数值对应发送时当前位于的时隙数   
reg [3:0]    div8_rec_reg  ;          // 寄存器的计数值对应接收时当前位于的时隙数 
reg [3:0]    state_tras  ;            // 发送状态寄存器
reg [3:0]    state_rec  ;             //接受状态寄存器 
reg          clkbaud_tras ;           //以波特率为频率的发送使能信号  
reg          clkbaud_rec  ;           //以波特率为频率的接受使能信号  
reg          clkbaud8x   ;            //以8倍波特率为频率的时钟,它的作用是将发送或接受一个bit的时钟周期分为8个时隙  
reg          recstart  ;              //开始发送标志 
reg          recstart_tmp ;           //开始接受标志  
reg          trasstart   ;            
reg          rxd_reg1  ;               //接收寄存器1  
reg          rxd_reg2  ;               //接收寄存器2,因为接收数据为异步信号,故用两级缓存  
reg          txd_reg  ;                //发送寄存器  
reg [7:0]    rxd_buf   ;              //接受数据缓存   
reg [7:0]    txd_buf   ;              //发送数据缓存   
reg [3:0]    send_state  ;            //每次按键给PC发送"Welcome"字符串,这是发送状态寄存器   
reg          key_entry2  ;            //确定有键按下标志 

parameter  div_par =16'b0000000000011011;
//分频参数,其值由对应的波特率计算而得,按此参数分频的时钟频率是波倍特率的8倍,此处值对应115200的波特率,即分频出的时钟频率是115200*8	    	    

assign  txd = txd_reg ;

always @(posedge clk or negedge rst)
    begin
      if(rst==1'b0)
        begin
        div_reg<=16'h00;  
        clkbaud8x <= 1'b0; 
        end
        else if(div_reg < div_par)  
            div_reg <= div_reg + 1'b1; 
               else
                begin
                  div_reg<=16'h0000;
                  clkbaud8x <= ~clkbaud8x; 
                end
     end

always @(posedge clkbaud8x or negedge rst)
    begin
      if(rst==1'b0)
          div8_rec_reg <= 3'b000; 
       else if(recstart ==1'b1)
          div8_rec_reg<=div8_rec_reg+1'b1;
      end   


always @(posedge clkbaud8x or negedge rst)                    
    begin
      if(rst==1'b0)
        div8_tras_reg <=3'b000;
      else if(trasstart ==1'b1)
        div8_tras_reg <= div8_tras_reg + 1'b1; 
    end

 always @(div8_rec_reg)
     begin
       if(div8_rec_reg == 3'b111)
         clkbaud_rec <= 1'b1;
       else  
         clkbaud_rec <= 1'b0;
     end

 always @(div8_rec_reg)
     begin
       if(div8_tras_reg == 3'b111)
           clkbaud_tras <= 1'b1;
        else  
           clkbaud_tras <= 1'b0;
        end

always @(posedge clkbaud8x  or negedge rst)   
    begin
       if(rst==1'b0)
       begin
         txd_reg <=1'b1;
         trasstart <= 1'b0;
         txd_buf <= 8'h00;
         state_tras <= 4'b0000;
         send_state <= 4'b0000;
         key_entry2 <=1'b1;
         txd_buf <= 8'b0000_0000;//8'b01110111;//"w"
         end
      else
   case(state_tras)   
    4'b0000: begin  //发送起始位
               if(!trasstart&&(send_state < 4'b1000))
                trasstart <= 1'b1;
                else if(send_state < 4'b1000)
                 if (clkbaud_tras == 1'b1)
                   begin                              
                     txd_reg <= 1'b0; 
                     state_tras <= state_tras + 1'b1;                     
                   end
               else
                  begin
                      key_entry2 <= 1'b0; 
                      state_tras <= 4'b0000;
                  end
               end                                      
    4'b0001: begin  //发送第一位
                if(clkbaud_tras == 1'b1)
                  begin                           
                   txd_reg = txd_buf[0];
                   txd_buf[6:0] = txd_buf[7:1];
                   state_tras = state_tras +1'b1;  
                   end
               end                  
    4'b0010: begin
               if (clkbaud_tras == 1'b1)
                    begin
                     txd_reg <= txd_buf[0];
                     txd_buf[6:0] <= txd_buf[7:1];
                     state_tras <= state_tras +1'b1;  
                    end
              end
    4'b0011: begin
            if (clkbaud_tras == 1'b1)
                begin                      
                   txd_reg <= txd_buf[0];
                   txd_buf[6:0] <= txd_buf[7:1];
                   state_tras <= state_tras +1'b1;  
                end
            end
   4'b0100: begin
          if (clkbaud_tras == 1'b1)
             begin 
               txd_reg <= txd_buf[0];
               txd_buf[6:0] <= txd_buf[7:1];
               state_tras <= state_tras +1'b1;
             end
          end
    4'b0101: begin
          if (clkbaud_tras == 1'b1)
             begin 
             txd_reg <= txd_buf[0];
             txd_buf[6:0] <= txd_buf[7:1];
             state_tras <= state_tras +1'b1;
             end
           end
   4'b0110: begin
         if (clkbaud_tras == 1'b1)
              begin 
                txd_reg <= txd_buf[0];
                txd_buf[6:0] <= txd_buf[7:1];
                state_tras <= state_tras +1'b1;
              end
            end
   4'b0111: begin
          if (clkbaud_tras == 1'b1)
              begin 
                txd_reg <= txd_buf[0];
                txd_buf[6:0] <= txd_buf[7:1];
                state_tras <= state_tras +1'b1;
              end
            end
    4'b1000: begin//发送第8位
          if (clkbaud_tras == 1'b1)
              begin 
                txd_reg <= txd_buf[0];
                txd_buf[6:0] <= txd_buf[7:1];
                state_tras <= state_tras +1'b1;
              end
            end
   4'b1001: begin//发送停止位
          if (clkbaud_tras == 1'b1)
              begin 
                txd_reg <= 1'b1;
                txd_buf <= 8'b01010101;    
                state_tras <= state_tras +1'b1;
              end
            end
   4'b1111:begin
         if (clkbaud_tras == 1'b1)                           
             begin
               state_tras <= state_tras + 1'b1;
               send_state <= send_state + 1'b1;
               trasstart  <= 1'b0;    
                  case (send_state)     
                             4'b0000:txd_buf <=8'b01110111;//"w"
                             4'b0001:txd_buf <=8'b01100101;//"e"
                             4'b0010:txd_buf <=8'b01101100;//"l"
                             4'b0011:txd_buf <=8'b01100011;//"c"
                             4'b0100:txd_buf <=8'b01101111;//"o"
                             4'b0101:txd_buf <=8'b01101101;//"m"
                             4'b0110:txd_buf <=8'b01100101;//"e"
                            default:txd_buf <=8'b00000000;          
                   endcase
             end
           end
        default:begin
                if (clkbaud_tras == 1'b1)   
                    begin
                      state_tras <= state_tras + 1'b1;
                      trasstart <= 1'b1;
                    end    
                end         
       endcase           
   end
               
endmodule

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -