复习_2: Find the toppest 1

记得这道题好像是之前一次笔试的题目。。当时想了想没想出来,考完了就知道怎么写了,可能这就是笔试吧 😦 , 被自己难受到了

题目

假设一个输入为自己可以定义位数的数字输入,需要得到的结果是这个输入的最高位的1 (最左边的1)

思路方法

在纸上写下来之后才发现原来是一个可以在一个时钟周期搞定的combinational logic, 首先既然知道输入的数字位数,那么就可以通过 $clog2 来得到表示 输入位数 所需要用到多少位, 然后对这个位数做文章。
假设输入的值是一个11位的数字 P,那么clog2 之后会得到 4, 假设最后得到的结果D是 _ _ _ _ , 如果其中的第一位是1的话,那么TOP 1的位置就是要在第八位往上,也就是说这个数字必须大于(2^8),那么其实此时就可以有一个分支会出现:
1. if(P>(2^8)), D[log2(8) ] = 1
2. if(P<(2^8)), D[log2(8) ] = 0
从第一个分支走起,如果最高位不是第八位的话,接下来D剩下的三个位置应该是由{P[11],P[10],P[9]}所决定的,那么其实就是 P/(2^8), 然后其实就是一个类似recursion的概念往下套就行
而第二个分支的结果就是对P%(2^8)之后的数字进行类似的recursion,直到最后一位

写码

如果一开始就告诉位数。。那其实可以非常开心的就手动写很多个assign … = (截取位数的值/2^>0) ?1:0
但是既然是不知道输入的数字位数那其实还是把它当作一个parameter来写比较好,之后使用genvar + generate(end) 一套直接带走 (虽然DEBUG了很久,不知道为什么quartus对genvar特别不友好)

module findtopone#(
	parameter length = 11,
	parameter index = $clog2(length)
)(
	input[length-1:0] signal,
	output[index:0] 	index_pos
);
	//integer i;
	reg[length-1:0] cur_val[index:0];
	assign index_pos[index] = ((signal/(2**(2**index)))>0)? 1:0;
	genvar i;
	generate
	assign cur_val[index] = signal;
	for(i=index-1;i>=0;i=i-1) begin:findstart
		assign cur_val[i] = (index_pos[i+1]==1'b1)? (cur_val[i+1]/(2**(2**(i+1)))):(cur_val[i+1]%(2**(2**(i+1))));   
		assign index_pos[i] =  ((  cur_val[i] /(2**(2**i)))>0)?1:0;
	end
	endgenerate
	
endmodule

之后的testcase在waveform里面直接跑了一下没啥问题,不是啥专业的写verilog testcase + modelsim的验证就不上传了

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页