Verilog 統計第一個1后0的個數/1的個數/第一個1的位置


一、前言

當數據的位寬不是很長時,此類問題可以使用移位寄存器來解決。我們將輸入數據不斷的右移,這樣每次只需要對最后一bit進行判斷。由於需要統計個數,我們還需要定義一些計數器,cnt用來計數已經處理了多個bit,而cnt0和cnt1用來記錄要統計的0和1的個數。
當然還需要一些其他邏輯輔助完成這些功能,可以參考下面的代碼,為了方便理解,里面也寫了一些注釋。

二、從低到高統計數據中第一個1后面的0的個數

/* 從低到高 統計第一個1后面的0的個數 */
module cnt_num(
	input clk,
	input rst_n,
	input din_en,
	input [7:0]din,
	output reg[3:0]count_out
);

	reg [3:0]cnt;//計數檢測了多少bit
    reg [3:0]cnt0;//計數0的個數
	reg flag;//檢測到了第一個1
	reg [7:0]din_r;//din的移位寄存器

	reg din_en_r;
	wire pos_din_en;
	localparam BitWidth = 8;

	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			din_en_r <= 1'b0;
		else 
			din_en_r <= din_en;
	end

	assign pos_din_en = din_en && (!din_en_r);

	
	
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			cnt <= 4'd0;
		else if(din_en && (cnt < BitWidth))
			cnt <= cnt + 1'b1;
		else 
			cnt <= 4'd0;
	end

	//當flag有效時,就開始判斷每一bit是不是0
	//是的話,cnt0計數+1;否則就保持不變,當所有bit檢測完后歸零
  	always@(posedge clk or negedge rst_n)begin
		if(!rst_n || pos_din_en)
			cnt0 <= 4'd0;
		else if(flag && (din_r[0] == 0))
			cnt0 <= cnt0 + 1'b1;
		else if (cnt < BitWidth) begin
            cnt0 <= cnt0;
        end
        else
			cnt0 <= 4'd0;
	end
	
	//判斷是否已經檢測到了第一個1
  	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			flag <= 1'b0;
		else if(din_r[0])
			flag <= 1'b1;
		else if (cnt == BitWidth) begin
            flag <= 1'b0;
        end
        else
            flag <= flag;
			
	end

	//din的右移移位寄存器,這樣只需要每次檢測最低位即可
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			din_r <= 8'd0;
		else if(pos_din_en)
			din_r <= din;
		else if(din_en)
			din_r <= {0,din_r[7:1]};
		else 
			din_r <= din_r;
	end
	
	//在cnt=0時將計數結果賦給count_out
	//沒有在cnt=8時賦值,是因為cnt0的邏輯比cnt1延遲了一個周期,因為前者受flag的影響
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			count_out <= 4'd0;
		else if(cnt == 4'd0)
			count_out <= cnt0;
		else 
			count_out <= count_out;
	end
	
endmodule

在這里插入圖片描述

三、統計數據中1的個數

/* 統計1的個數 */
module cnt_num2(
	input clk,
	input rst_n,
	input din_en,
	input [7:0]din,
	output reg[3:0]count_out
);

	reg [3:0]cnt;//計數檢測了多少bit
    reg [3:0]cnt1;//計數1的個數

	reg [7:0]din_r;//din的移位寄存器

	reg din_en_r;
	wire pos_din_en;
	
    localparam BitWidth = 8;
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			din_en_r <= 1'b0;
		else 
			din_en_r <= din_en;
	end

	assign pos_din_en = din_en && (!din_en_r);

	
	
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			cnt <= 4'd0;
		else if(din_en && (cnt < BitWidth))
			cnt <= cnt + 1'b1;
		else 
			cnt <= 4'd0;
	end

    //檢測到1就加1,否則保持不變,檢測完所有bit歸零
    always@(posedge clk or negedge rst_n)begin
		if(!rst_n || pos_din_en)
			cnt1 <= 4'd0;
		else if(din_r[0] == 1)
			cnt1 <= cnt1 + 1'b1;
		else if (cnt < BitWidth) begin
            cnt1 <= cnt1;
        end
        else
			cnt1 <= 4'd0;
	end
	
    //din的右移移位寄存器,這樣只需要每次檢測最低位即可
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			din_r <= 8'd0;
		else if(pos_din_en)
			din_r <= din;
		else if(din_en)
			din_r <= {0,din_r[7:1]};
		else 
			din_r <= din_r;
	end
	
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			count_out <= 4'd0;
		else if(cnt == BitWidth)
			count_out <= cnt1;
		else 
			count_out <= count_out;
	end
	
endmodule

在這里插入圖片描述

四、獲取第一個1的位置


/* 從低到高 記錄第一個1的位置 */
module cnt_num3(
	input clk,
	input rst_n,
	input din_en,
	input [7:0]din,
	output reg[2:0]index_out
);

	reg [3:0]cnt;//計數檢測了多少bit
	reg flag;//檢測到了第一個1
	reg [7:0]din_r;//din的移位寄存器

    reg [2:0]index;//記錄第一個1的位置

	reg din_en_r;
	wire pos_din_en;
	localparam BitWidth = 8;

	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			din_en_r <= 1'b0;
		else 
			din_en_r <= din_en;
	end

	assign pos_din_en = din_en && (!din_en_r);

	
	
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			cnt <= 4'd0;
		else if(din_en && (cnt < BitWidth))
			cnt <= cnt + 1'b1;
		else 
			cnt <= 4'd0;
	end

	//判斷是否已經檢測到了第一個1
  	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)begin
            index <= 3'd0;
            flag <= 1'b0;
        end
		else if((!flag) && din_r[0] && (cnt < BitWidth))begin
            flag <= 1'b1;
            index <= cnt;
        end
        else if (cnt == BitWidth) begin
            flag <= 1'b0;
            index <= 3'd0;
        end
        else begin
            flag <= flag;
            index <= index;
        end
            
			
	end

	//din的右移移位寄存器,這樣只需要每次檢測最低位即可
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			din_r <= 8'd0;
		else if(pos_din_en)
			din_r <= din;
		else if(din_en)
			din_r <= {0,din_r[7:1]};
		else 
			din_r <= din_r;
	end
	
	//在cnt=0時將計數結果賦給count_out
	//沒有在cnt=8時賦值,是因為cnt0的邏輯比cnt1延遲了一個周期,因為前者受flag的影響
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			index_out <= 3'd0;
		else if(cnt == BitWidth)
			index_out <= index;
		else 
			index_out <= index_out;
	end
endmodule

在這里插入圖片描述
需要注意的是代碼中的一些邏輯,需要根據輸入數據din和使能信號din_en的實際時序做出一些修改,但核心思想是差不多的!!!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM