题解 | 求最小公倍数
求最小公倍数
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延时几拍在赋值,就会产生中间结果的提前到位波形错误