题解 | #使用握手信号实现跨时钟域数据传输#

使用握手信号实现跨时钟域数据传输

https://www.nowcoder.com/practice/2bf1b28a4e634d1ba447d3495134baac

使用状态机求解

`timescale 1ns/1ns

module data_driver(

    input clk_a,

    input rst_n,

    input data_ack,

    output reg [3:0]data,

    output reg data_req

    );

    //状态定义

    

    parameter IDLE = 5'd16;//初始状态

    parameter S_0 = 5'd0;

    parameter S_1 = 5'd1;

    parameter S_2 = 5'd2;

    parameter S_3 = 5'd3;

    parameter S_4 = 5'd4;

    parameter S_5 = 5'd5;

    parameter S_6 = 5'd6;

    parameter S_7 = 5'd7;

    parameter T_0 = 5'd8;

    parameter T_1 = 5'd9;

    parameter T_2 = 5'd10;

    parameter T_3 = 5'd11;

    parameter T_4 = 5'd12;

    parameter T_5 = 5'd13;

    parameter T_6 = 5'd14;

    parameter T_7 = 5'd15;

    //时钟计数器

    reg [2:0]cnt_timer;

    //状态寄存器定义

    reg [4:0]curr_state;

    reg [4:0]next_state;

    //状态转换条件

    always@(*)(1444584)begin

        case(curr_state)

            IDLE: next_state <= (cnt_timer == 3'd3)? S_0:IDLE;

            S_0: next_state <= data_ack? T_0:S_0;//发送数据0

            T_0: next_state <= (cnt_timer == 3'd4)? S_1:T_0;//时间间隔

            S_1: next_state <= data_ack? T_1:S_1;//发送数据1

            T_1: next_state <= (cnt_timer == 3'd4)? S_2:T_1;//时间间隔

            S_2: next_state <= data_ack? T_2:S_2;//发送数据2

            T_2: next_state <= (cnt_timer == 3'd4)? S_3:T_2;//时间间隔

            S_3: next_state <= data_ack? T_3:S_3;//发送数据3

            T_3: next_state <= (cnt_timer == 3'd4)? S_4:T_3;//时间间隔

            S_4: next_state <= data_ack? T_4:S_4;//发送数据4

            T_4: next_state <= (cnt_timer == 3'd4)? S_5:T_4;//时间间隔

            S_5: next_state <= data_ack? T_5:S_5;//发送数据5

            T_5: next_state <= (cnt_timer == 3'd4)? S_6:T_5;//时间间隔

            S_6: next_state <= data_ack? T_6:S_6;//发送数据6

            T_6: next_state <= (cnt_timer == 3'd4)? S_7:T_6;//时间间隔

            S_7: next_state <= data_ack? T_7:S_7;//发送数据7

            T_7: next_state <= (cnt_timer == 3'd4)? S_0:T_7;//时间间隔

            default: next_state <= S_0;

        endcase

    end

    //状态转换实现

    always@((487950916)posedge clk_a or negedge rst_n)begin

        if(!rst_n)

            curr_state <= IDLE;

        else

            curr_state <= next_state;

    end

    //状态输出

    always@((487950916)posedge clk_a or negedge rst_n)begin

        if(!rst_n)begin

            data <= 4'd0;

            data_req <= 1'b0;

            cnt_timer <= 3'd0;

        end

        else if(curr_state == IDLE)begin

            cnt_timer <= cnt_timer + 1'b1;

        end

        else if(curr_state == S_0)begin//发送数据0

            cnt_timer <= 3'd0;

            data <= 4'd0;//发送新数据

            data_req <= 1'b1;//拉高data_reg信号

        end

        else if(curr_state == T_0)begin//间隔5个时钟

            if(data_req)begin

                cnt_timer <= 3'd0;

                data_req <= 1'b0;//撤销data_reg

            end

            else begin

                cnt_timer <= cnt_timer + 1'b1;

                data_req <= 1'b0;

            end

        end

        else if(curr_state == S_1)begin//发送数据1

            data <= 4'd1;

            data_req <= 1'b1;

        end

        else if(curr_state == T_1)begin//间隔5个时钟

            if(data_req)begin

                cnt_timer <= 3'd0;

                data_req <= 1'b0;//撤销data_reg

            end

            else begin

                cnt_timer <= cnt_timer + 1'b1;

                data_req <= 1'b0;

            end

        end

        else if(curr_state == S_2)begin//发送数据2

            data <= 4'd2;

            data_req <= 1'b1;

        end

        else if(curr_state == T_2)begin//间隔5个时钟

            if(data_req)begin

                cnt_timer <= 3'd0;

                data_req <= 1'b0;//撤销data_reg

            end

            else begin

                cnt_timer <= cnt_timer + 1'b1;

                data_req <= 1'b0;

            end

        end

        else if(curr_state == S_3)begin//发送数据3

            data <= 4'd3;

            data_req <= 1'b1;

        end

        else if(curr_state == T_3)begin//间隔5个时钟

            if(data_req)begin

                cnt_timer <= 3'd0;

                data_req <= 1'b0;//撤销data_reg

            end

            else begin

                cnt_timer <= cnt_timer + 1'b1;

                data_req <= 1'b0;

            end

        end

        else if(curr_state == S_4)begin//发送数据4

            data <= 4'd4;

            data_req <= 1'b1;

        end

        else if(curr_state == T_4)begin//间隔5个时钟

            if(data_req)begin

                cnt_timer <= 3'd0;

                data_req <= 1'b0;//撤销data_reg

            end

            else begin

                cnt_timer <= cnt_timer + 1'b1;

                data_req <= 1'b0;

            end

        end

        else if(curr_state == S_5)begin//发送数据5

            data <= 4'd5;

            data_req <= 1'b1;

        end

        else if(curr_state == T_5)begin//间隔5个时钟

            if(data_req)begin

                cnt_timer <= 3'd0;

                data_req <= 1'b0;//撤销data_reg

            end

            else begin

                cnt_timer <= cnt_timer + 1'b1;

                data_req <= 1'b0;

            end

        end

        else if(curr_state == S_6)begin//发送数据6

            data <= 4'd6;

            data_req <= 1'b1;

        end

        else if(curr_state == T_6)begin//间隔5个时钟

            if(data_req)begin

                cnt_timer <= 3'd0;

                data_req <= 1'b0;//撤销data_reg

            end

            else begin

                cnt_timer <= cnt_timer + 1'b1;

                data_req <= 1'b0;

            end

        end

        else if(curr_state == S_7)begin//发送数据7

            data <= 4'd7;

            data_req <= 1'b1;

        end

        else if(curr_state == T_7)begin//间隔5个时钟

            if(data_req)begin

                cnt_timer <= 3'd0;

                data_req <= 1'b0;//撤销data_reg

            end

            else begin

                cnt_timer <= cnt_timer + 1'b1;

                data_req <= 1'b0;

            end

        end

    end

endmodule

//数据接收模块

module data_receiver(

    input clk_b,

    input rst_n,

    input [3:0]data,

    input data_req,

    output reg data_ack

);

    reg [3:0]data_reg;

always@((487950916)posedge clk_b or negedge rst_n)begin

    if(!rst_n)

        data_ack <= 1'b0;

    else if(data_req)begin//检测到此刻的data数据有效,拉高data_ack

        data_reg <= data;//储存数据

        data_ack <= 1'b1;

    end

    else

        data_ack <= 1'b0;

end

endmodule

全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务