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
相关推荐
9527华安10 小时前
FPGA纯verilog实现 2.5G UDP协议栈,基于1G/2.5G Ethernet PCS/PMA or SGMII,提供14套工程源码和技术支持
5g·fpga开发·udp·ethernet·verilog·sgmii·2.5g udp
奋斗的牛马17 小时前
硬件基础知识-电容(一)
单片机·嵌入式硬件·学习·fpga开发·信息与通信
li星野18 小时前
打工人日报#20251110
fpga开发
0基础学习者1 天前
跨时钟域处理
fpga开发·verilog·数字ic
FPGA_小田老师1 天前
Xilinx FIFO Generate IP核(8):FIFO设计常见问题与解决方案
fpga开发·fifo generate·fifo常见问题·fifo异常定位·fifo丢数·fifo读数重复
范纹杉想快点毕业1 天前
100道关于STM32的问题解答共十万字回答,适用入门嵌入式软件初级工程师,筑牢基础,技术积累,校招面试。
驱动开发·单片机·嵌入式硬件·fpga开发·硬件工程
知识充实人生2 天前
时序收敛方法二:Fanout优化
fpga开发·fanout·高扇出·时序收敛
Js_cold2 天前
(* MARK_DEBUG=“true“ *)
开发语言·fpga开发·debug·verilog·vivado
Js_cold2 天前
(* clock_buffer_type=“NONE“ *)
开发语言·fpga开发·verilog·vivado·buffer·clock
深圳光特通信豆子2 天前
TTL光模块:短距离传输场景的优选方案
fpga开发