FPGA刷题——信号发生器+冒泡法求6个数中的最小值

最近做了一些公司的笔试题,和牛客网上的题还是很重合的!坚定了我继续刷题的目标!更新2道比较难的题:
目录
信号发生器
方波
锯齿波
三角波
冒泡法排序

信号发生器 FPGA刷题——信号发生器+冒泡法求6个数中的最小值
文章图片

这道题比较难,想了很久才写出满意的程序。首先,方波的周期是20,锯齿波的周期是21,三角波的周期是40,且wave的最大值是20。题目没有明确告知,我是从其他人的题解中知道的。下面分别分析一下三种波形如何产生。
方波
方波模式需注意wave在什么时候翻转。设置一个计数器cnt,计数范围是0-19。该计数器仅在方波模式也就是wave_choise==0时工作。

1
2
3
wave <= cnt ==9 ? 20:
【FPGA刷题——信号发生器+冒泡法求6个数中的最小值】cnt ==19? 0 :
wave;
cnt值在0~9时,wave==20;当cnt值在10~19时,wave==0。也就是wave应在cnt==10时从0变为20。但由于非阻塞赋值,cnt==10时,wave应对cnt==9是否成立进行判断。cnt==19也是同样原因。

锯齿波
锯齿波比较简单。wave产生锯齿波时,需要从0增加到20,所以周期是21。 当wave增加到20时,清零。
1
wave <= wave==20? 0: wave+1;
三角波
三角波模式需要设置一个标志位flagflag仅在三角波模式也就是wave_chosie==2时工作。当flag==0时,wave减少;当flag==1时,wave增加。
1
wave <= flag==0 ? wave-1: wave+1;
由波形图得知,刚进入三角波模式时,wave是下降的,所以flag的默认值是0。wave在最小值0和最大值20时,flag应进行翻转。同样由于是非阻塞赋值,所以wave上升到19时,flag从1到0,也就是flag <= wave==19&&flag==1? 0: flagwave下降到1时,flag从0到1,也就是flag <= wave==1&&flag==0? 1: flag
完整代码如下:
`timescale 1ns/1ns module signal_generator( input clk, input rst_n, input [1:0] wave_choise, output reg [4:0]wave ); reg [4:0] cnt; reg flag; // 方波模式下,计数器控制 always@(posedge clk or negedge rst_n) begin if(~rst_n) cnt <= 0; else cnt <= wave_choise!=0 ? 0: cnt==19? 0: cnt + 1; end// 三角波模式下,标志位控制 always@(posedge clk or negedge rst_n) begin if(~rst_n) flag <= 0; else flag <= wave_choise!=2 ? 0: wave==1 ? 1: wave==19? 0: flag; end// 更新wave信号 always@(posedge clk or negedge rst_n) begin if(~rst_n) wave <= 0; else case(wave_choise) 0: wave <= cnt == 9? 20: cnt ==19? 0: wave; 1: wave <= wave==20? 0: wave+1; 2: wave <= flag==0 ? wave-1: wave+1; default: wave <= 0; endcase end endmodule

冒泡法排序 求6个数中的最小值,且保证索引值不变,输入输出已经给出,如下:
module MinValue ( input InClk, input [7:0]InData0, input [7:0]InData1, input [7:0]InData2, input [7:0]InData3, input [7:0]InData4, input [7:0]InData5, input [7:0]InData6, output [7:0]OutMinValue, output [2:0]OutMinIndex);

首先,我们定义6个寄存器,寄存输入的6个数据,由于题目要求索引值不改变,再设置6个寄存器寄存每一个数据的索引值:
reg [7:0] MinValue1; reg [7:0] MinValue2; reg [7:0] MinValue3; reg[7:0]MinValue4; reg [7:0]MinValue5; reg[7:0]MinValue6; reg[2:0]MinIndex1; reg[2:0]MinIndex2; reg[2:0]MinIndex3; reg[2:0]MinIndex4; reg[2:0]MinIndex5; reg[2:0]MinIndex6;

根据冒泡排序的原理,如果数据a>数据b,b是目前的最小值,则交换a和b的数值(同时交换a和b的索引值),a就成为了目前的最小值。数据a<数据b,a本身就是目前的最小值,则无需交换。再用a与其他数据进行比较:
always @(posedge InClk ) begin if (Indata0<=Indata1) begin//数据0小于1 MinValue1<=InData0; //数据1成原先的数据0 MinIndex1<=3'd0; //数据1索引变成数据0的 end elsebegin MinValue1<=Indata1; //数据1本来就是最小值,索引不变 MinIndex1<=3'd1; end endalways @(posedge InClk ) begin if (Indata2<=Indata3) begin MinValue2<=InData2; MinIndex2<=3'd2; end elsebegin MinValue2<=Indata3; MinIndex2<=3'd3; end endalways @(posedge InClk ) begin if (Indata4<=Indata5) begin MinValue3<=InData4; MinIndex3<=3'd4; end elsebegin MinValue3<=Indata5; MinIndex3<=3'd5; end end

经过上面的操作,(数据0和数据1比较)最小值是数据1,(数据2和数据3比较)最小值是数据1,(数据4和数据5比较)最小值是数据3。
接下来对数据1,2,3进行比较:首先比较数据1和数据2,较小的给数据4,数据3赋给数据5;再比较数据4和数据5,较小的给数据6,至此,数据6就是最小的数据了
always @(posedge InClk ) begin if (MinValue1<=MinValue2) begin MinValue4<=MinValue1; MinIndex4<=MinIndex1; end elsebegin MinValue4<=MinValue2; MinIndex4<=MinIndex2; end endalways @(posedge InClk ) begin MinValue5<=MinValue3; MinIndex5<=MinIndex3; endalways @(posedge InClk ) begin if (MinValue4<=MinValue5) begin MinValue6<=MinValue4; MinIndex6<=MinIndex4; end elsebegin MinValue6<=MinValue5; MinIndex6<=MinIndex5; end endassign OutMinValue = https://www.it610.com/article/MinValue6; assign OutMinIndex =MinIndex6;

冒泡排序的顺序都是可以自己定义的,不一定非要1~n,只要每次冒泡完成之后将数据值交换+索引交换即可!

    推荐阅读