sasinop 发表于 2013-5-8 10:24:17

请教Verilog 串口,不加校验位

`timescale 1ns / 1ps
////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date:    21:50:13 10/02/07
// Design Name:   
// Module Name:    rs232
// Project Name:   
// Target Device:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
////////////////////////////////////////////////////////////////////////////////
module rs232(clk50,rst,rxd,txd,led,led2,led3,led4);

        input clk50,rst;
        input rxd;
        output txd;
        output led,led2;
        output led3,led4;
       
        reg txd;
        reg rxd_reg;
        reg led; //对应开发板上第8个LED灯
        reg led2; //对应开发板上第七个LED灯
        reg led3;
        reg led4;
       
        wire clk50;

        reg waddr;
        reg raddr;
        reg wdata;
        wire rdata;
        reg wea;

        reg DRI_state;//驱动状态,输出状态
        reg REV_state;        //输入状态
        reg REV_counter,DRI_counter;
//        reg REV_counter,DRI_counter; //for test
        reg received_char;//接收到一个字节后为1,否则为0

        reg rev_char; //接收到的字符
        reg rev_check;   //接收到字符的校验位
        reg send_char; //要发送的字符
        reg send_check;   //发送字符的校验位,偶校验
        reg send_char_tmp;
        reg start_send_char;//为1时表示要发送一个字符,字符为send_char
        reg send_char_over; //发送一个字符结束后变为1
       
        reg rev_bits_count; //记录接收一个字符8位里的多少位
        reg send_bits_count;//记录发送一个字符8位里的多少位

        reg response; //为1时表示收到读取数据的命令,响应开始
        reg CHAR_REV_state;// 字符接收状态机
        reg       CHAR_DRI_state;//字符发送状态机

//        parameter DELAYCOUNT=10'b01_0100_0100;//324+1+1=326
        parameter DELAYCOUNT= 14'b01_0100_0101_0110; //5206+1+1=5208
//        parameter DELAYCOUNT=2'b10;//for test
        parameter BITS_PER_CHAR=3'b110;//6+1+1=8

        parameter REV_IDLE=3'b000,REV_START=3'b001,REV_BIT=3'b010,REV_CHECK=3'b101,REV_STOP=3'b100; //CHECK为校验位状态

        parameter DRI_IDLE=3'b000,DRI_START=3'b001,DRI_BIT=3'b010,DRI_CHECK=3'b101,DRI_STOP=3'b100;

        parameterCHAR_REV_IDLE=3'b000,CHAR_REV_CHAR2=3'b001,CHAR_REV_CHAR3=3'b010,CHAR_REV_CHAR4=3'b100;

        parameterCHAR_DRI_IDLE=4'b0000,CHAR_DRI_ADDR=4'b0001,CHAR_DRI_CHAR2=4'b0010,CHAR_DRI_CHAR3=4'b0011,
                CHAR_DRI_CHAR4=4'b0100,CHAR_DRI_DATA1=4'b0101,CHAR_DRI_DATA2=4'b0110,CHAR_DRI_DATA3=4'b1000,
                CHAR_DRI_DATA4=4'b1001,CHAR_DRI_SUM=4'b0111;
       
        parameter REV_ADDR=8'hE4,REV_CHAR2=8'h00,REV_CHAR3=8'h01,REV_CHAR4=8'h04;
        parameter DRI_ADDR=8'hE4,DRI_CHAR2=8'hE1,DRI_CHAR3=8'h01,DRI_CHAR4=8'h04;
       
        always @ (posedge clk50)
        begin
                if(~rst)
                begin
                        rxd_reg<=1;
                        led2<=0;
                        led3<=0;
                        led4<=0;
                end
                else
                begin
                        rxd_reg<=rxd;
                        if(~rxd_reg)
                        begin
                                led2<=1; //PC机向串口发送数据时,该灯点亮
                                led3<=1;
                                led4<=1;
                        end
                end
        end

//串口字符接收状态机,根据最开始从串口接收到的四个字符来判断是不是建立了连接

always @ (posedge clk50)
        if(~rst)
        begin
                response<=0;
                CHAR_REV_state<=CHAR_REV_IDLE; //b'000
                led<=1;
               
        end
        else if(~wea)
        begin
                case(CHAR_REV_state)
                        CHAR_REV_IDLE:
                        begin
                                CHAR_REV_state<=CHAR_REV_IDLE;
                                response<=0;
                                led<=1;
                                //led4<=1;
                                if(received_char) //收到一个字符
                                begin
                                        if(rev_char==REV_ADDR)
                                        begin
                                                CHAR_REV_state<=CHAR_REV_CHAR2;
                                        end
                                end
                        end
                        CHAR_REV_CHAR2:
                        begin
                                if(received_char)
                                begin
                                        if(rev_char==REV_CHAR2)
                                        begin
                                                CHAR_REV_state<=CHAR_REV_IDLE;
                                                response<=1;
                                                led<=0;
                                                //led4<=0;
                                        end       
                                        else
                                                CHAR_REV_state<=CHAR_REV_IDLE;
                                end
                        end
               
                        default:
                                CHAR_REV_state<=CHAR_REV_IDLE;
        endcase
end

//串口字符发送状态机
always @ (posedge clk50)
        if(~rst)
        begin
                start_send_char<=0;
                CHAR_DRI_state<=CHAR_DRI_IDLE;
                raddr<=0;
        end
        else if(~wea)
        begin
                case(CHAR_DRI_state)
                        CHAR_DRI_IDLE:
                        begin
                                CHAR_DRI_state<=CHAR_DRI_IDLE;
                                start_send_char<=0;
                                raddr<=0;
                                if(response) //为1时表示收到PC机的命令,开始输出数据
                                begin
                                        CHAR_DRI_state<=CHAR_DRI_ADDR;
                                        send_char_tmp<=DRI_ADDR;
                                        start_send_char<=1;
                                end
                        end
                        CHAR_DRI_ADDR:
                        begin
                                start_send_char<=0;
                                if(send_char_over)
                                begin
                                        CHAR_DRI_state<=CHAR_DRI_CHAR2;
                                        send_char_tmp<=DRI_CHAR2;
                                        start_send_char<=1;
                                end
                        end
                        CHAR_DRI_CHAR2:
                        begin
                                start_send_char<=0;
                                if(send_char_over)
                                begin
                                        CHAR_DRI_state<=CHAR_DRI_DATA1;
                                        send_char_tmp<=rdata;
                        //                send_char_tmp<=raddr;                               
                                        start_send_char<=1;
                                        raddr<=raddr+1;
                                end
                        end
               
                        CHAR_DRI_DATA1:
                        begin
                                start_send_char<=0;
                                if(raddr==7'd20)
                                        CHAR_DRI_state<=CHAR_DRI_IDLE;
                                else if(send_char_over)
                                begin
                                        CHAR_DRI_state<=CHAR_DRI_DATA1;
                                        send_char_tmp<=rdata;
                                        start_send_char<=1;
                                        raddr<=raddr+1;
                                end
                        end
       
                        default:
                                CHAR_DRI_state<=CHAR_DRI_IDLE;
        endcase
end



/*******************************************************************/
//单个字符接收状态机       
always @ (posedge clk50)
        if(~rst)
        begin
                rev_char<=8'b0;
                REV_counter<=DELAYCOUNT;
                REV_state<=REV_IDLE;
                rev_bits_count<=BITS_PER_CHAR;
                received_char<=0;
        end
        else if(~wea)
                case(REV_state)
                        REV_IDLE:
                        begin
                                REV_counter<=DELAYCOUNT;
                                rev_bits_count<=BITS_PER_CHAR;
                                received_char<=0;
                                rev_check<=0;
                                rev_char<=8'b0;
                                if(~rxd_reg)//为低,起始位
                                begin
                                        REV_state<=REV_START;       
                                end       
                        end
                        REV_START:
                        begin
                                if(REV_counter)//计数完成
                                begin
                                        REV_state<=REV_BIT;
                                        REV_counter<=DELAYCOUNT;
                                end
                                else
                                        REV_counter<=REV_counter-1;                               
                        end
                        REV_BIT:
                        begin


                                        if(REV_counter)//计数完成
                                        begin
                                                REV_state<=REV_BIT;
                                                REV_counter<=DELAYCOUNT;
                                               
                                                if(rev_bits_count)
                                                begin
                                                        REV_state<=REV_CHECK;
                                                        REV_counter<=DELAYCOUNT;

                                                end
                                                else
                                                        rev_bits_count<=rev_bits_count-1;
                                        end
                                        else
                                                REV_counter<=REV_counter-1;
                                        if(REV_counter==2500) //在延时中间取值
                                //        if(REV_counter==1)
                                        begin
                                                rev_char<={rxd_reg,rev_char}; //rev_char右移一位,低位在前
                                        end
                       
                        end
                        REV_CHECK:
                        begin
                                if(REV_counter)//计数完成
                                begin
                                        REV_state<=REV_STOP;
                                        REV_counter<=DELAYCOUNT;   //对校验位没有做处理!!!!!!!!!!!!!!!!!!!!!!!!
                                        received_char<=1;//接受到一个字符,指示总状态机接收到一个字符
                                end
                                else
                                        REV_counter<=REV_counter-1;

                                if(REV_counter==2500)
                        //        if(REV_counter==1)
                                begin
                                        rev_check<=rxd_reg; //接收到校验位
                                end       
                        end                        REV_STOP:        //一个停止位
                        begin
                                received_char<=0;
                                if(REV_counter)//计数完成
                                begin
                                        REV_state<=REV_IDLE;
                                        REV_counter<=DELAYCOUNT;
                                end
                                else
                                        REV_counter<=REV_counter-1;
                        end
                        default:
                                REV_state<=REV_IDLE;
                endcase

//单个字符发送状态机       
always @ (posedge clk50)
        if(~rst)
        begin
                DRI_counter<=DELAYCOUNT;
                DRI_state<=DRI_IDLE;
                send_bits_count<=BITS_PER_CHAR;
                send_char_over<=0;
                txd<=1;//高表示空闲
        end
        else if(~wea)
                case(DRI_state)
                        DRI_IDLE:
                        begin
                                DRI_counter<=DELAYCOUNT;
                                send_char_over<=0;
                                txd<=1;
                                send_check<=0;
                                send_bits_count<=BITS_PER_CHAR;
                                if(start_send_char)//要发送一个字符
                                begin
                                        txd<=0; //起始位
                                        DRI_state<=DRI_START;
                                        send_char<=send_char_tmp;
                                        send_check<=^send_char_tmp; //偶校验位为send_char_tmp的8数据位按位异或的结果
                                end       
                        end
                        DRI_START:
                        begin
                                if(DRI_counter)//计数完成
                                begin
                                        DRI_state<=DRI_BIT;
                                        txd<=send_char;
                                        send_char<={send_char,send_char}; //右移一位
                                        DRI_counter<=DELAYCOUNT;
                                end
                                else
                                        DRI_counter<=DRI_counter-1;                               
                        end
                        DRI_BIT:
                        begin


                                        if(DRI_counter)//计数完成
                                        begin
                                       
                                                if(send_bits_count)
                                                begin
                                                        DRI_state<=DRI_CHECK;
                                                        txd<=send_check;
                                                        DRI_counter<=DELAYCOUNT;
                                       
                                                end
                                                else
                                                begin
                                                        DRI_state<=DRI_BIT;
                                                        txd<=send_char;
                                                        send_char<={send_char,send_char}; //右移一位
                                                        DRI_counter<=DELAYCOUNT;
                                                        send_bits_count<=send_bits_count-1;
                                                end
                                        end
                                        else
                                                DRI_counter<=DRI_counter-1;
                       
                        end
                        DRI_CHECK:
                        begin
                                if(DRI_counter)//计数完成
                                begin
                                        DRI_state<=DRI_STOP;
                                        txd<=1; //停止位
                                        DRI_counter<=DELAYCOUNT;
                                       
                                end
                                else
                                        DRI_counter<=DRI_counter-1;
                        end
                        DRI_STOP:        //一个停止位
                        begin
                                if(DRI_counter)//计数完成
                                begin
                                        DRI_state<=DRI_IDLE;
                                        DRI_counter<=DELAYCOUNT;
                                        send_char_over<=1; //发送完一个字符
                                end
                                else
                                        DRI_counter<=DRI_counter-1;
                        end
                        default:
                                DRI_state<=DRI_IDLE;
                endcase
//上电复位后,写将20个数写入BlockRam
        always @ (posedge clk50)
        begin
                if(~rst)
                begin
                        waddr<=0;
                        wdata<=0;
                        wea<=1;
                end
                else
                begin
                        if(waddr==7'd20)
                        begin
                                wea<=0;
                                waddr<=0;
                                wdata<=0;
                        end
                        else
                        begin
                                waddr<=waddr+1;
                                wdata<=wdata+1;
                        end
                end       
        end

//调用BlockRam块
        ram_dataout ram(
                .addra(waddr),
                .addrb(raddr),
                .clka(clk50),
                .clkb(clk50),
                .dina(wdata),
                .doutb(rdata),
                .wea(wea));


endmodule

这个是开发板自带的程序,功能就是 ,通过串口发送 E4 00 ,然后FPGA 返回 E4 41 + 20个事先写入RAM里的数据

PC 发 FPGA时, 串口要设置校验位,,偶校验,
现在想把校验的功能去掉
是不是把 代码中红色部分去掉就可以了?

谢谢

sasinop 发表于 2013-5-8 10:32:55

好像不行


jm2011 发表于 2013-5-8 16:28:25

REV_state<=REV_CHECK; 修改为:REV_state<=REV_STOP;

sasinop 发表于 2013-5-8 16:56:02

jm2011 发表于 2013-5-8 16:28 static/image/common/back.gif
REV_state

是了一下

不行啊

去掉这句,,,发 E4 00 后,啥也不回了,,调试软件带校验位或不带校验位,都不回数据。

加这句后, 带校验位的话,回 22个字节数据,,,不带校验位,也是啥也不回

深海烟花 发表于 2013-5-8 17:11:21

楼主代码太凌乱了

sasinop 发表于 2013-5-8 18:38:50

深海烟花 发表于 2013-5-8 17:11 static/image/common/back.gif
楼主代码太凌乱了

是的
开发板自带的程序...

深海烟花 发表于 2013-5-9 22:36:45

sasinop 发表于 2013-5-8 18:38 static/image/common/back.gif
是的
开发板自带的程序...

建议楼主分模块写,这样比较好.

sasinop 发表于 2013-5-10 04:54:01

深海烟花 发表于 2013-5-9 22:36 static/image/common/back.gif
建议楼主分模块写,这样比较好.

谢谢建议

努力中...

刚开始玩...
页: [1]
查看完整版本: 请教Verilog 串口,不加校验位