One out of two data selectors realize the Verilog of 15 frequency division (asynchronous reset) and 18 frequency division (synchronous reset) with a duty cycle of 50%

The above topic was one of the topics that our laboratory came up with when we were new. It mainly investigated the knowledge of odd frequency division and even frequency division principles and timing logic such as counters. In combinatorial logic, it only included one out of two data selectors, which was not difficult. For us who had only studied for less than two months at that time, the difficulty of this topic was moderate. Let's analyze the implementation of the topic.

Even frequency division

Principle introduction:

Even frequency division is easy to understand. For example, if the frequency is 1 / 4 of the clk signal, its period is 4 times that of the clk signal. Therefore, when the value of the counter is equal to half of the frequency division coefficient or equal to the frequency division coefficient, the signal is reversed.

Taking the frequency division 4 in the following figure as an example, use the counter cnt to count, add 1 at the rising edge of the clock, flip div_4 once when counting to (4 / 2-1), flip it again when counting to (4-1), and repeat it periodically to get the frequency division 4 clock div_4  .

Even frequency division (4) source code:

module fenpin_4(
    input clk,
    input rst_n,
	output reg clk_div
    );
    parameter NUM_DIV = 4;
	reg[4:0] cnt;
always @(posedge clk)begin
    if(!rst_n)
        cnt <= 0;
	 else if(cnt == NUM_DIV - 1'b1)
		cnt <= 0;
    else 
        cnt <= cnt + 1'b1;
end
always @(posedge clk)
    if(!rst_n)
        clk_div <= 1'b1;
    else if(cnt < NUM_DIV / 2) 
        clk_div <= 1'b1;
    else
        clk_div <= 1'b0;


endmodule

tb file:

module tb_fenpin_4;

	// Inputs
	reg clk;
	reg rst_n;

	// Outputs
	wire clk_div;

	// Instantiate the Unit Under Test (UUT)
	fenpin_4 uut (
		.clk(clk), 
		.rst_n(rst_n), 
		.clk_div(clk_div)
	);
always #10 clk = ~clk;
	initial begin
		// Initialize Inputs
		clk = 0;
		rst_n = 0;

		// Wait 100 ns for global reset to finish
		#100;
        rst_n = 1;
		// Add stimulus here

	end
      
endmodule

  Simulation waveform:

  Odd frequency division

Principle introduction:

Odd frequency division is similar to even frequency division. The principle is slightly more complex. It is not possible to take the frequency division coefficient directly like even frequency division. Generally, the signal is reversed to directly realize the duty cycle of 50%. At this time, we need to get it through the combined logic operation of two frequency division signals. Let's analyze the design idea.

As shown in the figure below, taking the frequency division of 3 as an example, use the counter cnt to count and add 1 at the rising edge of the clock. When cnt counts to (3 / 2 = 1) and the clock is at the falling edge, clk_out_1 (div_3shift by edge in the figure) Perform a flip. When the cnt counts the frequency division coefficient 3 and the clock is at the falling edge, flip clk_out_1 again. Finally, the signal clk_out_1 with a duty cycle of 1 / 3 is obtained.

At the same time, when the cnt counts to (3 / 2 = 1) and the clock is at the upper and lower edges, clk_out_1 (div_3shift by position in the figure) is flipped once. When the cnt counts to the frequency division coefficient 3 and the clock is at the upper and lower edges, clk_out_1 is flipped again. Finally, the signal clk_out_1 with a duty cycle of 1 / 3 is obtained.

Then the two signals are passed through the "or" gate to obtain div_3 signal.

  (3) frequency division source code:

module fenpin_3(
    input clk,
    input rst_n,
    output clk_div
    );
 
    parameter NUM_DIV = 3;
    reg[2:0] cnt1;
    reg[2:0] cnt2;
    reg    clk_div1, clk_div2;
 
always @(posedge clk or negedge rst_n)
    if(!rst_n)
        cnt1 <= 0;
    else if(cnt1 < NUM_DIV - 1)
        cnt1 <= cnt1 + 1'b1;
    else 
        cnt1 <= 0;
        
always @(posedge clk or negedge rst_n)
    if(!rst_n)
        clk_div1 <= 1'b1;
    else if(cnt1 < NUM_DIV / 2) 
        clk_div1 <= 1'b1;
    else
        clk_div1 <= 1'b0;
        
always @(negedge clk or negedge rst_n)
    if(!rst_n)
       cnt2 <= 0;
    else if(cnt2 < NUM_DIV - 1)
       cnt2 <= cnt2 + 1'b1;
    else 
       cnt2 <= 0;
 
always @(negedge clk or negedge rst_n)
    if(!rst_n)
        clk_div2 <= 1'b1;
    else if(cnt2 < NUM_DIV / 2) 
        clk_div2 <= 1'b1;
    else
        clk_div2 <= 1'b0;
        
    assign clk_div = clk_div1 | clk_div2;
 
endmodule

tb file:

module tb_fenpin_3;

	// Inputs
	reg clk;
	reg rst_n;

	// Outputs
	wire clk_div;

	// Instantiate the Unit Under Test (UUT)
	fenpin_3 uut (
		.clk(clk), 
		.rst_n(rst_n), 
		.clk_div(clk_div)
	);
always #10 clk = ~clk;
	initial begin
		// Initialize Inputs
		clk = 0;
		rst_n = 0;

		// Wait 100 ns for global reset to finish
		#100;
		rst_n = 1;
        
		// Add stimulus here

	end
      
endmodule

Simulation waveform:

The above is an introduction to the main framework of this topic. Odd frequency division and even frequency division are very commonly used in our projects, such as dynamic nixie tube and other projects requiring time.

To get down to business, with the above foundation, it's easy to do the original topic. Next, I'll post the code of the interview topic here.

Source code of the topic:  

module pro_2(
    input clk,
	 input sel,
    input rst_n,
	 output reg out
    );
    parameter NUM_DIV = 15;
    parameter NUM_DIV_1 = 18;    
	 reg[4:0] cnt1;
    reg[4:0] cnt2;
	 reg[4:0] cnt3;
    reg    clk_div1, clk_div2,clk_div3;
    wire clk_div;
always @(posedge clk  or negedge rst_n)
    if(!rst_n)
        cnt1 <= 0;
    else if(cnt1 < NUM_DIV - 1)
        cnt1 <= cnt1 + 1'b1;
    else 
        cnt1 <= 0;
always @(posedge clk  or negedge rst_n)
    if(!rst_n)
        clk_div1 <= 1'b1;
    else if(cnt1 < NUM_DIV / 2) 
        clk_div1 <= 1'b1;
    else
        clk_div1 <= 1'b0;
always @(negedge clk or negedge rst_n)
    if(!rst_n)
       cnt2 <= 0;
    else if(cnt2 < NUM_DIV - 1)
       cnt2 <= cnt2 + 1'b1;
    else 
       cnt2 <= 0;
always @(negedge clk or negedge rst_n)
    if(!rst_n)
        clk_div2 <= 1'b1;
    else if(cnt2 < NUM_DIV / 2) 
        clk_div2 <= 1'b1;
    else
        clk_div2 <= 1'b0;
		  
assign clk_div = clk_div1 | clk_div2;//15 frequency division


always @(posedge clk)begin
    if(!rst_n)
        cnt3 <= 0;
	 else if(cnt3 == NUM_DIV_1 - 1'b1)
			cnt3 <= 0;
    else 
        cnt3 <= cnt3 + 1'b1;
end
always @(posedge clk)
    if(!rst_n)
        clk_div3 <= 1'b1;
    else if(cnt3 < NUM_DIV_1 / 2) 
        clk_div3 <= 1'b1;
    else
        clk_div3 <= 1'b0;//18 frequency division

always@(*)begin
    if(sel==0)
	   out = clk_div;
	 else if(sel==1)
	   out = clk_div3;
end
        

endmodule

tb file  :

module tb_pro2;

	// Inputs
	reg clk;
	reg sel;
	reg rst_n;

	// Outputs
	wire out;

	// Instantiate the Unit Under Test (UUT)
	pro_2 uut (
		.clk(clk), 
		.sel(sel), 
		.rst_n(rst_n), 
		.out(out)
	);
always #10 clk = ~clk;
	initial begin
		// Initialize Inputs
		clk = 0;
		sel = 0;
		rst_n = 0;

		// Wait 100 ns for global reset to finish
		#100;
		sel = 0;
		rst_n = 1;
		
		#100000;
		sel = 1;
   		// Add stimulus here

	end
      
endmodule

Simulation waveform:

When sel control signal is 0, 15 frequency division is output

  When sel control signal is 1, 18 frequency division is output

Posted by l008com on Sat, 23 Oct 2021 06:15:19 -0700