Use the Migen asynchronous FIFO

This commit is contained in:
Sebastien Bourdeauducq 2013-04-25 19:43:26 +02:00
parent d64b64501a
commit 4ff1175dcf
4 changed files with 9 additions and 162 deletions

View file

@ -27,10 +27,6 @@ TIMESPEC "TSphy_tx_clk" = PERIOD "GRPphy_tx_clk" 40 ns HIGH 50%;
TIMESPEC "TSphy_tx_clk_io" = FROM "GRPphy_tx_clk" TO "PADS" 10 ns; TIMESPEC "TSphy_tx_clk_io" = FROM "GRPphy_tx_clk" TO "PADS" 10 ns;
TIMESPEC "TSphy_rx_clk_io" = FROM "PADS" TO "GRPphy_rx_clk" 10 ns; TIMESPEC "TSphy_rx_clk_io" = FROM "PADS" TO "GRPphy_rx_clk" 10 ns;
NET "asfifo*/counter_read/gray_count*" TIG;
NET "asfifo*/counter_write/gray_count*" TIG;
NET "asfifo*/preset_empty*" TIG;
NET "{dviclk0}" TNM_NET = "GRPdviclk0"; NET "{dviclk0}" TNM_NET = "GRPdviclk0";
NET "{dviclk0}" CLOCK_DEDICATED_ROUTE = FALSE; NET "{dviclk0}" CLOCK_DEDICATED_ROUTE = FALSE;
TIMESPEC "TSdviclk0" = PERIOD "GRPdviclk0" 26.7 ns HIGH 50%; TIMESPEC "TSdviclk0" = PERIOD "GRPdviclk0" 26.7 ns HIGH 50%;
@ -44,7 +40,7 @@ TIMESPEC "TSdviclk1" = PERIOD "GRPdviclk1" 26.7 ns HIGH 50%;
dviclk0=platform.lookup_request("dvi_in", 0).clk, dviclk0=platform.lookup_request("dvi_in", 0).clk,
dviclk1=platform.lookup_request("dvi_in", 1).clk) dviclk1=platform.lookup_request("dvi_in", 1).clk)
for d in ["generic", "m1crg", "s6ddrphy", "minimac3"]: for d in ["m1crg", "s6ddrphy", "minimac3"]:
platform.add_source_dir(os.path.join("verilog", d)) platform.add_source_dir(os.path.join("verilog", d))
platform.add_sources(os.path.join("verilog", "lm32", "submodule", "rtl"), platform.add_sources(os.path.join("verilog", "lm32", "submodule", "rtl"),
"lm32_cpu.v", "lm32_instruction_unit.v", "lm32_decoder.v", "lm32_cpu.v", "lm32_instruction_unit.v", "lm32_decoder.v",

View file

@ -2,6 +2,7 @@ from migen.fhdl.structure import *
from migen.fhdl.specials import Instance from migen.fhdl.specials import Instance
from migen.fhdl.module import Module from migen.fhdl.module import Module
from migen.genlib.record import Record from migen.genlib.record import Record
from migen.genlib.fifo import AsyncFIFO
from migen.flow.actor import * from migen.flow.actor import *
from migen.flow.network import * from migen.flow.network import *
from migen.flow.transactions import * from migen.flow.transactions import *
@ -132,33 +133,15 @@ class FIFO(Module):
### ###
data_width = 2+2*3*_bpc_dac data_width = 2+2*3*_bpc_dac
fifo_full = Signal() fifo = AsyncFIFO(data_width, 256)
fifo_write_en = Signal() self.add_submodule(fifo, {"write": "sys", "read": "vga"})
fifo_read_en = Signal()
fifo_data_out = Signal(data_width)
fifo_data_in = Signal(data_width)
self.specials += Instance("asfifo",
Instance.Parameter("data_width", data_width),
Instance.Parameter("address_width", 8),
Instance.Output("data_out", fifo_data_out),
Instance.Output("empty"),
Instance.Input("read_en", fifo_read_en),
Instance.Input("clk_read", ClockSignal("vga")),
Instance.Input("data_in", fifo_data_in),
Instance.Output("full", fifo_full),
Instance.Input("write_en", fifo_write_en),
Instance.Input("clk_write", ClockSignal()),
Instance.Input("rst", 0))
fifo_in = self.dac.payload fifo_in = self.dac.payload
fifo_out = Record(_dac_layout) fifo_out = Record(_dac_layout)
self.comb += [ self.comb += [
self.dac.ack.eq(~fifo_full), self.dac.ack.eq(fifo.writable),
fifo_write_en.eq(self.dac.stb), fifo.we.eq(self.dac.stb),
fifo_data_in.eq(fifo_in.raw_bits()), fifo.din.eq(fifo_in.raw_bits()),
fifo_out.raw_bits().eq(fifo_data_out), fifo_out.raw_bits().eq(fifo.dout),
self.busy.eq(0) self.busy.eq(0)
] ]
@ -177,7 +160,7 @@ class FIFO(Module):
self.vga_b.eq(fifo_out.p0.b) self.vga_b.eq(fifo_out.p0.b)
) )
] ]
self.comb += fifo_read_en.eq(pix_parity) self.comb += fifo.re.eq(pix_parity)
def sim_fifo_gen(): def sim_fifo_gen():
while True: while True:

View file

@ -1,103 +0,0 @@
/*
* This file is based on "Asynchronous FIFO" by Alex Claros F.,
* itself based on the article "Asynchronous FIFO in Virtex-II FPGAs"
* by Peter Alfke.
*/
module asfifo #(
parameter data_width = 8,
parameter address_width = 4,
parameter fifo_depth = (1 << address_width)
) (
/* Read port */
output reg [data_width-1:0] data_out,
output reg empty,
input read_en,
input clk_read,
/* Write port */
input [data_width-1:0] data_in,
output reg full,
input write_en,
input clk_write,
/* Asynchronous reset */
input rst
);
reg [data_width-1:0] mem[fifo_depth-1:0];
wire [address_width-1:0] write_index, read_index;
wire equal_addresses;
wire write_en_safe, read_en_safe;
wire set_status, clear_status;
reg status;
wire preset_full, preset_empty;
reg [data_width-1:0] data_out0;
always @(posedge clk_read) begin
data_out0 <= mem[read_index];
data_out <= data_out0;
end
always @(posedge clk_write) begin
if(write_en & !full)
mem[write_index] <= data_in;
end
assign write_en_safe = write_en & ~full;
assign read_en_safe = read_en & ~empty;
asfifo_graycounter #(
.width(address_width)
) counter_write (
.gray_count(write_index),
.ce(write_en_safe),
.rst(rst),
.clk(clk_write)
);
asfifo_graycounter #(
.width(address_width)
) counter_read (
.gray_count(read_index),
.ce(read_en_safe),
.rst(rst),
.clk(clk_read)
);
assign equal_addresses = (write_index == read_index);
assign set_status = (write_index[address_width-2] ~^ read_index[address_width-1]) &
(write_index[address_width-1] ^ read_index[address_width-2]);
assign clear_status = ((write_index[address_width-2] ^ read_index[address_width-1]) &
(write_index[address_width-1] ~^ read_index[address_width-2]))
| rst;
always @(posedge clear_status, posedge set_status) begin
if(clear_status)
status <= 1'b0;
else
status <= 1'b1;
end
assign preset_full = status & equal_addresses;
always @(posedge clk_write, posedge preset_full) begin
if(preset_full)
full <= 1'b1;
else
full <= 1'b0;
end
assign preset_empty = ~status & equal_addresses;
always @(posedge clk_read, posedge preset_empty) begin
if(preset_empty)
empty <= 1'b1;
else
empty <= 1'b0;
end
endmodule

View file

@ -1,29 +0,0 @@
/*
* This file is based on "Asynchronous FIFO" by Alex Claros F.,
* itself based on the article "Asynchronous FIFO in Virtex-II FPGAs"
* by Peter Alfke.
*/
module asfifo_graycounter #(
parameter width = 2
) (
output reg [width-1:0] gray_count,
input ce,
input rst,
input clk
);
reg [width-1:0] binary_count;
always @(posedge clk, posedge rst) begin
if(rst) begin
binary_count <= {width{1'b0}} + 1;
gray_count <= {width{1'b0}};
end else if(ce) begin
binary_count <= binary_count + 1;
gray_count <= {binary_count[width-1],
binary_count[width-2:0] ^ binary_count[width-1:1]};
end
end
endmodule