網(wǎng)站后端開發(fā)流程刷百度關(guān)鍵詞排名
??途W(wǎng)Verilog刷題——VL46
- 題目
- 解析
- 答案
題目
??根據(jù)題目提供的雙口RAM代碼和接口描述,實(shí)現(xiàn)同步FIFO,要求FIFO位寬和深度參數(shù)化可配置。電路的接口如下圖所示。
??雙口RAM端口說明:
??同步FIFO端口說明:
??雙口RAM代碼如下,可在本題答案中添加并例化此代碼。
module dual_port_RAM #(parameter DEPTH = 16,parameter WIDTH = 8)(input wclk
,input wenc
,input [$clog2(DEPTH)-1:0] waddr //深度對2取對數(shù),得到地址的位寬。
,input [WIDTH-1:0] wdata //數(shù)據(jù)寫入
,input rclk
,input renc
,input [$clog2(DEPTH)-1:0] raddr //深度對2取對數(shù),得到地址的位寬。
,output reg [WIDTH-1:0] rdata //數(shù)據(jù)輸出
);reg [WIDTH-1:0] RAM_MEM [0:DEPTH-1];always @(posedge wclk) begin
if(wenc)
RAM_MEM[waddr] <= wdata;
end always @(posedge rclk) begin
if(renc)
rdata <= RAM_MEM[raddr];
end endmodule
??輸入輸出描述:
信號(hào) | 類型 | 輸入/輸出 | 位寬 | 描述 |
---|---|---|---|---|
clk | wire | Intput | 1 | 讀寫時(shí)鐘信號(hào) |
rstn | wire | Intput | 1 | 讀寫異步復(fù)位信號(hào),低電平有效 |
winc | wire | Intput | 1 | 寫使能信號(hào) |
rinc | wire | Intput | 1 | 讀使能信號(hào) |
wdata | wire | Intput | WIDTH | 寫數(shù)據(jù) |
wfull | wire | Output | 1 | 寫滿信號(hào) |
rempty | wire | Output | 1 | 讀空信號(hào) |
rdata | wire | Output | WIDTH | 讀數(shù)據(jù) |
解析
??同步FIFO中,讀操作與寫操作均在同一時(shí)鐘域下進(jìn)行,不涉及跨時(shí)鐘域操作,所以只需要用一個(gè)計(jì)數(shù)器來計(jì)數(shù)當(dāng)前FIFO中存儲(chǔ)的實(shí)際數(shù)據(jù)個(gè)數(shù)(寫入數(shù)據(jù)個(gè)數(shù)減去讀出數(shù)據(jù)個(gè)數(shù)),再用于判斷產(chǎn)生空滿信號(hào)即可。所以同步FIFO設(shè)計(jì)的要點(diǎn)就在于以下幾點(diǎn):
- 空滿信號(hào)判斷
答案
`timescale 1ns/1ns
/**********************************RAM************************************/
module dual_port_RAM #(parameter DEPTH = 16,parameter WIDTH = 8)(input wclk,input wenc,input [$clog2(DEPTH)-1:0] waddr //深度對2取對數(shù),得到地址的位寬。,input [WIDTH-1:0] wdata //數(shù)據(jù)寫入,input rclk,input renc,input [$clog2(DEPTH)-1:0] raddr //深度對2取對數(shù),得到地址的位寬。,output reg [WIDTH-1:0] rdata //數(shù)據(jù)輸出
);reg [WIDTH-1:0] RAM_MEM [0:DEPTH-1];always @(posedge wclk) beginif(wenc)RAM_MEM[waddr] <= wdata;
end always @(posedge rclk) beginif(renc)rdata <= RAM_MEM[raddr];
end endmodule /**********************************SFIFO************************************/
module sfifo#(parameter WIDTH = 8,parameter DEPTH = 16
)(input clk , input rst_n ,input winc ,input rinc ,input [WIDTH-1:0] wdata ,output reg wfull ,output reg rempty ,output wire [WIDTH-1:0] rdata
);//---------------------------------
// 使用內(nèi)部計(jì)數(shù)器設(shè)計(jì)同步FIFO
//---------------------------------
reg [$clog2(DEPTH)-1:0] waddr;
reg [$clog2(DEPTH)-1:0] raddr;
reg [$clog2(DEPTH):0] cnt;//內(nèi)部計(jì)數(shù)器
always @(posedge clk or negedge rst_n)if(!rst_n)cnt <= 'd0;else if(!wfull && !rempty && winc && rinc)cnt <= cnt;else if(!wfull && winc)cnt <= cnt + 1;else if(!rempty && rinc)cnt <= cnt - 1;elsecnt <= cnt;//空滿判斷
always @(posedge clk or negedge rst_n)if(!rst_n) beginwfull <= 1'b0;rempty <= 1'b0;endelse if(cnt == DEPTH) beginwfull <= 1'b1;rempty <= 1'b0;endelse if(cnt == 0) beginwfull <= 1'b0;rempty <= 1'b1;endelse beginwfull <= 1'b0;rempty <= 1'b0;end//寫地址
always @(posedge clk or negedge rst_n)if(!rst_n)waddr <= 'd0;else if(!wfull && winc)waddr <= waddr + 1'd1;elsewaddr <= waddr;//讀地址
always @(posedge clk or negedge rst_n)if(!rst_n)raddr <= 'd0;else if(!rempty && rinc)raddr <= raddr + 1'd1;elseraddr <= raddr;//雙端口RAM例化
dual_port_RAM
#( .DEPTH(DEPTH),.WIDTH(WIDTH)
)
dual_port_RAM_inst
(.wclk(clk),.wenc(winc && !wfull),.waddr(waddr), //深度對2取對數(shù),得到地址的位寬。.wdata(wdata), //數(shù)據(jù)寫入.rclk(clk),.renc(rinc && !rempty),.raddr(raddr), //深度對2取對數(shù),得到地址的位寬。.rdata(rdata) //數(shù)據(jù)輸出
);endmodule