FPGA project: uart_rs485

module ctrl(
    input       wire                sys_clk     ,
    input       wire                sys_rst_n   ,
    input       wire                key_w       ,
    input       wire                key_b       ,

    output      wire        [7:0]   po_data     , // 由于w_en 与b_en 使能信号是reg型,虽然po_data是时序逻辑,但是相对于按键按下信号,仍然要延后一个时钟周期。
    output      reg                 po_flag       // 所以po_data 应该用reg
);
    reg  w_en ;
    reg  b_en ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            w_en <= 1'b0 ;
        end else begin
            if(key_w == 1'b1) begin
                w_en <= ~w_en ;
            end else begin
                if(key_b == 1'b1) begin
                    w_en <= 1'b0 ;
                end else begin
                    w_en <= w_en ;
                end
            end
        end 
    end
    // b_en
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            b_en <= 1'b0 ;
        end else begin
            if(key_b == 1'b1) begin
                b_en <= ~b_en ;
            end else begin
                if(key_w == 1'b1) begin
                    b_en <= 1'b0 ;
                end else begin
                    b_en <= b_en ;
                end
            end
        end 
    end

    // [7:0]   po_data     ,
    assign po_data = {6'd0,w_en,b_en} ;
    //         po_flag   
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            po_flag <= 1'b0 ;
        end else begin
            po_flag <= key_b || key_w ;
        end
    end 
endmodule

`timescale 1ns/1ns
module test_ctrl();
    reg                   sys_clk     ;
    reg                   sys_rst_n   ;
    reg                   key_w       ;
    reg                   key_b       ;

    wire        [7:0]     po_data     ;
    wire                  po_flag     ;

ctrl ctrl_insert(
    .sys_clk            ( sys_clk   )   ,
    .sys_rst_n          ( sys_rst_n )   ,
    .key_w              ( key_w     )   ,
    .key_b              ( key_b     )   ,

    .po_data            ( po_data   )   ,
    .po_flag            ( po_flag   )     
);
    parameter CYCLE = 20 ;

    initial begin
        sys_clk    = 1'b1 ;
        sys_rst_n <= 1'b0 ;
        key_w     <= 1'b0 ;
        key_b     <= 1'b0 ;
        #( CYCLE * 10 )   ;
        sys_rst_n <= 1'b1 ;
        #( 210 )          ;
        sys_rst_n <= 1'b0 ;
        #( 10 )           ;
        #( CYCLE * 10 )   ;
        sys_rst_n <= 1'b1 ;
        #( CYCLE * 100  ) ;

        key_w     <= 1'b1 ;
        #( CYCLE )        ;
        key_w     <= 1'b0 ;
        #( CYCLE * 500)   ;

        key_b     <= 1'b1 ;
        #( CYCLE )        ;
        key_b     <= 1'b0 ;
        #( CYCLE * 500)   ;

        key_w     <= 1'b1 ;
        #( CYCLE )        ;
        key_w     <= 1'b0 ;
        #( CYCLE * 500)   ;

        key_b     <= 1'b1 ;
        #( CYCLE )        ;
        key_b     <= 1'b0 ;
        #( CYCLE * 500)   ;
        
        key_w     <= 1'b1 ;
        #( CYCLE )        ;
        key_w     <= 1'b0 ;
        #( CYCLE * 500)   ;

        key_w     <= 1'b1 ;
        #( CYCLE )        ;
        key_w     <= 1'b0 ;
        #( CYCLE * 500)   ;

        $stop             ;
    end

    always #( CYCLE / 2 ) sys_clk = ~sys_clk ;


endmodule

module be_ctrl(
    input       wire                sys_clk     ,
    input       wire                sys_rst_n   ,
    // input       wire                key_w       , // 作为被控制板模块的ctrl 一些端口信号用不到的。
    // input       wire                key_b       ,
    input       wire        [7:0]   pi_data     , 
    input       wire                pi_flag     , 
    input       wire        [3:0]   led_w       , 
    input       wire        [3:0]   led_b       , 

    // output      wire        [7:0]   po_data     ,
    // output      wire                po_flag     
    output      reg         [3:0]   led_out       // 也可以用组合逻辑
);
    reg  w_en ;
    reg  b_en ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            w_en <= 1'b0 ;
        end else begin
            if(pi_data[1]) begin
                w_en <= ~w_en ;
            end else begin
                if(pi_data[0]) begin
                    w_en <= 1'b0 ;
                end else begin
                    w_en <= w_en ;
                end
            end
        end 
    end
    // b_en
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            b_en <= 1'b0 ;
        end else begin
            if(pi_data[0]) begin
                b_en <= ~b_en ;
            end else begin
                if(pi_data[1]) begin
                    b_en <= 1'b0 ;
                end else begin
                    b_en <= b_en ;
                end
            end
        end 
    end

    // [3:0]   led_out 
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            led_out <= 3'd0 ;
        end else begin
            if(w_en == 1'b1) begin
                led_out <= led_w;
            end else begin
                if(b_en == 1'b1) begin
                    led_out <= led_b;
                end else begin
                    led_out <= led_out ;
                end
            end 
        end
    end
endmodule

`timescale 1ns/1ns
module test_be_ctrl();
    reg                   sys_clk     ;
    reg                   sys_rst_n   ;
    reg         [7:0]     pi_data_w   ;
    reg                   pi_flag_w   ;

    wire        [3:0]     led_out     ;

    
    // 由例化的模块产生
    wire        [3:0]     led_w_w       ;
    wire        [3:0]     led_b_w       ;

water_led  
#(
    .MAX_CNT                ( 25'd25_0) // 00_000 
)water_led_insert
(
    .sys_clk                ( sys_clk    ) ,
    .sys_rst_n              ( sys_rst_n  ) ,

    .led                    ( led_w_w )
);
breath_led 
#(
    .CNT_1US            ( 5          )  ,
    .CNT_1K             ( 10         ) 
)breath_led_insert
(
    .sys_clk            ( sys_clk    )  ,
    .sys_rst_n          ( sys_rst_n  )  ,

    .led_out_1          ( led_b_w[0] )  ,
    .led_out_2          ( led_b_w[1] )  ,
    .led_out_3          ( led_b_w[2] )  ,
    .led_out_4          ( led_b_w[3] )   
);

be_ctrl be_ctrl_insert(
    .sys_clk            ( sys_clk   ) ,
    .sys_rst_n          ( sys_rst_n ) ,
    .pi_data            ( pi_data_w ) , 
    .pi_flag            ( pi_flag_w ) , 
    .led_w              ( led_w_w   ) , 
    .led_b              ( led_b_w   ) , 

    .led_out            ( led_out   )     
);
    parameter CYCLE = 20 ;

    initial begin
        sys_clk    = 1'b1 ;
        sys_rst_n <= 1'b0 ;
        pi_data_w <= 8'd0 ;
        pi_flag_w <= 1'b0 ;
        #( CYCLE * 10 )   ;
        sys_rst_n <= 1'b1 ;
        #( 210 )          ;
        sys_rst_n <= 1'b0 ;
        #( 10 )           ;
        #( CYCLE * 10 )   ;
        sys_rst_n <= 1'b1 ; // 复位释放。
        #( 50 * CYCLE)    ;
        pi_data_w <= 8'd1 ; // 呼吸灯控制按键按下
        pi_flag_w <= 1'b1 ;
        #( CYCLE )        ;
        pi_data_w <= 8'd0 ;
        pi_flag_w <= 1'b0 ;
        #( CYCLE * 500 )  ;

        pi_data_w <= 8'd1 ; // 呼吸灯控制按键按下
        pi_flag_w <= 1'b1 ;
        #( CYCLE )        ;
        pi_data_w <= 8'd0 ;
        pi_flag_w <= 1'b0 ;
        #( CYCLE * 500 )  ;

        pi_data_w <= 8'd2 ; // 流水灯控制按键按下
        pi_flag_w <= 1'b1 ;
        #( CYCLE )        ;
        pi_data_w <= 8'd0 ;
        pi_flag_w <= 1'b0 ;
        #( CYCLE * 500 )  ;
        
        pi_data_w <= 8'd1 ; // 呼吸灯控制按键按下
        pi_flag_w <= 1'b1 ;
        #( CYCLE )        ;
        pi_data_w <= 8'd0 ;
        pi_flag_w <= 1'b0 ;
        #( CYCLE * 500 )  ;
        $stop ;
    end

    always #( CYCLE / 2 ) sys_clk = ~sys_clk ;


endmodule
流水灯模块与呼吸灯模块是之前工程里的。

module rs_485_tx (
    input       wire            sys_clk   ,
    input       wire            sys_rst_n ,
    input       wire   [7:0]    pi_data   ,
    input       wire            pi_flag   ,

    output      reg             tx        ,
    output      reg             re         
);

    // reg signal define
    reg             pi_flag_r   ;
    reg     [7:0]   pi_data_r   ;
    reg             work_en     ;
    reg     [12:00] baud_cnt    ;
    reg             bit_flag    ;
    reg     [ 3: 0] bit_cnt     ;
    // pi_flag_r     ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            pi_flag_r <= 1'b0 ;
        end else begin
            if(pi_flag == 1'b1) begin
                pi_flag_r <= 1'b1 ;
            end else begin
                pi_flag_r <= 1'b0 ;
            end
        end
    end
    // [7:0] pi_data_r   ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            pi_data_r <= 1'b0 ;
        end else begin
            if(pi_flag == 1'b1) begin
                pi_data_r <= pi_data ;
            end else begin
                pi_data_r <= pi_data_r ;
            end
        end
    end
    //        work_en      ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            work_en <= 1'b0 ;
        end else begin
            if(baud_cnt == 13'd5027 && bit_cnt == 4'd9) begin
                work_en <= 1'b0 ;
            end else begin
                if(pi_flag_r == 1'b1) begin
                    work_en <= 1'b1 ;
                end else begin
                    work_en <= work_en ;
                end
            end
        end
    end
    // [12:00] baud_cnt    ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            baud_cnt <= 13'd0 ;
        end else begin
            if(work_en == 1'b1 && baud_cnt == 13'd5027 || work_en == 1'b0) begin
                baud_cnt <= 13'd0 ;
            end else begin
                if(work_en == 1'b1) begin
                    baud_cnt <= baud_cnt + 1'b1 ;
                end else begin
                    baud_cnt <= 13'd0 ;
                end
            end
        end
    end
    //         bit_flag    ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            bit_flag <= 1'b0 ;
        end else begin
            if(baud_cnt == 13'd5026) begin // 野火上是等于 1 .
                bit_flag <= 1'b1 ;
            end else begin
                bit_flag <= 1'b0 ;
            end
        end
    end
    // [ 3: 0] bit_cnt     ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            bit_cnt <= 4'd0 ;
        end else begin
            if(bit_flag == 1'b1 && bit_cnt == 4'd9 || work_en == 1'b0) begin
                bit_cnt <= 4'd0 ;
            end else begin
                if(bit_flag == 1'b1) begin
                    bit_cnt <= bit_cnt + 1'b1 ;
                end else begin
                    bit_cnt <= bit_cnt ;
                end
            end
        end
    end

    // output signal
    // tx
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            tx <= 1'b1 ;
        end else begin
            if(work_en == 1'b1 && bit_cnt == 4'd0) begin
                tx <= 1'b0 ;
            end else begin
                if(work_en == 1'b1 && bit_cnt == 4'd9 || work_en == 1'b0) begin
                    tx <= 1'b1 ;
                end else begin
                    tx <= pi_data_r[bit_cnt - 1'b1] ;
                end
            end
        end
    end
    // re
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            re <= 1'b0 ;
        end else begin
            re <= work_en ;
        end
    end
endmodule

`timescale 1ns/1ns
module test_rs_485_tx();
    reg             sys_clk   ;
    reg             sys_rst_n ;
    reg    [7:0]    pi_data   ;
    reg             pi_flag   ;

    wire            tx        ;
    wire            re        ;


rs_485_tx rs_485_tx_insert(
    .sys_clk        ( sys_clk   ) ,
    .sys_rst_n      ( sys_rst_n ) ,
    .pi_data        ( pi_data   ) ,
    .pi_flag        ( pi_flag   ) ,

    .tx             ( tx        ) ,
    .re             ( re        )  
);
    parameter CYCLE = 20 ;

    initial begin
        sys_clk    = 1'b1 ;
        sys_rst_n <= 1'b0 ;
        pi_data <= 8'd0 ;
        pi_flag <= 1'b0 ;
        #( CYCLE * 10 )   ;
        sys_rst_n <= 1'b1 ;
        #( 210 )          ;
        sys_rst_n <= 1'b0 ;
        #( 10 )           ;
        #( CYCLE * 10 )   ;
        sys_rst_n <= 1'b1 ; // 复位释放。
        #( 50 * CYCLE)    ;
        pi_data <= 8'd1 ; // 呼吸灯控制按键按下
        pi_flag <= 1'b1 ;
        #( CYCLE )        ;
        pi_data <= 8'd0 ;
        pi_flag <= 1'b0 ;
        #( CYCLE * 96100 )  ;

        pi_data <= 8'd1 ; // 呼吸灯控制按键按下
        pi_flag <= 1'b1 ;
        #( CYCLE )        ;
        pi_data <= 8'd0 ;
        pi_flag <= 1'b0 ;
        #( CYCLE * 96100 )  ;

        pi_data <= 8'd2 ; // 流水灯控制按键按下
        pi_flag <= 1'b1 ;
        #( CYCLE )        ;
        pi_data <= 8'd0 ;
        pi_flag <= 1'b0 ;
        #( CYCLE * 96100 )  ;
        
        pi_data <= 8'd1 ; // 呼吸灯控制按键按下
        pi_flag <= 1'b1 ;
        #( CYCLE )        ;
        pi_data <= 8'd0 ;
        pi_flag <= 1'b0 ;
         #( CYCLE * 96100 )  ;
        $stop ;
    end

    always #( CYCLE / 2 ) sys_clk = ~sys_clk ;


endmodule
相关推荐
北城笑笑7 小时前
FPGA 14 ,硬件开发板分类详解,FPGA开发板与普通开发板烧录的区别
fpga开发·fpga
2202_754421548 小时前
一个计算频率的模块
驱动开发·fpga开发
小灰灰的FPGA9 小时前
低速接口项目之串口Uart开发(七)——如何在FPGA项目中实现自适应波特率串口功能
fpga开发
fei_sun1 天前
【Verilog】第一章作业
fpga开发·verilog
深圳市雷龙发展有限公司longsto1 天前
基于FPGA(现场可编程门阵列)的SD NAND图片显示系统是一个复杂的项目,它涉及硬件设计、FPGA编程、SD卡接口、NAND闪存控制以及图像显示等多个方面
fpga开发
9527华安1 天前
FPGA实现PCIE3.0视频采集转10G万兆UDP网络输出,基于XDMA+GTH架构,提供工程源码和技术支持
网络·fpga开发·udp·音视频·xdma·pcie3.0·万兆网
able陈1 天前
为什么verilog中递归函数需要定义为automatic?
fpga开发
fei_sun1 天前
【Verilog】第二章作业
fpga开发·verilog
碎碎思1 天前
如何使用 Vivado 从源码构建 Infinite-ISP FPGA 项目
fpga开发·接口隔离原则
江山如画,佳人北望2 天前
fpga-状态机的设计及应用
fpga开发