for (j=3; j<=0; j=j-1) begin
if (j=3) // 最上位はそのままグレーコードに
wgray[3] <= inc_wp[3];
else
if (wgray[i-1]) // 上位の桁が1だったら
wgray[i] <= ~inc_wp[i];
else // 0だったらそのまま
wgray[i] <= inc_wp[i];
end
wgray <= {inc_wp[3], inc_wp[2:0] ^ inc_wp[3:1]}; // 結局上位の桁をXORすればOK
assign rdbinary = {rgrayd2[3], rgrayd2[2:0] ^ rgrayd2[3:1]};
// Read Gray Counterの値をバイナリ変換
always @* begin : READ_GRAY2BINARY
integer j;
for(j=3; j>=0; j=j-1) begin
if (j==3)
rdbinary[j] <= rgrayd2[j];
else
rdbinary[j] <= rgrayd2[j] ^ rdbinary[j+1];
end
end
// async_fifo.v
// 4bitアドレス、15深度
// Dual-Port RAMはRAM16X1Dプリミティブを使用する
// 出力は同期化されていないので、上のモジュールでFFを通す必要がある
`default_nettype none
`timescale 1ns / 1ps
module async_fifo (
din,
rd_clk,
rd_en,
rst,
wr_clk,
wr_en,
almost_empty,
almost_full,
dout,
empty,
full);
input wire [15 : 0] din;
input wire rd_clk;
input wire rd_en;
input wire rst;
input wire wr_clk;
input wire wr_en;
output wire almost_empty;
output wire almost_full;
output wire [15 : 0] dout;
output wire empty;
output wire full;
reg [3:0] wp, rp;
wire [3:0] inc_wp, inc_rp;
reg [3:0] wgray, rgray;
reg [3:0] rgrayd1, rgrayd2;
reg [3:0] wgrayd1, wgrayd2;
reg [3:0] rdbinary, wrbinary;
generate
genvar i;
for (i=15; i>=0; i=i-1) begin : DPRAM_GEN
RAM16X1D #(
.INIT(16'h000)
) RAM16X1D_inst (
.WCLK(wr_clk),
.WE(wr_en),
.A0(wp[0]),
.A1(wp[1]),
.A2(wp[2]),
.A3(wp[3]),
.D(din[i]),
.SPO(),
.DPRA0(rp[0]),
.DPRA1(rp[1]),
.DPRA2(rp[2]),
.DPRA3(rp[3]),
.DPO(dout[i])
);
end
endgenerate
// Write Clock Domain
assign inc_wp = wp + 1;
always @(posedge wr_clk, posedge rst) begin : WRITE_COUNTERS
integer j;
if (rst) begin
wp <= 4'h0;
wgray <= 4'h0;
end else begin
if (wr_en) begin
wp <= wp + 4'h1;
wgray <= {inc_wp[3], inc_wp[2:0] ^ inc_wp[3:1]}; // 結局上位の桁をXORすればOK
end
end
end
// Read Gray Counterからのグレーコードをwr_clkで同期化する
always @(posedge wr_clk, posedge rst) begin
if (rst) begin
rgrayd1 <= 4'h0;
rgrayd2 <= 4'h0;
end else begin
rgrayd1 <= rgray;
rgrayd2 <= rgrayd1;
end
end
// Read Gray Counterの値をバイナリ変換
always @* begin : READ_GRAY2BINARY
integer j;
for(j=3; j>=0; j=j-1) begin
if (j==3)
rdbinary[j] <= rgrayd2[j];
else
rdbinary[j] <= rgrayd2[j] ^ rdbinary[j+1];
end
end
assign full = (wp == rdbinary-4'h1) ? 1'b1 : 1'b0;
assign almost_full = (wp==rdbinary-4'h2) ? 1'b1 : 1'b0;
//Read Clock Domain
assign inc_rp = rp + 1;
always @(posedge rd_clk, posedge rst) begin : READ_COUNTERS
integer j;
if (rst) begin
rp <= 4'h0;
rgray <= 4'h0;
end else begin
if (rd_en) begin
rp <= rp + 4'h1;
rgray <= {inc_rp[3], inc_rp[2:0] ^ inc_rp[3:1]}; // 結局上位の桁をXORすればOK
end
end
end
// Write Gray Counterからのグレーコードをrd_clkで同期化する
always @(posedge rd_clk, posedge rst) begin
if (rst) begin
wgrayd1 <= 4'h0;
wgrayd2 <= 4'h0;
end else begin
wgrayd1 <= wgray;
wgrayd2 <= wgrayd1;
end
end
// Write Gray Counterの値をバイナリ変換
always @* begin : WRITE_GRAY2BINARY
integer j;
for(j=3; j>=0; j=j-1) begin
if (j==3)
wrbinary[j] <= wgrayd2[j];
else
wrbinary[j] <= wgrayd2[j] ^ wrbinary[j+1];
end
end
assign empty = (wrbinary == rp) ? 1'b1 : 1'b0;
assign almost_empty = (wrbinary-4'h1==rp) ? 1'b1 : 1'b0;
endmodule
日 | 月 | 火 | 水 | 木 | 金 | 土 |
---|---|---|---|---|---|---|
- | - | - | - | - | 1 | 2 |
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 | - | - | - | - | - | - |