⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 divider_stg_1.v

📁 VerilogHDL_advanced_digital_design_code_Ch10 VerilogHDL高级数字设计源码Ch10
💻 V
字号:
module Divider_STG_1 (quotient, remainder, Ready, Error, word1, word2, Start, clock, reset);
  parameter 	L_divn = 8;
  parameter 	L_divr = 4;			// Choose L_divr <= L_divn
  parameter	S_idle = 0, S_Adivr = 1, S_Adivn = 2, S_div = 3, S_Err = 4;
  parameter 	L_state = 3, L_cnt = 4, Max_cnt = L_divn - L_divr;
  output 	[L_divn -1: 0] 	quotient;
  output 	[L_divn -1: 0]	remainder;
  output 				Ready, Error;
  input 	[L_divn -1: 0] 	word1;				// Datapath for dividend
  input 	[L_divr -1: 0] 	word2;				// Datapath for divisor
  input 				Start, clock, reset;
  reg 	[L_state -1: 0] 	state, next_state;
  reg 				Load_words, Subtract, Shift_dividend, Shift_divisor;
  reg		[L_divn -1: 0]	 quotient;
  reg 	[L_divn: 0] 	dividend;			// Extended dividend
  reg	[L_divr -1: 0]	divisor; 
  reg	[L_cnt -1: 0]	num_shift_dividend, num_shift_divisor;
  reg	[L_divr: 0]	comparison;
  wire	MSB_divr = divisor[L_divr -1];
  wire 	Ready =((state == S_idle) && !reset) ;
  wire	Error = (state == S_Err);
  wire	Max = (num_shift_dividend == Max_cnt + num_shift_divisor );
  wire	sign_bit = comparison[L_divr];

  always @ (state or dividend or divisor or MSB_divr)			// subtract divisor from dividend
    case (state)
      S_Adivr:	if (MSB_divr == 0) comparison 
		= dividend[L_divn: L_divn - L_divr] + {1'b1, ~(divisor << 1)} + 1'b1;
	else comparison = dividend[L_divn: L_divn - L_divr] + {1'b1, ~divisor[L_divr -1:  0]} + 1'b1; 
      default:	comparison = dividend[L_divn: L_divn - L_divr] + {1'b1, ~divisor[L_divr -1:  0]} + 1'b1;
  endcase


   	// Shift the remainder to compensate for alignment shifts 
  assign 	remainder = (dividend[L_divn -1:  L_divn -L_divr]  ) >> num_shift_divisor;

  always @ (posedge clock or posedge reset)  		// State Transitions
    if (reset) state <= S_idle; else state <= next_state; 

  // Next state and control logic

  always 
    @ (state or word1 or word2 or Start or comparison or sign_bit or Max )  begin
    Load_words = 0; Shift_dividend = 0; Shift_divisor  = 0; Subtract = 0; 
    case (state)
      S_idle: 	case (Start) 		  
  	  0:   		next_state = S_idle; 
	  1:		if (word2 == 0) next_state = S_Err; 
			else if (word1) begin next_state = S_Adivr; Load_words = 1; end
			else next_state = S_idle;
	endcase 

      S_Adivr:	case (MSB_divr)
	  0:		if (sign_bit == 0) begin
		  	  next_state = S_Adivr; Shift_divisor = 1;		// can shift divisor
			end
			else if (sign_bit == 1)  begin
		  	  next_state = S_Adivn;				// cannot shift divisor
			end	
	  1:		next_state = S_div; 
	endcase
		
      S_Adivn:	case ({Max, sign_bit})
	  2'b00: 	next_state = S_div; 
	  2'b01: 	begin next_state = S_Adivn; Shift_dividend  = 1; end

	  2'b10: 	begin  next_state = S_idle; Subtract = 1; end
	  2'b11: 	next_state = S_idle;
	endcase
		  		
       S_div:	case ({Max, sign_bit}) 
	  2'b00:	begin next_state = S_div; Subtract = 1; end
	  2'b01:	next_state = S_Adivn;				
	  2'b10:	begin next_state = S_div; Subtract = 1; end
	  2'b11:	begin next_state = S_div; Shift_dividend = 1; end
	endcase
      default:	next_state = S_Err;
    endcase
  end

always @ (posedge clock or posedge reset) begin	// Register/Datapath operations	
    if (reset) begin 
      divisor <= 0; dividend <= 0; quotient <= 0; num_shift_dividend <= 0; num_shift_divisor <= 0;
    end

    else if (Load_words == 1)  
      begin 
        dividend <= word1; 
        divisor <= word2; 
        quotient <= 0; 
        num_shift_dividend <= 0; 
        num_shift_divisor <= 0; 
    end

    else if (Shift_divisor) begin 
      divisor <= divisor << 1; 
      num_shift_divisor <= num_shift_divisor + 1; 
    end

    else if (Shift_dividend) begin
      dividend <= dividend << 1;   
      quotient <= quotient << 1;
      num_shift_dividend <= num_shift_dividend +1;
    end

    else if (Subtract) 
      begin 
        dividend [L_divn: L_divn -L_divr] <= comparison; 
        quotient[0] <= 1; 
      end
    end
endmodule

module test_Divider_STG_1 ();
  parameter L_divn = 8;
  parameter L_divr = 4;
  parameter word_1_max = 255;
  parameter word_1_min = 1;
  parameter word_2_max = 15;
  parameter word_2_min = 1;
  parameter max_time = 850000;
  parameter half_cycle = 10;
  parameter start_duration = 20;
  parameter start_offset = 30;
  parameter delay_for_exhaustive_patterns = 490;
  parameter reset_offset = 50;
  parameter reset_toggle = 5;
  parameter reset_duration = 20;
  parameter word_2_delay = 20;
  wire [L_divn -1: 0] quotient;
  wire [L_divn-1:0] remainder;
  wire Ready, Div_zero;
  integer word1;		// dividend
  integer word2;		// divisor
  reg Start, clock, reset;
  reg [L_divn-1: 0] expected_value;
  reg [L_divn-1:0] expected_remainder;		 
  wire quotient_error, rem_error;
  integer k, m;

  // probes
  wire 	[L_divr-1:0] 	Left_bits = M1.dividend[L_divn-1: L_divn -L_divr];
   
  Divider_STG_1 M1 (quotient, remainder, Ready, Error, word1, word2, Start, clock, reset);

  initial #max_time $finish;
  initial begin clock = 0; forever #half_cycle clock = ~clock; end
  
  initial begin expected_value = 0; expected_remainder = 0;
    forever @ (negedge Ready)  begin    // Form expected values
      #2 if (word2 != 0) begin expected_value = word1 / word2; expected_remainder = word1 % word2; end
     end
  end

  assign quotient_error = (!reset && Ready) ? |(expected_value ^ quotient): 0;
  assign rem_error = (!reset && Ready) ? |(expected_remainder ^ remainder): 0;

  initial begin	// Test for divide by zero detection
    #2 reset = 1;
    #15 reset = 0; Start = 0;
    #10 Start = 1; #5 Start = 0;		
  end

  initial begin 	// Test for recovery from error state on reset and running reset
    #reset_offset reset = 1; #reset_toggle Start = 1; #reset_toggle reset = 0;
    word1 = 0; 
    word2 = 1; 
    while (word2 <= word_2_max) #20 word2 = word2 +1;
     #start_duration Start = 0; 
  end		 
  initial begin 	// Exhaustive patterns
    #delay_for_exhaustive_patterns  
    word1 = word_1_min; while (word1 <= word_1_max) begin			
    word2 = 1; while (word2 <= 15) begin
    #0 Start = 0; 
    #start_offset Start = 1;
    #start_duration Start = 0; 
    @ (posedge Ready) #0;
    word2 = word2 + 1; end  	// divisor pattern
    word1 = word1 + 1; end 	//  dividend pattern
  end 		 
endmodule

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -