原创 用verilog设计串口发送模块 带激励源(原创)

2008-8-7 09:25 6993 9 10 分类: FPGA/CPLD

学单片机时是从串口开始的,学FPGA仍旧从串口开始,谁让它是最简单的呢?
串口发送模块对外接口为: (下面给出的仅为1启动位,8个数据位,1个停止位,无奇偶校验)
            发送管脚     : txd_pin
            正在发送标志 : finish_F
            送数据接口   : bus
            波特率时钟   : clock
            复位信号     :  reset
            启动发送信号 :  load_bus_reg
module uart_emitter(txd_pin,finish_F,bus,clock,reset,load_bus_reg);
input load_bus_reg;                       
input clock;
input reset;
input [7:0] bus;//并行总线
output txd_pin;
output finish_F;//0:正在发送,1:移位寄存器空
reg finish_F;
reg txd_pin;

reg[7:0] bus_reg;//并行输入缓冲
reg[3:0] state;
//并-串状态机Gray码编码
parameter  idle="4"'b0000;
parameter  bit0=4'b0001;
parameter  bit1=4'b0011;
parameter  bit2=4'b0010;
parameter  bit3=4'b0110;
parameter  bit4=4'b0111;
parameter  bit5=4'b0101;
parameter  bit6=4'b0100;
parameter  bit7=4'b1100;
parameter  bit8=4'b1101;
parameter  bit9=4'b1111;
parameter  over="4"'b1110;
//////////////////////////////////////////
always@(posedge clock or negedge reset)
if(!reset)
    begin
    state<=idle;
    txd_pin<=1'b1;
    finish_F<=1;
    end   
else
    case(state)
        idle :
        begin
            if(load_bus_reg)
                begin
                bus_reg<=bus;
                state<=bit0;
                end
            else
                begin
                state<=idle;
                finish_F<=1;
                end     
       end
       bit0 : begin txd_pin<=1'b0;state<=bit1; finish_F<=0; end//bit0
       bit1 : begin txd_pin<=bus_reg[0];state<=bit2;end//bit1
       bit2 : begin txd_pin<=bus_reg[1];state<=bit3;end//bit2
       bit3 : begin txd_pin<=bus_reg[2];state<=bit4;end//bit3
       bit4 : begin txd_pin<=bus_reg[3];state<=bit5;end//bit4
       bit5 : begin txd_pin<=bus_reg[4];state<=bit6;end//bit5
       bit6 : begin txd_pin<=bus_reg[5];state<=bit7;end//bit6
       bit7 : begin txd_pin<=bus_reg[6];state<=bit8;end//bit7
       bit8 : begin txd_pin<=bus_reg[7];state<=bit9;end//bit8
       bit9 : begin txd_pin<=1'b1; state<=over;     end//bit9
       over : begin finish_F<=1'b1;state<=idle;     end
       default : begin state<=idle;                 end
    endcase
endmodule
 
提串口发送,就不能不提时钟分频,因为上边的模块用的就是实际波特率,
而我们电路板上不可能刚好接成串口的频率时钟,所以就需要用现有的时钟分频得到串口时钟,
下边给出的是为40M的源时钟时,串口对应的分频设置:
//===========================================================
// 40MHz = 40,000,000 Hz 
// 40MHz ~~~ 8*115200*11*4
`define Baudrate_preDiv        11

`define Baudrate_115200_b      2
`define Baudrate_115200_v      3     // 3.9457 ~~~~ 4
 
`define Baudrate_57600_b       3
`define Baudrate_57600_v       7     // 7.89    ~~~~ 8
 
`define Baudrate_38400_b       4
`define Baudrate_38400_v       11     // 11.837  ~~~ 12

`define Baudrate_19200_b       5
`define Baudrate_19200_v       23     // 23.674  ~~~ 24

`define Baudrate_9600_b        6
`define Baudrate_9600_v        46    // 47.348 ~~~ 47
//============================
`define BAUD_RATE_USE_b   2 //115200------已测试OK
`define BAUD_RATE_USE_v   3
//===========================================================
module uart_clk(sys_clock,reset,uart_rx_clk,uart_tx_clk);
input sys_clock;
input reset;
output uart_rx_clk;  // 串口接收的采样时钟
output uart_tx_clk;  // 串口发送的时钟

wire sys_clock_by_11;

divide_by_11    divide_11(sys_clock,reset,sys_clock_by_11);
divide_by_xx    divide_xx(sys_clock_by_11,reset,uart_rx_clk,uart_tx_clk);

endmodule
/////////////////////
module divide_by_11(sys_clock,reset,sys_clock_by_11);
input sys_clock;
input reset;
output sys_clock_by_11;
wire sys_clock_by_11;
reg [3:0] temp;

assign  sys_clock_by_11=temp[3];

always@(posedge sys_clock or negedge reset)
    if(!reset)
        temp<=0;
    else       
        begin
        if(temp==(`Baudrate_preDiv-1)) temp<=0;
        else temp<=temp+1;
        end   
endmodule
//////////////////////////
module divide_by_xx(sys_clock_11,reset,clock,sample_clk);
input reset;
input sys_clock_11;
output clock;
output sample_clk;

wire clock;
wire sample_clk;

reg[(`BAUD_RATE_USE_b-1):0] temp;
reg[2:0] temp0;

assign sample_clk=temp0[2];
assign clock = temp[(`BAUD_RATE_USE_b-1)];

always@(posedge sys_clock_11 or negedge reset)
    if(!reset)
        temp<=0;
    else begin
        if (temp==`BAUD_RATE_USE_v) temp<=0;
        else temp<=temp+1;
    end
   
always@( posedge clock or negedge reset)
    if(!reset)
        temp0<=0;
    else begin
        if(temp0==7) temp0<=0;
        else temp0<=temp0+1;
    end   
endmodule

最外层的调用接用,
uart_clk UartClock(.sys_clock(clk),
                   .reset(rst),
                   .uart_rx_clk(uart_rxclk),
                   .uart_tx_clk(uart_txclk));
                  
uart_emitter UartTx(.txd_pin(txdPin),
                    .finish_F(txFlgPin),
                    .bus(tx_reg),
                    .clock(uart_txclk),
                    .reset(rst),
                    .load_bus_reg(tx_dat_rdy));                  
设置UCF文件分配好管脚就可以用来发送数据了,但要注意目前我可是没有给数据源噢,
不过也可以写个模块模拟产生一个源噢,然后就可以源源不断地发送数据到PC端了,呵呵,
stimulus_uart_tx gentxq(
.clk(buzzerClk),//产生源数据的时钟  我用的是0.0625s
.txStart(txFlgPin),//发送状态标志,避免一个字符发N次,
.reset(rst), 
.databus(tx_reg),  //产生要发送的数据;
.data_rdy(tx_dat_rdy),//启动发送,只维持一个发送时钟周期
.txFlgpin(txRdyPin));  //这个是我留的一个测试点,LED
把全部代码编译生成BIT文件后写入,就看见复位一次就发送出"123.....z"的串,
这个激励是由模拟的激励模块产生的噢,

PARTNER CONTENT

文章评论1条评论)

登录后参与讨论

用户188696 2010-5-8 23:00

你好,我现在也在弄串口,想请教一下复位信号怎末给出的
相关推荐阅读
walnutcy_696810119 2012-11-21 08:37
Linux下使用smartCOM调试串口
在Windows下的串口调试一直使用sscom,在Linux下只找到一个cutecom,用了几次,很不喜欢,就着手开发了一款自己的串口调试工具,smartCOM。 smartCOM介绍:http...
walnutcy_696810119 2012-03-29 18:12
【博客大赛】原创--测量基础:什么是测量
写在正文之前: 适逢EDNChina搞活动,而我本人也算在测量业工作,就一起作下笔记吧。若有错误,请大家一起斧正。笔者写本文一方面是梳理知识,另一方面也希望与大家探讨有关测量的知识、应用等,希...
walnutcy_696810119 2011-12-20 18:29
GLONASS 15年来,首次实现24颗星在轨可用
  EDN的博客改版后,不太好用,在SINA重开一个,不过重点改为关注GNSS行业新闻 http://blog.sina.com.cn/s/blog_7420cd1701012en9....
walnutcy_696810119 2011-12-20 17:49
逆向工程第一步:通信协议分析
工程中常有这样的事,想分析下其他知名公司产品中的通信协议,以便生产设计兼容产品。 1) 逆向工程,首先要了解产品,知己知彼,百战不怠;     去年受命想仿一款GARMIN的导航盒,但无法...
walnutcy_696810119 2011-11-14 11:30
通用代码调试方法 (Keil, VCC)
调试代码一般需要定位问题,这里给出一个解决方案, 一般的编译器均支持这些宏指令。   #define DEBUG_WALT_1113     1 extern void log_t...
EE直播间
更多
我要评论
1
9
关闭 站长推荐上一条 /3 下一条