列表

详情


VL75. 求最小公倍数

描述

       设计一个时序电路,输入2个无符号数,位宽可以通过参数DATA_W确定,输出这两个数的最小公倍数和最大公约数。

模块的接口信号图如下:

要求使用Verilog HDL语言实现,并编写testbench验证模块的功能。

输入描述

clk::时钟信号

rst_n:复位信号,低电平有效

A:输入信号,位宽可以通过DATA_W指定

B:输入信号,位宽可以通过DATA_W指定

vld_in:输入数据有效的指示信号

输出描述

lcm_out:输出最小公倍数

mcd_out:输出最大公约数

vld_out:输出数据有效的指示信号

原站题解

Verilog 解法, 执行用时: 0ms, 内存消耗: 0KB, 提交时间: 2022-08-05

`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*2-1:0]  mcd,a_buf,b_buf;
reg [DATA_W*2-1:0] mul_buf;
reg                 mcd_vld;
reg [1:0]           cur_st,nxt_st;
parameter IDLE= 2'b00,S0 = 2'b01, S1 = 2'b10, S2 = 2'b11;
//两段式状态机
always @(posedge clk or negedge rst_n)
    if (!rst_n)
        cur_st <= IDLE;
    else
        cur_st <= nxt_st;
always @(posedge clk or negedge rst_n)
    if (!rst_n) begin
        nxt_st <= IDLE;
        mcd   <= 0;
        mcd_vld <= 0;
        a_buf <= 0;
        b_buf <= 0;
        mul_buf <= 0;
        vld_out <= 1'b0;
    end
    else begin
        case (cur_st)
        IDLE:if(vld_in) begin 
                a_buf <= A;
                b_buf <= B;
                nxt_st <= S0;
                mul_buf <= A*B;
                mcd_vld <= 0;
                vld_out <= 1'b0;
                end
                else begin
                nxt_st <= IDLE;
                mcd_vld <= 0;
                vld_out <= 1'b0;
                end
        S0:if(a_buf!=b_buf)begin
                if(a_buf>b_buf)begin
                    a_buf<=a_buf-b_buf;
                    b_buf<=b_buf;
                end
                else begin 
                    b_buf <= b_buf - a_buf;
                    a_buf <= a_buf;
                    vld_out <= 1'b0;
                end
                nxt_st <= S0;
                end
                else begin
                    nxt_st <=S1;
                    vld_out <= 1'b0;
                    end
        S1:begin   
            mcd <= b_buf;
            mcd_vld <= 1'b1;
            nxt_st  <= IDLE;
            vld_out <= 1'b1;
            end
        default:begin  
            nxt_st<=IDLE;
            vld_out <= 1'b0;
            end
        endcase
    end
     
assign mcd_out = mcd;
assign lcm_out = mul_buf/mcd;
endmodule

Verilog 解法, 执行用时: 0ms, 内存消耗: 0KB, 提交时间: 2022-08-05

`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*2-1:0]	mcd,a_buf,b_buf;
reg [DATA_W*2-1:0]	mul_buf;
reg					mcd_vld;
reg	[1:0]			cur_st,nxt_st;
parameter IDLE= 2'b00,S0 = 2'b01, S1 = 2'b10, S2 = 2'b11;
//两段式状态机
always @(posedge clk or negedge rst_n)
	if (!rst_n)
		cur_st <= IDLE;
	else
		cur_st <= nxt_st;
always @(posedge clk or negedge rst_n)
	if (!rst_n) begin
		nxt_st <= IDLE;
		mcd	  <= 0;
		mcd_vld <= 0;
		a_buf <= 0;
		b_buf <= 0;
		mul_buf <= 0;
		vld_out <= 1'b0;
	end
	else begin	
		case (cur_st)
		IDLE:if(vld_in) begin	
				a_buf <= A;
				b_buf <= B;
				nxt_st <= S0;
				mul_buf <= A*B;
				mcd_vld <= 0;
				vld_out <= 1'b0;
				end
				else begin
				nxt_st <= IDLE;
				mcd_vld <= 0;
				vld_out <= 1'b0;
				end
		S0:if(a_buf!=b_buf)begin
				if(a_buf>b_buf)begin
					a_buf<=a_buf-b_buf;
					b_buf<=b_buf;
				end
				else begin 
					b_buf <= b_buf - a_buf;
					a_buf <= a_buf;
					vld_out <= 1'b0;
				end
				nxt_st <= S0;
				end
				else begin	
					nxt_st <=S1;
					vld_out <= 1'b0;
					end
		S1:begin	
			mcd <= b_buf;
			mcd_vld <= 1'b1;
			nxt_st	<= IDLE;
			vld_out <= 1'b1;
			end
		default:begin	
			nxt_st<=IDLE;
			vld_out <= 1'b0;
			end
		endcase
	end
	
assign mcd_out = mcd;
assign lcm_out = mul_buf/mcd;
endmodule

Verilog 解法, 执行用时: 0ms, 内存消耗: 0KB, 提交时间: 2022-08-04

`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] atemp,btemp;
    reg [DATA_W*2-1:0] mcd,lcm_buf;
    reg [1:0] state, nexts;
    parameter IDLE = 2'b00, BUSY = 2'b01, VALID = 2'b10;
    always@(posedge clk or negedge rst_n)
        begin
            if(!rst_n)
                state <= IDLE;
            else
                state <= nexts;
        end
    always@(posedge clk or negedge rst_n)
        begin
            if(!rst_n)
                begin
                    atemp <= 0;
                    btemp <= 0;
                    mcd <= 0;
                    lcm_buf <= 0;
                    vld_out <= 0;
                    nexts <= IDLE;
                end    
            else
                case(state)
                    IDLE: 
                        if(vld_in) 
                            begin   //注意这里不能把mcd的寄存器清零,不然assign的除法会报错。
                                atemp <= A;
                                btemp <= B;
                                vld_out <= 0;
                                lcm_buf <= A*B;
                                nexts <= BUSY;
                            end
                        else
                            begin
                                nexts <= IDLE;
                                vld_out <= 0;
                            end
                    BUSY:
                        begin
                            if(atemp!=btemp)
                                begin
                                    nexts <= BUSY;
                                    if(atemp>btemp)
                                        begin   
                                            atemp <= atemp-btemp;
                                            btemp <= btemp;
                                        end
                                    else
                                        begin   
                                            btemp <= btemp-atemp;
                                            atemp <= atemp;
                                        end
                                end
                            else
                                begin
                                    vld_out <= 0;
                                    nexts <= VALID;
                                end
                        end
                    VALID:
                        begin
                            mcd <= btemp;
                            vld_out <= 1;
                            nexts <= IDLE;
                        end
                    default:
                        begin
                            vld_out <= 0;
                            nexts <= IDLE;
                        end
                endcase
        end
    assign mcd_out = mcd;
    assign lcm_out = lcm_buf/mcd;
    
    
endmodule

Verilog 解法, 执行用时: 0ms, 内存消耗: 0KB, 提交时间: 2022-08-04

`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*2-1:0]  mcd,a_buf,b_buf;
reg [DATA_W*2-1:0] mul_buf;
reg                 mcd_vld;
reg [1:0]           cur_st,nxt_st;
parameter IDLE= 2'b00,S0 = 2'b01, S1 = 2'b10, S2 = 2'b11;
//两段式状态机
always @(posedge clk or negedge rst_n)
    if (!rst_n)
        cur_st <= IDLE;
    else
        cur_st <= nxt_st;
always @(posedge clk or negedge rst_n)
    if (!rst_n) begin
        nxt_st <= IDLE;
        mcd   <= 0;
        mcd_vld <= 0;
        a_buf <= 0;
        b_buf <= 0;
        mul_buf <= 0;
        vld_out <= 1'b0;
    end
    else begin
        case (cur_st)
        IDLE:if(vld_in) begin 
                a_buf <= A;
                b_buf <= B;
                nxt_st <= S0;
                mul_buf <= A*B;
                mcd_vld <= 0;
                vld_out <= 1'b0;
                end
                else begin
                nxt_st <= IDLE;
                mcd_vld <= 0;
                vld_out <= 1'b0;
                end
        S0:if(a_buf!=b_buf)begin
                if(a_buf>b_buf)begin
                    a_buf<=a_buf-b_buf;
                    b_buf<=b_buf;
                end
                else begin 
                    b_buf <= b_buf - a_buf;
                    a_buf <= a_buf;
                    vld_out <= 1'b0;
                end
                nxt_st <= S0;
                end
                else begin
                    nxt_st <=S1;
                    vld_out <= 1'b0;
                    end
        S1:begin   
            mcd <= b_buf;
            mcd_vld <= 1'b1;
            nxt_st  <= IDLE;
            vld_out <= 1'b1;
            end
        default:begin  
            nxt_st<=IDLE;
            vld_out <= 1'b0;
            end
        endcase
    end
     
assign mcd_out = mcd;
assign lcm_out = mul_buf/mcd;
    
endmodule

Verilog 解法, 执行用时: 0ms, 内存消耗: 0KB, 提交时间: 2022-08-04

`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*2-1:0]	mcd,a,b;
reg [DATA_W*2-1:0]	mul_buf;
//reg					mcd_vld;
reg	[1:0]			cur_st,nxt_st;
parameter IDLE= 2'b00,S0 = 2'b01, S1 = 2'b10, S2 = 2'b11;
//两段式状态机
always @(posedge clk or negedge rst_n)
	if (!rst_n)
		cur_st <= IDLE;
	else
		cur_st <= nxt_st;
always @(posedge clk or negedge rst_n)
	if (!rst_n) begin
		nxt_st <= IDLE;
		mcd	  <= 0;
		a <= 0;
		b <= 0;
		mul_buf <= 0;
		vld_out <= 1'b0;
	end
	else begin	
		case (cur_st)
		IDLE:if(vld_in) begin	
				a <= A;
				b <= B;
				nxt_st <= S0;
				mul_buf <= A*B;
				vld_out <= 1'b0;
				end
				else begin
				nxt_st <= IDLE;
				vld_out <= 1'b0;
				end
		S0:if(a!=b)begin
                if(a>b) a<=a-b;
				else b <= b-a;
                nxt_st <= S0;
            end
            else nxt_st <=S1;
		S1:begin	
			mcd <= b;
			nxt_st	<= IDLE;
			vld_out <= 1'b1;
			end
		default:begin	
			nxt_st<=IDLE;
			vld_out <= 1'b0;
			end
		endcase
	end
	
assign mcd_out = mcd;
assign lcm_out = mul_buf/mcd;
endmodule

上一题