题解 | 求最小公倍数

求最小公倍数

https://www.nowcoder.com/practice/ce067d6beee2413c8a26d37ca1a9431f

`timescale 1ns / 1ns
module lcm #(
    parameter DATA_W = 8
) (
    input       [  DATA_W-1:0] A,
    input       [  DATA_W-1:0] B,
    input                      vld_in,
    input                      rst_n,
    input                      clk,
    output wire [DATA_W*2-1:0] lcm_out,
    output wire [  DATA_W-1:0] mcd_out,
    output reg                 vld_out
);
    reg [DATA_W-1:0] a_reg, b_reg;
    reg [  DATA_W-1:0] mcd_reg;
    reg [2*DATA_W-1:0] mul_reg;
    localparam [1:0] IDLE = 2'b00;
    localparam [1:0] S_COMPARE = 2'b01;
    localparam [1:0] S_UPDATE = 2'b10;
    reg [1:0] cs, ns;
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            cs <= IDLE;
        end else begin
            cs <= ns;
        end
    end
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            ns <= IDLE;

            a_reg <= 0;
            b_reg <= 0;
            mul_reg <= 0;
            mcd_reg <= 0;

            vld_out <= 0;
        end else begin
            case (cs)
                IDLE: begin
                    ns <= vld_in ? S_COMPARE : IDLE;
                    if (vld_in) begin
                        a_reg   <= A;
                        b_reg   <= B;
                        mul_reg <= A * B;
                    end
                    vld_out <= 0;
                end
                S_COMPARE: begin
                    if (a_reg != b_reg) begin
                        ns <= S_COMPARE;
                        a_reg <= (a_reg > b_reg) ? b_reg : (b_reg - a_reg);
                        b_reg <= (a_reg > b_reg) ? (a_reg - b_reg) : a_reg;
                    end else begin
                        ns <= S_UPDATE;
                    end
                    vld_out <= 0;
                end
                S_UPDATE: begin
                    ns <= IDLE;
                    mcd_reg <= a_reg;
                    vld_out <= 1;
                end
                // default: begin
                //     ns <= IDLE;
                //     vld_out <= 0;
                // end

            endcase
        end
    end
    assign mcd_out = mcd_reg;
    assign lcm_out = mul_reg / mcd_reg;
endmodule

在这个题中我们一定要注意状态机的ns更新,因为!rst_n也是一个case,因此要在其中标明vld_out和ns的次态;

当然如果不想在!rst_n的标注我们可以在else.case中标明default,时序逻辑中可以没有default,但是如果上述两个都没有的话则会造成状态机无法自启动,比如!rst_n先拉高,后续ns延时几拍在赋值,就会产生中间结果的提前到位波形错误

全部评论

相关推荐

牛客42479632...:多投吧 我学c++就学了3个月都找到好几家实习了
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

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