主要思想还是时间并行,以及大计数周期的概念。
module rs232_diver_RX(sys_clk,sys_rst,RX,data_RX1,data_flag);
input sys_clk,sys_rst;//系统时钟,系统复位
input RX; //数据接受
output data_RX1;
output data_flag;
reg [7:0] data_RX1;//表示接受的数据(总线)
reg [7:0] data_RX;
reg data_flag;//表示数据接收到了
/*设置波特率*/
parameter Baud_MAX=15'd5208; //9600Baud
reg [14:0] cnt_Baud; //波特计数,用于产生波特率
reg RX_reg1; //防止亚稳态
reg RX_reg2; //防止亚稳态
reg RX_reg3;
reg Baud_clk; //用于数据读取标志(这里设置码元1/4-1/2位置,这里1/4位置)(Buad_MAX/4-1)
reg Baud_flag; //用于数据位数计数,使能,开始标志等(这里设置在码元中间位置)(Baud_MAX/2-1)
reg [3:0] Baud_num; //用于记录一个数据经历几个sys_flag
reg start_flag; //当接受高电平时,在sys_clk立刻置为,这时立刻同步波特计数
reg RX_enable; //表示数据有效状态
/* 防止亚稳态(注意默认接受为高电平,低电平表示启动) */
always@(posedge sys_clk or negedge sys_rst)
begin
if(!sys_rst)
RX_reg1<=1'b1;
else
RX_reg1<=RX;
end
always@(posedge sys_clk or negedge sys_rst)
begin
if(!sys_rst)
RX_reg2<=1'b1;
else
RX_reg2<=RX_reg1;
end
always@(posedge sys_clk or negedge sys_rst)
begin
if(!sys_rst)
RX_reg3 <= 1'b1;
else
RX_reg3 <= RX_reg2;
end
//start_flag:检测到下降沿时start_flag产生一个时钟的高电平
always@(posedge sys_clk or negedge sys_rst)
begin
if(!sys_rst)
start_flag <= 1'b0;
else if((~RX_reg2) && (RX_reg3)&&(RX_enable==1'b0))
start_flag <= 1'b1;
else
start_flag <= 1'b0;
end
/* RX_enable信号 */
always@(posedge sys_clk or negedge sys_rst)
begin
if(!sys_rst)
RX_enable<=1'b0;
else if(start_flag==1'b1)
RX_enable<=1'b1;
else if((Baud_num==4'd9)&&(Baud_flag==1'b1))//----------------------------------------
RX_enable<=1'b0;
else
RX_enable<=RX_enable;
end
/* 波特计数,产生”码元长度“,为后面分别在1/2码元长度产生Baud_flag,和1/4码元产生baud_clk */
always@(posedge sys_clk or negedge sys_rst)
begin
if(!sys_rst)
cnt_Baud<=15'd0;
else if((cnt_Baud==Baud_MAX-1)||(start_flag==1'b1))
cnt_Baud<=15'd0;
else
cnt_Baud<=cnt_Baud+1'b1;
end
/* 产生Baud_flag */
always@(posedge sys_clk or negedge sys_rst)
begin
if(!sys_rst)
Baud_flag<=1'b0;
else if(cnt_Baud==Baud_MAX/2-1)
Baud_flag<=1'b1;
else
Baud_flag<=1'b0;
end
/* 产生Baud_clk */
always@(posedge sys_clk or negedge sys_rst)
begin
if(!sys_rst)
Baud_clk<=1'b0;
else if(cnt_Baud==Baud_MAX*3/4)
Baud_clk<=1'b1;
else
Baud_clk<=1'b0;
end
/* 产生Baud_num */
always@(posedge sys_clk or negedge sys_rst)
begin
if(!sys_rst)
Baud_num<=4'd0;
else if(RX_enable==1'b0) Baud_num<=4'd0;
else if((RX_enable==1'b1)&&(Baud_flag==1'b1))
Baud_num<=Baud_num+1'b1;
else
Baud_num<=Baud_num;
end
/* 最后一步,根据Baud_num和into_reg2进行数据的合并 */
always@(posedge sys_clk or negedge sys_rst)
begin
if(!sys_rst)
data_RX<=8'b1111_1111;
else if((Baud_clk==1'b1)&&(RX_enable==1'b1))
begin
case(Baud_num)
2: data_RX<={data_RX[7],data_RX[6],data_RX[5],data_RX[4],data_RX[3],data_RX[2],data_RX[1],RX_reg2};
3: data_RX<={data_RX[7],data_RX[6],data_RX[5],data_RX[4],data_RX[3],data_RX[2],RX_reg2,data_RX[0]};
4: data_RX<={data_RX[7],data_RX[6],data_RX[5],data_RX[4],data_RX[3],RX_reg2,data_RX[1],data_RX[0]};
5: data_RX<={data_RX[7],data_RX[6],data_RX[5],data_RX[4],RX_reg2,data_RX[2],data_RX[1],data_RX[0]};
6: data_RX<={data_RX[7],data_RX[6],data_RX[5],RX_reg2,data_RX[3],data_RX[2],data_RX[1],data_RX[0]};
7: data_RX<={data_RX[7],data_RX[6],RX_reg2,data_RX[4],data_RX[3],data_RX[2],data_RX[1],data_RX[0]};
8: data_RX<={data_RX[7],RX_reg2,data_RX[5],data_RX[4],data_RX[3],data_RX[2],data_RX[1],data_RX[0]};
9: data_RX<={RX_reg2,data_RX[6],data_RX[5],data_RX[4],data_RX[3],data_RX[2],data_RX[1],data_RX[0]};
default: data_RX<=data_RX;
endcase
end
else
data_RX<=data_RX;
end
/* 最后一步,产生data_flag用于其他模块,表示已经接收到数据,最后这里一般会存到RAM中,或者FiFo */
always@(posedge sys_clk or negedge sys_rst)
begin
if(!sys_rst)begin
data_flag<=1'b0;
data_RX1<=8'b1111_0000;
end
else if((Baud_flag==1'b1)&&(Baud_num==4'd9))begin
data_RX1<=data_RX;
data_flag<=1'b1;
end
else
data_flag<=1'b0;
end
endmodule
module rs232_diver_TX(sys_clk,sys_rst,TX_data1,TX_dataStart,TX_out1); input sys_clk,sys_rst;//系统时钟,复位 input wire [7:0] TX_data1;//表示要发送的数据 input wire TX_dataStart;//表示数据发送开始标志位 output reg TX_out1;//表示数据输出 parameter Baud_MAX=15'd5209;//波特率设置(50_000_000/波特率) reg TX_out;//防止亚稳态 reg [7:0] TX_data;//暂存该数据 reg [14:0] cnt_Baud; reg Baud_clk; reg [4:0] state; reg [4:0] state_num; reg TX_enable; always@(posedge sys_clk or negedge sys_rst) begin if(!sys_rst) cnt_Baud<=15'd0; else if((cnt_Baud==Baud_MAX)||(TX_dataStart==1'b1))//产生码元同步 cnt_Baud<=15'd0; else cnt_Baud<=cnt_Baud+1'b1; end /* 产生baud_clk信号 */ always@(posedge sys_clk or negedge sys_rst) begin if(!sys_rst) Baud_clk<=1'b0; else if((cnt_Baud==Baud_MAX-1))//产生码元同步 Baud_clk<=1'b1; else Baud_clk<=1'b0; end /* 产生TX_enable信号 */ always@(posedge sys_clk or negedge sys_rst) begin if(!sys_rst) TX_enable<=1'b0; else if((TX_dataStart==1'b1)&&(TX_enable==1'b0)) TX_enable<=1'b1; else if((state_num==4'd10)&&(TX_enable==1'b1)&&(cnt_Baud==Baud_MAX/2)) TX_enable<=1'b0; else TX_enable<=TX_enable; end /* 产生state_num信号 */ always@(posedge sys_clk or negedge sys_rst) begin if(!sys_rst) state_num<=4'd0; else if(TX_enable==1'b0) state_num<=4'd0; else if((cnt_Baud==Baud_MAX/2)&&(TX_enable==1'b1)) state_num<=state_num+1'b1; else state_num<=state_num; end /* 执行串行输出 */ always@(posedge sys_clk or negedge sys_rst) begin if(!sys_rst) TX_out<=1'b1; else if((TX_enable==1'b1)&&(Baud_clk==1'b1)) begin case(state_num) 0:TX_out<=1'b1; 1:TX_out<=1'b0; 2:TX_out<=TX_data[0]; 3:TX_out<=TX_data[1]; 4:TX_out<=TX_data[2]; 5:TX_out<=TX_data[3]; 6:TX_out<=TX_data[4]; 7:TX_out<=TX_data[5]; 8:TX_out<=TX_data[6]; 9:TX_out<=TX_data[7]; 10: TX_out<=1'b1; default: TX_out<=1'b1; endcase end end /* 以下缓存 */ always@(posedge sys_clk or negedge sys_rst) begin if(!sys_rst) TX_out1<=1'b1; else TX_out1<=TX_out; end always@(posedge sys_clk or negedge sys_rst) begin if(!sys_rst) TX_data<=8'hff; else if(TX_dataStart==1'b1) TX_data<=TX_data1; else TX_data<=TX_data; end endmodule