framebuffer: FIFO
authorSebastien Bourdeauducq <sebastien@milkymist.org>
Sun, 1 Jul 2012 13:22:57 +0000 (15:22 +0200)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Sun, 1 Jul 2012 13:22:57 +0000 (15:22 +0200)
milkymist/framebuffer/__init__.py
verilog/generic/asfifo.v [new file with mode: 0644]
verilog/generic/asfifo_graycounter.v [new file with mode: 0644]

index b30e1acd6d62f2cf605fd86277fc14fa6ddf8f21..f7d8c1b7104ed23bb93f54378934de254dbfc10c 100644 (file)
@@ -111,12 +111,44 @@ class FIFO(Actor):
                self.vga_clk = Signal()
                self.vga_hsync_n = Signal()
                self.vga_vsync_n = Signal()
-               self.vga_r = Signal(BV(8))
-               self.vga_g = Signal(BV(8))
-               self.vga_b = Signal(BV(8))
+               self.vga_r = Signal(BV(_bpc_dac))
+               self.vga_g = Signal(BV(_bpc_dac))
+               self.vga_b = Signal(BV(_bpc_dac))
        
        def get_fragment(self):
-               return Fragment() # TODO
+               data_width = 2+3*_bpc_dac
+               asfifo = Instance("asfifo",
+                       [
+                               ("data_out", BV(data_width)),
+                               ("empty", BV(1)),
+                               
+                               ("full", BV(1))
+                       ], [
+                               ("read_en", BV(1)),
+                               ("clk_read", self.vga_clk),
+                               
+                               ("data_in", BV(data_width)),
+                               ("write_en", BV(1)),
+                               
+                               ("rst", BV(1))
+                       ],
+                       parameters=[
+                               ("data_width", data_width),
+                               ("address_width", 8)
+                       ],
+                       clkport="clk_write")
+               t = self.token("dac")
+               return Fragment([
+                       Cat(self.vga_hsync_n, self.vga_vsync_n, self.vga_r, self.vga_g, self.vga_b).eq(asfifo.outs["data_out"]),
+                       asfifo.ins["read_en"].eq(1),
+                       
+                       self.endpoints["dac"].ack.eq(~asfifo.outs["full"]),
+                       asfifo.ins["write_en"].eq(self.endpoints["dac"].stb),
+                       asfifo.ins["data_in"].eq(Cat(~t.hsync, ~t.vsync, t.r, t.g, t.b)),
+                       
+                       self.busy.eq(0),
+                       asfifo.ins["rst"].eq(0)
+               ], instances=[asfifo])
 
 class Framebuffer:
        def __init__(self, address, asmiport):
diff --git a/verilog/generic/asfifo.v b/verilog/generic/asfifo.v
new file mode 100644 (file)
index 0000000..1618964
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * 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 [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;
+
+assign data_out = mem[read_index];
+
+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
diff --git a/verilog/generic/asfifo_graycounter.v b/verilog/generic/asfifo_graycounter.v
new file mode 100644 (file)
index 0000000..531ca80
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * 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