学习摘自数字芯片实验室
Nvidia前端设计2018
1、什么是建立时间、保持时间?如果setup time violation或者hold time violation应该怎么做?
建立时间:在触发器的时钟信号边沿来临之前,数据稳定不变的时间
保持时间:在触发器的时钟信号边沿来临之后,数据稳定不变的时间
setup time :
Tclk - Tco – Tcomb + Tskew > Tsu
根据上述公式,解决setup violation,可以从一下角度考虑:
1、Tclk(时钟周期) : 增加Tclk,即降频
2、Tcomb(触发器之间组合逻辑延时): 减小Tcomb,即优化关键路径组合逻辑,减小负载,或者增加一个触发器来分割组合逻辑延时
3、Tskew(触发器之间时钟偏移):增加Tskew,即增加时钟路径的skew,可能会影响hold time violation
4、Tco 和 Tsu (库中器件固定属性):更换更快的标准单元库,即hvt - > lvt。
hold time :
Tco + Tcomb – Tskew > Thold
根据上述公式,解决hold violation,可以从一下角度考虑:
1、Tcomb :增加Tcomb,即增加组合逻辑延时,插入buffer。可能会影响setup violation
2、Tskew :减小Tskew,做好时钟树的balance
2、 Giventhe following design ,please draw out the waveform of outout Y.
其中,S= Async preset,异步置位
module demo(
input D ,
input CLK ,
input S ,
output Y );
reg Q ;
always@(posedge CLK or negedge S ) begin
if(~S) begin
Q <= 1'b1 ;
end
else begin
Q <= D ;
end
end
assign Y = D && Q ;
endmodule
module demo_tb;
reg D ;
reg CLK ;
reg S ;
wire Y ;
demo demo(
.D(D),
.CLK(CLK),
.S(S),
.Y(Y)
);
initial begin
CLK = 0 ;
S = 0 ;
#6 S= 1 ;
#52.5 S = 0 ;
end
initial begin
D = 0 ;
#16 D = 1 ;
#20 D = 0 ;
#30 D =1 ;
#4 D = 0 ;
end
always #5 CLK =~CLK ;
endmodule
3、Pleaseimprove the following design to save power
时钟门控
En = 1’b0 时,可以关闭时钟触发,减少动态功耗
题目电路仿真及功耗分析:
门控后仿真及功耗分析:
4、 Asyncfifo design using Verilog
Design:
module asyn_fifo(
input wclk ,
input rst_n ,
input wr_en ,
input [7 : 0] data_in ,
output full ,
input rclk ,
input rd_en ,
output reg [7:0] data_out ,
output empty
);
reg [7 : 0 ] mem[7 : 0] ;
wire [2:0] r_addr , w_addr ;
reg [3:0] binary_r_addr , binary_w_addr ;
wire [3:0] gray_r_addr , gray_w_addr ;
reg [3:0] gray_r_addr_reg , gray_w_addr_reg ;
assign gray_r_addr = ( binary_r_addr >> 1 ) ^ binary_r_addr;
assign gray_w_addr = ( binary_w_addr >> 1 ) ^ binary_w_addr;
assign r_addr = gray_r_addr[2:0] ;
assign w_addr = gray_w_addr[2:0] ;
always@(posedge rclk or negedge rst_n ) begin
if(~rst_n) begin
binary_r_addr <= 4'b0 ;
gray_w_addr_reg <= 4'b0 ;
data_out <= 8'b0 ;
end
else begin
gray_w_addr_reg <= gray_w_addr ;
if(rd_en == 1'b1 && empty == 1'b0) begin
data_out <= mem[r_addr] ;
binary_r_addr <= binary_r_addr + 1'b1 ;
end
end
end
always@(posedge wclk or negedge rst_n) begin
if(~rst_n) begin
binary_w_addr <= 4'b0 ;
gray_r_addr_reg <= 4'b0 ;
end
else begin
gray_r_addr_reg <= gray_r_addr ;
if(wr_en == 1'b1 && full == 1'b0 )begin
mem[w_addr] <= data_in ;
binary_w_addr <= binary_w_addr + 1'b1 ;
end
end
end
assign empty = (gray_r_addr == gray_w_addr_reg) ? 1:0 ;
assign full = ( (gray_w_addr[3] !== gray_r_addr_reg[3]) && (gray_w_addr[2] !== gray_r_addr_reg[2]) &&(gray_w_addr[1:0] == gray_r_addr_reg[1:0]) ) ? 1:0 ;
endmodule
Testbench:
`timescale 1ns/1ns
module async_fifo_tb;
reg rst_n;
reg wr_en ;
reg rclk;
wire [7:0] data_out;
wire full ;
reg [7:0] data_in;
reg wclk ;
reg rd_en ;
wire empty;
asyn_fifo asyn_fifo(
.wclk(wclk) ,
.rst_n(rst_n) ,
.wr_en(wr_en) ,
.data_in(data_in) ,
.full(full) ,
.rclk(rclk) ,
.rd_en(rd_en) ,
.data_out(data_out) ,
.empty(empty)
);
initial begin
rst_n=1;
rclk=0;
wclk=0;
#1 rst_n=0;
#5 rst_n=1;
end
initialbegin
wr_en=0;
#1 wr_en=1;
end
initial
begin
rd_en=0;
#650 rd_en=1;
wr_en=0;
end
always #30 rclk=~rclk;
always #20 wclk=~wclk;
initial begin
data_in=8'h0;
#40 data_in=8'h1;
#40 data_in=8'h2;
#40 data_in=8'h3;
#40 data_in=8'h4;
#40 data_in=8'h5;
#40 data_in=8'h6;
#40 data_in=8'h7;
#40 data_in=8'h8;
#40 data_in=8'h9;
#40 data_in=8'ha;
#40 data_in=8'hb;
#40 data_in=8'hc;
#40 data_in=8'hd;
#40 data_in=8'he;
#40 data_in=8'hf;
#1600 $finish;
end
endmodule
fifo写数据:
fifo读数据:
5、Design theschematic for the logic of New_en = eco_en ? (eco_mask ^ en) : en;
(Please ONLY use NAND2 cells ,and tryto use as less cells as possible)
数字电路卡诺图化简
用2输入与非门构成任意组合逻辑,这也是工具基于标准单元库进行逻辑综合的理论基础
了解逻辑综合之后,也就知道大学数字电路出这种题目的意义了。
6、Optimize thetiming paths from IN* to OUT.You can use inverter,nand2,nor2 and mux,assuming0.1ns delay ve the longest delay after optimization.
Hint :you cannot change logic insidethe boxes.
没看懂
7、Write verilog code which supports followingfunction:For a string A ,detect the location of its letters in string B ,and output the location of thelast detectedletter in string B.For example :string Ais “nvidia” and string B is “naabcdiaiccbvde”,the last detected letter in B isv , so output 13.
Design
module sequence_detect(
input clk,
input rst_n,
input [7:0] stringB_in,
input stringB_en ,
input stringB_over ,
output reg [4:0] location,
output reg out_valid
);
reg [4:0] location_reg_count;
always @ (posedge clk or negedge rst_n) begin
if(!rst_n)
location_reg_count <= 5'd0;
else if(stringB_en == 1'b1 && stringB_over == 1'b0) begin
location_reg_count <= location_reg_count+1;
end
end
reg [4:0] location_reg;
always @ (posedge clk or negedge rst_n) begin
if(!rst_n)
location_reg <= 0;
else if (stringB_en == 1'b1 && stringB_over == 1'b0 ) begin
if(stringB_in == "n" || stringB_in == "v" || stringB_in == "i" ||stringB_in == "d" || stringB_in == "a") begin
location_reg <= location_reg_count ;
end
else begin
location_reg <= location_reg ;
end
end
end
always @ (posedge clk or negedge rst_n) begin
if(!rst_n)
out_valid <= 0;
else if (stringB_over == 1'b1 ) begin
location <= location_reg ;
out_valid <= 1'b1;
end
else begin
location <= 0 ;
out_valid <= 1'b0;
end
end
endmodule
Testbench:
`timescale 1ns/1ps
module sequence_detect_tb;
reg clk;
reg rst_n;
reg stringB_en ;
reg stringB_over ;
reg [7:0] stringB_in;
wire [4:0] location;
wire out_valid;
// instance of the DUT
sequence_detect sequence_detect(
.clk(clk),
.rst_n(rst_n),
.stringB_in(stringB_in),
.stringB_en(stringB_en),
.stringB_over(stringB_over) ,
.location(location),
.out_valid(out_valid)
);
always #5 clk = ~clk;
initial begin
clk = 1'b0;
rst_n = 1'b1;
stringB_en = 1'b0;
stringB_over = 1'b0 ;
stringB_in = "0" ;
#100 rst_n = 1'b0;
#100 rst_n = 1'b1;
stringB_en = 0;
end
initial begin
end
initial begin
#300 ;
stringB_en = 1;
#1 stringB_in = "n" ;
@(posedge clk ) ;
#1 stringB_in = "a" ;
@(posedge clk ) ;
#1 stringB_in = "a" ;
@(posedge clk ) ;
#1 stringB_in = "b" ;
@(posedge clk ) ;
#1 stringB_in = "c" ;
@(posedge clk ) ;
#1 stringB_in = "d" ;
@(posedge clk ) ;
#1 stringB_in = "i" ;
@(posedge clk ) ;
#1 stringB_in = "a" ;
@(posedge clk ) ;
#1 stringB_in = "i" ;
@(posedge clk ) ;
#1 stringB_in = "c" ;
@(posedge clk ) ;
#1 stringB_in = "c" ;
@(posedge clk ) ;
#1 stringB_in = "b" ;
@(posedge clk ) ;
#1 stringB_in = "v" ;
@(posedge clk ) ;
#1 stringB_in = "d" ;
@(posedge clk ) ;
#1 stringB_in = "e" ;
@(posedge clk ) ;
#1 stringB_in = "0" ;
@(posedge clk ) ;
stringB_over = 1'b1 ;
end
initial begin
#1000 $finish;
end
endmodule