这里只记录Verilog题集,准备设计岗的。笔试题目更新在上一篇中。
目录
关于状态机编码,三段式编码方式中的三个always模块是什么作用?
关于状态机编码,三段式编码方式中的三个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