
基于verilog hdl语言的串口设计.docx
28页基于 Verilog HDL 语言的串口设计串口 Verilog HDL 代码://串口module trans(clk,rst,en,TxD_data,Wsec,RxD,TxD,TxD_busy,rcven,RxD_data);//时钟50MHzinput clk,rst,en; //en 时发送数据使能input [7:0]TxD_data; //发送数据输入input [2:0]Wsec; //波特率调节 0-2400;1-4800;2-9600 ;3-14400;4-19200;5-38400 ;6-115200;7-128000input RxD; //接收数据输入端output TxD,TxD_busy,rcven;//发送,发送忙,接收结束标志输出output [7:0]RxD_data;//接收数据输出wire Baud1,Baud8;reg [7:0]addwire;//RAM 地址连线reg [7:0]data;wire[7:0]AD_t;//读取 RAM 数据的地址用于发送wire[7:0]AD_r;//接收的数据存储在 RAM 中的地址wire [7:0]datawire;//数据连线//发送例化trans_t tt1(.clk_t(clk),.rst_t(rst),.en_t(en),.BTI_t(Baud1),.recen(recen),.TxD_data_t(datawire),.TxD_t(TxD),.addro_t(AD_t),.TxD_busy_t(TxD_busy));//波特生成例化BaudG tt2(.clk_b(clk),.rst_b(rst),.BTO_b(Baud1),.BTO_R(Baud8),.Wsec_b(Wsec));//接收例化trans_r tt3(.clk_r(clk),.rst_r(rst),.BTI_r(Baud8),.RxD_r(RxD),.RxD_data_r(RxD_data),.wren_r(wren_r),.addro_r(AD_r),.RxD_end(RxD_end));//LPM_RAM 例化RAM0 tt4(.address(addwire),.clock(~clk),.data(data),.wren(wren_r),.q(datawire));always @(posedge clk or negedge rst)if(~rst)addwire 1302)begin FT8=1'b1; BGA162500)begin FT=1'b1;FT8=1'b1; BGA1651)begin FT8=1'b1; BGA162500)begin FT=1'b1; FT8=1'b1; BGA1651)begin FT8=1'b1; BGA115625)begin FT=1'b1;FT8=1'b1; BGA1217)begin FT8=1'b1; BGA117361)begin FT=1'b1;FT8=1'b1; BGA1651)begin FT8=1'b1; BGA115625)begin FT=1'b1; FT8=1'b1; BGA1244)begin FT8=1'b1; BGA115625)begin FT=1'b1;FT8=1'b1; BGA1217)begin FT8=1'b1; BGA1434) begin FT=1'b1;FT8=1'b1; BGA1122)begin FT8=1'b1; BGA13125) begin FT=1'b1; BGA=2000000) printf("*"); else printf(" ");acc %= 2000000;}这段代码会精确的以平均每 "17.361111111..." 个时钟间隔打印出一个"*"。
为了从 FPGA 得到同样的效果,考虑到串行接口可以容忍一定的波特率误差,所以即使我们使用 17.3 或者 17.4 这样的分频比也是没有关系的FPGA 波特率发生器我们希望 2000000 是 2 的整数幂,但很可惜,它不是所以我们改变分频比,"2000000/115200" 约等于 "1024/59" = 17.356. 这跟我们要求的分频比很接近,并且使得在 FPGA 上实现起来相当有效//10 位的累加器 ([9:0]), 1 位进位输出 ([10])reg [10:0] acc; //一共 11 位!always @(posedge clk)acc >5))/(ClkFrequency>>4);这行程序也使得结果成为整数,从而避免截断这就是整个的设计方法了现在我们已经得到了足够精确的波特率,可以继续设计串行接收和发送模块了FPGA 实现串行接口 RS232(3)2008-12-17 11:40RS-232 发送模块下面是我们所想要实现的:它应该能像这样工作: 发送器接收 8 位的数据,并将其串行输出 ("TxD_start"置位后开始传输). 当有数传输的时候,使"busy"信号有效,此时“TxD_start” 信号被忽略. RS-232 模块的参数是固定的: 8 位数据, 2 个停止位, 无奇偶校验.数据串行化假设我们已经有了一个 115200 波特的"BaudTick"信号.我们需要产生开始位、8 位数据以及停止位。
用状态机来实现看起来比较合适reg [3:0] state;always @(posedge clk)case(state)4'b0000: if(TxD_start) state =1&&state_rec<=8) beginif(clkbaud_rec) beginrxd_buf[7]<=rxd_reg2;rxd_buf[6:0]<=rxd_buf[7:1];state_rec<=state_rec+1;endendelse if(state_rec==9) beginif(clkbaud_rec) beginstate_rec<=0;recstart<=0;endendendendalways@(rxd_buf) //将接受的数据用数码管显示出来begincase (rxd_buf)8'h30:seg_data=8'b0000_0011;8'h31: seg_data=8'b1001_1111;8'h32:seg_data=8'b0010_0101;8'h33:seg_data=8'b0000_1101;8'h34:seg_data=8'b1001_1001;8'h35:seg_data=8'b0100_1001;8'h36:seg_data=8'b0100_0001;8'h37:seg_data=8'b0001_1111;8'h38:seg_data=8'b0000_0001;8'h39:seg_data=8'b0001_1001;8'h41:seg_data=8'b0001_0001;8'h42:seg_data=8'b1100_0001;8'h43:seg_data=8'b0110_0011;8'h44:seg_data=8'b1000_0101;8'h45:seg_data=8'b0110_0001;8'h46:seg_data=8'b0111_0001;default:seg_data=8'b1111_1111;endcaseend endmodule。
