电力电子转战数字IC——IC笔试面试Verilog合集(持续更新)

这里只记录Verilog题集,准备设计岗的。笔试题目更新在上一篇中。

目录

关于状态机编码,三段式编码方式中的三个always模块是什么作用?

Verilog实现3:8译码器

Verilog实现4位全加器

对异步复位D触发器对应的Verilog描述?

Verilog实现4*16同步FIFO


关于状态机编码,三段式编码方式中的三个always模块是什么作用?

第一个采用同步时序的方式描述状态转移;

阻塞赋值,描述状态寄存器

第一个采用组合逻辑的方式判断状态转移条件,描述状态转移规律;

描述转移,非阻塞赋值

第三个always模块使用同步时序电路描述每个状态的输出。

描述输出,阻塞(当前状态)与非阻塞赋值(下一个状态)都有

参考如下:

三段式状态机理解浅析_vegetable_birds123的博客-CSDN博客_三段式状态机

Verilog实现3:8译码器

输出3位二进制数,对应的十进制数作为点亮位输出

module decode_38 ( input wire[2:0] a, output reg[7:0] y ); 
integer i; 
always @(*) begin 
for (i=0;i<8;i=i+1) 
begin 
if (a==i) y[i]<=1; else y[i]<=0; end 
end 
endmodule

Verilog实现4位全加器

全加器的真值表如下,输入两个加数和进位,输出和、进位,这个做法是直接拼在一起

module adder( input clk, input rst, input [3:0] a,b; input ci, output [3:0] y, output co ) 
always @ (posedge clk, negedge rst) 
begin 
if(!rst) {co,y} <= 5'b00000; 
else 
begin {co,y} <= a + b + ci; end 
end
endmodule

如果按书里做化简

assign y=a^b^ci;
assign co=(a&b)|((a^b)&cin);

对异步复位D触发器对应的Verilog描述?

首先D触发器按照真值表是同或,相同出1;或者用非阻塞,clk到来输入进D触发器,下一个clk就输出

module huawei (D,Q1,Q2);
input D;
input Q1;
output Q2;
reg Q2;
assign Q2=D^~Q1
endmodule 

//或者
always @(posedge clk)
Q<=D;

异步复位就是有复位信号rst,rst为0时输出为1,rst为1时输出为输入的data

module dff_async_pre ( input data, clk, rst, output q ); 
parameter UDLY = 1; 
reg q; 
always @ (posedge clk or negedge rst) 
begin 
if ( ~rst) 
begin q <= #UDLY 1’b1; end 
else 
begin q <= #UDLY data; end 
end

Verilog实现4*16同步FIFO

同步FIFO见链接:

电力电子转战数字IC20220601day16——同步FIFO_广工陈奕湘的博客-CSDN博客

同步FIFO就是只有一个clk的FIFO,第一个问题是空满标志,读写指针完全相同为空,读写指针除了最高位相反其他位相同为满;

4*16就是4个16位的数据量,也就是mem或者RAM的容量 ,深度为4=2的2次方深度为2也就是DEPTH

这里的代码没有地址,直接把指针作为mem的地址,写成mem[指针]即可,而链接中第一次做的是有地址的。

总的设计思路就是:

写指针,不满时每一次写入一个data写指针就加1;读指针,不空时每一次读出一个data读指针就加1;读写指令就是allow允许读写的信号;

通过计数器count记录存储的数据数量,并以此判断空满(与链接中的看指针的方法不同)

module  fifo_four (clk, rstp, din, readp, writep, dout, emptyp, fullp) ; 
input clk; //时钟 
input rstp;               //复位 
input[15:0]din;           //16位输入信号 
input readp;              //读指令 
input writep;              //写指令 
output[15:0]dout;         //16位输出信号 
output emptyp;            //空指示信号 
output fullp;             //满指示信号 
parameter DEPTH=2,MAX_COUNT=2'b11; 
reg[15:0]dout; 
reg emptyp; 
reg fullp; 
reg[(DEPTH-1):0] tail; //读指针 
reg[(DEPTH-1):0] head;//写指针 
reg[(DEPTH-1):0] count; //计数器 
reg[15:0]fifomem[0:MAX_COUNT]; //四个16位存储单元 
//read 
always@(posedge clk) 
if(rstp==1)    
dout<=0;  
else if(readp==1&&emptyp==0) 
dout<=fifomem[tail]; 
//write   
always@(posedge clk) 
if(rstp==1&&writep==1&&fullp==0) 
fifomem[head]<=din; 
//更新head指针 
always@(posedge clk)    
if(rstp==1) head<=0; 
else if(writep==1&&fullp==0) 
head<=head+1; 
//更新tail指针 
always@(posedge clk)    
if(rstp==1) 
tail<=0; 
else if(readp==1&&emptyp==0) 
tail<=tail+1; 
//count 
always@(posedge clk) 
if(rstp==1) 
count<=0; 
else 
case({readp,writep}) 
2'b00: count<=count; 
2'b01: if(count!=MAX_COUNT) count<=count+1; 
2'b10: if(count!=0) count<=count-1; 
2'b11: count<=count; 
endcase 
//更新标志位emptyp 
always@(count) 
if(count==0) 
emptyp<=1; 
else 
emptyp<=0; 
//更新标志位tail 
always@(count) 
if(count==MAX_COUNT) 
tail<=1; 
else tail<=0; 
endmodule

第一次做的代码 


`timescale 1ns/1ps
//FIFO宽度16,FIFO深度256,深度2^8的FIFO需要的读写指针位宽8+1,多一位作为标志位
//所以这是个256*16的FIFO
module FIFO(
rst_n,
clk,
//read_clk,
read_allow,
read_data,
//write_clk,
write_allow,
write_data,
empty,
full);
 
input rst_n;
input clk;
//input write_clk;
input write_allow;
input [15:0] write_data;
//input read_clk;
input read_allow;
output reg [15:0] read_data;
 
output empty;
output full;
//reg [15:0] read_data;
 
reg [15:0] RAM [255:0];//存放数据
wire [7:0] read_address;
wire [7:0] write_address;//读写RAM的地址 
reg [8:0] read_pointer;
reg [8:0] write_pointer;//两个指针
 
 
//write_pointer
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
write_pointer<=9'd0;
else if(write_allow && (~full))//允许写且不满则每个时钟指针+1
write_pointer<=write_pointer+9'd1;
else
write_pointer<=write_pointer;//不允许写或者满了,写指针不变
end
 
assign write_address=write_pointer[7:0];//把指针除了标示位赋给写地址
 
//write,当允许写且不满时,把输入数据write_data给到RAM中的写地址
always @(posedge clk)
begin
if(write_allow &&(~full))
RAM[write_address]<=write_data;
else
RAM[write_address]<=RAM[write_address];
end
 
//read_pointer
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
read_pointer<=9'd0;
else if(read_allow && (~empty))//允许读且不空则每个时钟+1
read_pointer<=read_pointer+9'd1;
else
read_pointer<=read_pointer;//不允许读或者空了,读指针不变
end
 
assign read_address=read_pointer[7:0];//把指针除了标示位赋给读地址
 
//read,当允许读且不空时,把RAM中写进来的数据给到read_data
always @(posedge clk)
begin
if(read_allow &&(~empty))
read_data<=RAM[read_address];
else
read_data<='h0;
end
 
//空满标志
assign empty= (read_pointer==write_pointer)? 1:0;
assign  full= (write_pointer=={~(read_pointer[8]),read_pointer[7:0]})? 1:0;
 
endmodule 
————————————————
版权声明:本文为CSDN博主「广工陈奕湘」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_39668316/article/details/125085218

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值