복구 잔수 제법기

4692 단어

복구 잔수 제법기


알고리즘 설명


복구 여수 제법기는 흔히 사용하는 제법기로서 과정은 수산 제법의 방법과 매우 유사하다. 과정은
  • 나눗셈이 나눗셈보다 클 때까지 왼쪽으로 이동
  • 피제수 감제수 조작을 실행하여 여수를 얻고 상인을 왼쪽으로 1위 이동, 빈자리 보충 1
  • 나머지가 0보다 크면 나머지를 오른쪽으로 1위 이동한다.여수가 0보다 적으면 여수에 현재 제수를 더하면 상마지막 위치 0, 제수는 오른쪽으로 1위 이동
  • 2로 중복되고 나눗셈이 최초의 나눗셈보다 작다
  • RTL 코드


    RTL 코드는 대량의 if 문장을 사용하여 이상의 알고리즘 설명을 완성한 것이다. 그 중에서
  • 위치 이동 후의 제수가 피제수보다 크다는 것을 확보하기 위해 제수를 한 비트의 와이드TH*3 레지스터의 앞 와이드TH 비트
  • 에 직접 넣는다.
  • divisor_move >= '{divisor_lock}는 위치 이동 제수가 원래 제수보다 적을 때 정지
  • 에 사용
  • (divisor_move > '{remainder_r}) && (dout == 'b0) 첫 번째 1이 나타날 때 결과를 저장하는 데 사용
  • module restore_divider #(
        parameter WIDTH = 4
    )(
        input clk,    // Clock
        input rst_n,  // Asynchronous reset active low
    
        input [WIDTH * 2 - 1:0]dividend,
        input [WIDTH - 1:0]divisor,
    
        input din_valid,
    
        output reg [2 * WIDTH - 1:0]dout,
        output [WIDTH - 1:0]remainder
    );
    
    reg [2 * WIDTH:0]remainder_r;
    reg [3 * WIDTH - 1:0]divisor_move;
    reg [WIDTH - 1:0]divisor_lock;
    always @ (posedge clk or negedge rst_n) begin
        if(~rst_n) begin
            //   
            {remainder_r,divisor_lock,divisor_move,dout} <= 'b0;
        end else begin
            if(din_valid == 1'b1) begin 
                //    ,3 WIDTH                  
                remainder_r[WIDTH * 2 - 1:0] <= dividend;
                remainder_r[2 * WIDTH] <= 'b0;
                divisor_move[3 * WIDTH - 1:2 * WIDTH] <= divisor;
                divisor_move[2 * WIDTH - 1:0] <= 'b0;
                divisor_lock <= divisor;
                dout <= 'b0;
            end else if((divisor_move > '{remainder_r}) && (dout == 'b0)) begin
                //    
                 remainder_r <= remainder_r;
                dout <= 'b0;
                divisor_move <= divisor_move >> 1;
                divisor_lock <= divisor_lock;
            end else if(divisor_move >= '{divisor_lock}) begin
                if(remainder_r[2 * WIDTH] == 1'b0) begin //    
                    remainder_r <= remainder_r - divisor_move;
                    dout <= {dout[2 * WIDTH - 2:0],1'b1};
                    // divisor_move <= divisor_move >> 1;
                    divisor_lock <= divisor_lock;
                    if(remainder_r >= divisor_move) begin
                        divisor_move <= divisor_move >> 1;
                    end else begin
                        divisor_move <= divisor_move;
                    end
                end else begin  //    
                    remainder_r <= remainder_r + divisor_move;
                    dout <= {dout[2 * WIDTH - 1:1],1'b0};
                    divisor_move <= divisor_move >> 1;
                    divisor_lock <= divisor_lock;
                end
            end else begin
                remainder_r <= remainder_r;
                divisor_lock <= divisor_lock;
                divisor_move <= divisor_move;
                dout <= dout;
            end
        end
    end
    
    assign remainder = remainder_r[WIDTH - 1:0];
    
    endmodule
    

    테스트 플랫폼


    테스트 플랫폼은shiftsub 제법기의 플랫폼을 복용하여'오타가 발생하면 정지'기능을 증가시켰다
    module tb_divider (
    );
    
    parameter WIDTH = 4;
    
    logic clk;    // Clock
    logic rst_n;  // Asynchronous reset active low
    logic [2 * WIDTH - 1:0]dividend;
    logic [WIDTH - 1:0]divisor;
    
    logic din_valid;
    
    logic [2 * WIDTH - 1:0]dout;
    logic [WIDTH - 1:0]remainder;
    
    restore_divider #(
        .WIDTH(WIDTH)
    ) dut (
        .clk(clk),    // Clock
        .rst_n(rst_n),  // Asynchronous reset active low
    
        .dividend(dividend),
        .divisor(divisor),
    
        .din_valid(din_valid),
    
        .dout(dout),
        .remainder(remainder)
    );
    
    initial begin
        clk = 'b0;
        forever begin
            #50 clk = ~clk;
        end
    end
    
    initial begin
        rst_n = 1'b1;
        # 5 rst_n = 'b0;
        #10 rst_n = 1'b1;
    end
    
    logic [2 * WIDTH - 1:0]dout_exp;
    logic [WIDTH - 1:0]remainder_exp;
    initial begin
        {dividend,divisor,din_valid} = 'b0;
        forever begin
            @(negedge clk);
            dividend = (2 * WIDTH)'($urandom_range(0,2 ** (2 * WIDTH)));
            divisor = (WIDTH)'($urandom_range(1,2 ** WIDTH - 1));
            din_valid = 1'b1;
    
            remainder_exp = dividend % divisor;
            dout_exp = (dividend - remainder_exp) / divisor;
    
            repeat(5 * WIDTH) begin
                @(negedge clk);
                din_valid = 'b0;
            end
            if((remainder == remainder_exp) && (dout_exp == dout)) begin
                $display("successfully");
            end else begin
                $display("failed");
                $stop;
            end
        end
    end
    
    endmodule
    

    좋은 웹페이지 즐겨찾기