FPGA笔试题解析(五):Verilog程序设计

题目:使用状态机实现序列检测器?

序列检测器的状态机实现,以前的博文写的很多,这里贴出两个简单易懂的,看需要的部分即可:

序列检测器的Moore状态机实现

序列检测器的Mealy状态机实现


题目:用Verilog设计串专并电路?

在下面这篇博文中,包含串转并以及并转串的思路:移位寄存器专题

1. module left_shifter_reg(clk, din, dout);  
 
2.     input clk;  
 
3.     input din;  
 
4.     output [7:0] dout;  
 
5.     wire [7:0] dout;  
 
6.     reg [7:0] qtemp;  
 
7.     always @ (posedge clk)  
 
8.         begin  
 
9.             qtemp <= {qtemp[6:0], din}; //每次输入一位  
 
10.         end  
 
11.     assign dout = qtemp; //并行输出  
 
12.   
 
13. endmodule  

并转串

1. module right_shifter_reg(clk, en, din, dout);  
 
2.     input [7:0] din;  
 
3.     input en,clk;  
 
4.     output dout;  
 
5.     reg dout;  
 
6.     reg [7:0] qtemp;  
 
7.     always @(posedge clk)  
 
8.         begin  
 
9.             if(en == 1)  
 
10.                 qtemp <= din;  
 
11.             else  
 
12.                 begin  
 
13.                     dout <= qtemp[0];  
 
14.                     qtemp <= {qtemp[0], qtemp[7:1]};  
 
15.                 end  
 
16.         end  
 
17.   
 
18. endmodule 

题目:设计分频电路?

二分频:https://blog.csdn.net/Reborn_Lee/article/details/85254025

module clkdiv2(
    input ClkIn,
    input rst,
    output ClkOut
    );
    reg ClkOut;
    always@(posedge ClkIn)
    begin
    if(rst) ClkOut = 1'b0;
    else ClkOut = ~ClkOut;
    end
endmodule

奇偶分频:https://blog.csdn.net/Reborn_Lee/article/details/81298123

先看简单的偶分频电路设计,以10分频为例,意思就是频率降低10倍,那么周期就增大10倍,这样我只需要在原来时钟五倍周期时候翻转一次即可实现10分频电路,这是思路,具体实现时,我们使用计数器来完成10分频电路,计数器的初值为0,每到一个时钟上升沿计数一次并判断是否计数达到要求。

那么计数要求是多少呢?

当然是4,当计数器计数到4,也就是第4个上升沿到来时,要等到下一个上升沿到来判断计数是否到4,同时翻转时钟,这就达到了目的,具体代码移植以前的博文:

//偶分频电路的Verilog HDL设计(10分频为例)
module even_freq_div(clk, rst, clk_div10,cnt);
 
input clk;
input rst;
output clk_div10;
reg clk_div10;
output [2:0] cnt;          //输出cnt的原因是为了看到计数次数,便于分析仿真结果。
reg [2:0] cnt;
 
 
 
always @(posedge clk)
begin
	if(rst)  //复位信号有效;
	begin
		cnt <= 0;          //计数器清零
		clk_div10 <= 0;    //输出清零;
	end
	else     //复位信号无效;
	begin
		if(cnt == 4)                //每一次时钟上升沿到来时,都检查一次计数值是否达到4;
		begin
			clk_div10 <= ~clk_div10;
			cnt <= 0; //计数器计数到4后,重新清零;计数值为4意味着已经计了5个周期,这时10分频时钟翻转一次;
		end
		else     //如果计数器未计数到4,则来一个上升沿加1,同时分频时钟继续保持原值不变。
		begin
			cnt <= cnt + 1;           
			clk_div10 <= clk_div10;  //否则继续保持;
		end
	end
	
end
 
 
endmodule

功能仿真:

可以数数看,恰好是十分频。

接着看奇分频,且为占空比为50%的奇分频电路,以5分频为例:

表面上说,应该对被分频时钟计数2.5个时钟周期翻转一次,但如何计数2.5个周期是一个问题,有人可能会说,上升沿下降沿同时计数,想法很丰满,但在Verilog HDL代码设计中,要变一种实现方式:

首先产生一个与被分频时钟相位相反的时钟,这两个时钟的上升沿都计数即可,代码如下:

//奇分频电路的Verilog HDL设计(5分频为例)
module odd_freq_div(clk, rst, clk_div, cnt);
 
input clk;
input rst;
output clk_div;
reg clk_div;
output [2:0] cnt;          //输出cnt的原因是为了看到计数次数,便于分析仿真结果。
reg [2:0] cnt;
wire clk1;
 
assign clk1 = ~clk;         //相位与clk相差180°;
 
always @(posedge clk or posedge clk1)
begin
	if(rst)  //复位信号有效;
	begin
		cnt <= 0;          //计数器清零
		clk_div <= 0;    //输出清零;
	end
	else     //复位信号无效;
	begin
		if(cnt == 4)                //每一次时钟上升沿到来时,都检查一次计数值是否达到4;
		begin
			clk_div <= ~clk_div;
			cnt <= 0; //计数器计数到4后,重新清零;
		end
		else     //如果计数器未计数到4,则来一个上升沿加1,同时分频时钟继续保持原值不变。
		begin
			cnt <= cnt + 1;           
			clk_div <= clk_div;  //否则继续保持;
		end
	end
	
end
 
 
endmodule

功能仿真图:

至于其他幺蛾子,见原博文:https://blog.csdn.net/Reborn_Lee/article/details/81298123#%E5%89%8D%E8%A8%80%EF%BC%9A

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(#)