📄 serial.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 + -