generated from saji/ecp5-template
wip: 4x clock double-read bram
This commit is contained in:
parent
2a8c70bab2
commit
bcb463a8d0
|
@ -93,10 +93,10 @@ _connectors = [
|
||||||
class _CRG(LiteXModule):
|
class _CRG(LiteXModule):
|
||||||
def __init__(self, platform, sys_clk_freq, with_reset = False):
|
def __init__(self, platform, sys_clk_freq, with_reset = False):
|
||||||
self.cd_sys = ClockDomain("sys")
|
self.cd_sys = ClockDomain("sys")
|
||||||
self.cd_hub = ClockDomain("hub")
|
# self.cd_hub = ClockDomain("hub")
|
||||||
# self.cd_sdram = ClockDomain("sdram")
|
self.cd_sys_ps = ClockDomain("sys_ps")
|
||||||
self.cd_sys2x = ClockDomain()
|
# self.cd_sys2x = ClockDomain()
|
||||||
self.cd_sys2x_ps = ClockDomain()
|
# self.cd_sys2x_ps = ClockDomain()
|
||||||
|
|
||||||
# Clk / Rst.
|
# Clk / Rst.
|
||||||
clk25 = platform.request("clk25")
|
clk25 = platform.request("clk25")
|
||||||
|
@ -110,12 +110,12 @@ class _CRG(LiteXModule):
|
||||||
pll.register_clkin(clk25, 25e6)
|
pll.register_clkin(clk25, 25e6)
|
||||||
pll.create_clkout(self.cd_sys, sys_clk_freq)
|
pll.create_clkout(self.cd_sys, sys_clk_freq)
|
||||||
# for the sdram
|
# for the sdram
|
||||||
# pll.create_clkout(self.cd_sdram, sys_clk_freq, phase=180)
|
pll.create_clkout(self.cd_sys_ps, sys_clk_freq, phase=180)
|
||||||
pll.create_clkout(self.cd_sys2x, 2*sys_clk_freq)
|
# pll.create_clkout(self.cd_sys2x, 2*sys_clk_freq)
|
||||||
pll.create_clkout(self.cd_sys2x_ps, 2*sys_clk_freq, phase=180)
|
# pll.create_clkout(self.cd_sys2x_ps, 2*sys_clk_freq, phase=180)
|
||||||
|
|
||||||
sdram_clk = ClockSignal("sys2x_ps")
|
# sdram_clk = ClockSignal("sys2x_ps")
|
||||||
# sdram_clk = ClockSignal("sdram")
|
sdram_clk = ClockSignal("sys_ps")
|
||||||
self.specials += DDROutput(1,0, platform.request("sdram_clock"), sdram_clk)
|
self.specials += DDROutput(1,0, platform.request("sdram_clock"), sdram_clk)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -27,28 +27,28 @@ class GroovySoC(SoCCore):
|
||||||
self.submodules += self.crg
|
self.submodules += self.crg
|
||||||
print(kwargs)
|
print(kwargs)
|
||||||
|
|
||||||
if not self.integrated_main_ram_size:
|
# if not self.integrated_main_ram_size:
|
||||||
self.sdrphy = HalfRateGENSDRPHY(platform.request("sdram"), sys_clk_freq)
|
# self.sdrphy = GENSDRPHY(platform.request("sdram"), sys_clk_freq)
|
||||||
self.add_sdram("sdram",
|
# self.add_sdram("sdram",
|
||||||
phy = self.sdrphy,
|
# phy = self.sdrphy,
|
||||||
module = M12L64322A(sys_clk_freq, "1:2"),
|
# module = M12L64322A(sys_clk_freq, "1:1"),
|
||||||
l2_cache_size = kwargs.get("l2_size", 8192),
|
# l2_cache_size = kwargs.get("l2_size", 8192),
|
||||||
)
|
# )
|
||||||
|
#
|
||||||
|
#
|
||||||
self.submodules.ethphy = LiteEthPHYRGMII(
|
# self.submodules.ethphy = LiteEthPHYRGMII(
|
||||||
clock_pads= self.platform.request("eth_clocks", 0),
|
# clock_pads= self.platform.request("eth_clocks", 0),
|
||||||
pads = self.platform.request("eth", 0),
|
# pads = self.platform.request("eth", 0),
|
||||||
tx_delay = 0e-9, # not sure what this is
|
# tx_delay = 0e-9, # not sure what this is
|
||||||
)
|
# )
|
||||||
self.add_csr("ethphy")
|
# self.add_csr("ethphy")
|
||||||
self.add_etherbone(phy=self.ethphy, ip_address="192.168.0.36", mac_address = 0x10e2d5000001, data_width=32)
|
# # self.add_etherbone(phy=self.ethphy, ip_address="192.168.0.36", mac_address = 0x10e2d5000001, data_width=32)
|
||||||
if use_spi:
|
# if use_spi:
|
||||||
from litespi.modules import W25Q32JV as SpiFlashModule
|
# from litespi.modules import W25Q32JV as SpiFlashModule
|
||||||
from litespi.opcodes import SpiNorFlashOpCodes
|
# from litespi.opcodes import SpiNorFlashOpCodes
|
||||||
self.mem_map["spiflash"] = 0x20000000
|
# self.mem_map["spiflash"] = 0x20000000
|
||||||
mod = SpiFlashModule(SpiNorFlashOpCodes.READ_1_1_1)
|
# mod = SpiFlashModule(SpiNorFlashOpCodes.READ_1_1_1)
|
||||||
self.add_spi_flash(mode="1x", module=SpiFlashModule, with_master=False)
|
# self.add_spi_flash(mode="1x", module=SpiFlashModule, with_master=False)
|
||||||
self.platform.add_extension(make_hub75_iodevice(0, "j8"))
|
self.platform.add_extension(make_hub75_iodevice(0, "j8"))
|
||||||
hub_io = self.platform.request("hub75_iodev", 0)
|
hub_io = self.platform.request("hub75_iodev", 0)
|
||||||
self.submodules.hub75 = hub75 = Hub75VerilogDriver()
|
self.submodules.hub75 = hub75 = Hub75VerilogDriver()
|
||||||
|
@ -85,7 +85,7 @@ def main():
|
||||||
trellis_args(parser.add_argument_group('Trellis options'))
|
trellis_args(parser.add_argument_group('Trellis options'))
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
platform = Groovy1Platform()
|
platform = Groovy1Platform()
|
||||||
soc = GroovySoC(platform, 60e6, **soc_core_argdict(args))
|
soc = GroovySoC(platform, 120e6, **soc_core_argdict(args))
|
||||||
|
|
||||||
|
|
||||||
builder = Builder(soc, **builder_argdict(args))
|
builder = Builder(soc, **builder_argdict(args))
|
||||||
|
|
|
@ -38,30 +38,12 @@ module coordinator (
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
// slicer signals
|
|
||||||
wire bitslice_start;
|
|
||||||
wire [5:0] bitplane_data;
|
|
||||||
wire [10:0] bitplane_addr;
|
|
||||||
wire bitplane_wren;
|
|
||||||
wire bitplane_done;
|
|
||||||
|
|
||||||
bitslicer bslice (
|
|
||||||
.clk(clk),
|
|
||||||
.rgb0(pix_rgb0),
|
|
||||||
.rgb1(pix_rgb1),
|
|
||||||
.pixnum(x),
|
|
||||||
.start_write(bitslice_start),
|
|
||||||
.bitplane_data(bitplane_data),
|
|
||||||
.bitplane_addr(bitplane_addr),
|
|
||||||
.bitplane_wren(bitplane_wren),
|
|
||||||
.done(bitplane_done)
|
|
||||||
);
|
|
||||||
|
|
||||||
// bram signals
|
// bram signals
|
||||||
|
|
||||||
wire [8:0] din;
|
wire [35:0] din;
|
||||||
wire [8:0] dout;
|
wire [35:0] dout;
|
||||||
wire [10:0] addr_r;
|
wire [8:0] addr_r;
|
||||||
wire read_clk;
|
wire read_clk;
|
||||||
wire write_clk;
|
wire write_clk;
|
||||||
|
|
||||||
|
@ -117,6 +99,7 @@ module coordinator (
|
||||||
state <= StateGenerateLine;
|
state <= StateGenerateLine;
|
||||||
end
|
end
|
||||||
StateGenerateLine: begin
|
StateGenerateLine: begin
|
||||||
|
// generate data, move it into the bram.
|
||||||
pixgen_start <= 0;
|
pixgen_start <= 0;
|
||||||
if (bitplane_done) begin
|
if (bitplane_done) begin
|
||||||
if (x < 128) begin
|
if (x < 128) begin
|
||||||
|
|
|
@ -9,32 +9,28 @@ module hub75e (
|
||||||
output reg done = 0,
|
output reg done = 0,
|
||||||
|
|
||||||
// bram interface (using clk)
|
// bram interface (using clk)
|
||||||
output [10:0] pixbuf_addr,
|
output reg [8:0] pixbuf_addr,
|
||||||
input [ 8:0] pixbuf_data
|
input [35:0] pixbuf_data
|
||||||
);
|
);
|
||||||
|
|
||||||
parameter integer ROW_DEPTH = 128, BIT_DEPTH = 8;
|
parameter ROW_DEPTH = 128, BIT_DEPTH = 8, BCM_LEN = 32;
|
||||||
|
|
||||||
reg [31:0] counter = 0;
|
reg [31:0] counter = 0;
|
||||||
reg [ 3:0] bcm_shift = 7; // which bit of the colors are we currently exposing.
|
// which bit of the colors are we currently exposing.
|
||||||
|
reg [$clog2(BIT_DEPTH) - 1:0] bcm_shift = 7;
|
||||||
|
|
||||||
localparam integer StateInit = 0;
|
localparam StateInit = 0;
|
||||||
localparam integer StateWriteRow = 1;
|
localparam StateWriteRow = 1;
|
||||||
localparam integer StateLatchout = 2;
|
localparam StateLatchout = 2;
|
||||||
// the last data that we clock out for the row won't be exposed
|
// the last data that we clock out for the row won't be exposed
|
||||||
// in the next writerow state because we'll change addresses.
|
// in the next writerow state because we'll change addresses.
|
||||||
localparam integer StateFinishExpose = 3;
|
localparam StateFinishExpose = 3;
|
||||||
|
|
||||||
|
// this state is used to prefetch the first pixel so the cycle can work.
|
||||||
|
localparam StatePreload = 4;
|
||||||
|
|
||||||
reg [7:0] state = StateInit; // our state
|
reg [7:0] state = StateInit; // our state
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// initial begin
|
|
||||||
// state <= StateInit;
|
|
||||||
// counter <= 0;
|
|
||||||
// bcm_shift <= 7;
|
|
||||||
// end
|
|
||||||
|
|
||||||
// The FSM is a bit confusing since it's optimized for *speed*
|
// The FSM is a bit confusing since it's optimized for *speed*
|
||||||
// We can basically display the previous line of data while we write the
|
// We can basically display the previous line of data while we write the
|
||||||
// next one. So instead of having WRITEROW -> LATCH -> EXPOSE
|
// next one. So instead of having WRITEROW -> LATCH -> EXPOSE
|
||||||
|
@ -47,15 +43,21 @@ module hub75e (
|
||||||
// short!
|
// short!
|
||||||
|
|
||||||
wire should_clock, should_expose;
|
wire should_clock, should_expose;
|
||||||
assign should_clock = (counter < ROW_DEPTH * 2 + 1); // the plus 1 is for the falling edge!
|
// the plus 1 is for the falling edge!
|
||||||
assign should_expose = (counter < (16 << bcm_shift + 1)) && (bcm_shift != 7);
|
assign should_clock = (counter < (ROW_DEPTH << 2) + 1);
|
||||||
|
assign should_expose = (counter < (BCM_LEN << bcm_shift + 1)) && (bcm_shift != 7);
|
||||||
|
|
||||||
|
wire [7:0] ram_r, ram_g, ram_b;
|
||||||
|
assign ram_r = pixbuf_data[23:16];
|
||||||
|
assign ram_g = pixbuf_data[15:8];
|
||||||
|
assign ram_b = pixbuf_data[7:0];
|
||||||
|
wire [2:0] ram_rgb_slice;
|
||||||
|
assign ram_rgb_slice = {
|
||||||
|
(ram_r[bcm_shift]), (ram_g[bcm_shift]), (ram_b[bcm_shift])
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
reg [7:0] pixnum;
|
reg [7:0] pixnum;
|
||||||
assign pixbuf_addr = {bcm_shift, pixnum};
|
|
||||||
always @(*) begin
|
|
||||||
panel_rgb0 = pixbuf_data[2:0];
|
|
||||||
panel_rgb1 = pixbuf_data[5:3];
|
|
||||||
end
|
|
||||||
|
|
||||||
always_ff @(posedge clk) begin
|
always_ff @(posedge clk) begin
|
||||||
counter <= counter + 1;
|
counter <= counter + 1;
|
||||||
|
@ -65,25 +67,61 @@ module hub75e (
|
||||||
counter <= 0;
|
counter <= 0;
|
||||||
done <= 0;
|
done <= 0;
|
||||||
pixnum <= ROW_DEPTH - 1;
|
pixnum <= ROW_DEPTH - 1;
|
||||||
|
pixbuf_addr <= {1'b0, pixnum};
|
||||||
// wait for the signal to write out our lines.
|
// wait for the signal to write out our lines.
|
||||||
if (write_trig) begin
|
if (write_trig) begin
|
||||||
state <= StateWriteRow;
|
state <= StatePreload;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
StatePreload: begin
|
||||||
|
case (counter[1:0])
|
||||||
|
2'b00: begin
|
||||||
|
// wait for pix 1
|
||||||
|
pixbuf_addr <= {1'b1, pixnum};
|
||||||
|
end
|
||||||
|
2'b01: begin
|
||||||
|
// load pix 1
|
||||||
|
panel_rgb0 <= ram_rgb_slice;
|
||||||
|
end
|
||||||
|
2'b10: begin // rising edge
|
||||||
|
// store pix2
|
||||||
|
panel_rgb1 <= ram_rgb_slice;
|
||||||
|
// go to writerow
|
||||||
|
counter <= 0;
|
||||||
|
state <= StateWriteRow;
|
||||||
|
end
|
||||||
|
default: begin
|
||||||
|
counter <= 0;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
StateWriteRow: begin
|
StateWriteRow: begin
|
||||||
if (should_clock) begin
|
if (should_clock) begin
|
||||||
// we have data to clock
|
// we have data to clock
|
||||||
display_clk <= counter[0];
|
display_clk <= counter[1];
|
||||||
if (~counter[0]) begin
|
case (counter[1:0])
|
||||||
// the data from the previous cycle is now ready.
|
2'b10: begin // rising edge
|
||||||
// panel_rgb0 <= pixbuf_data[2:0];
|
// fetch pixel 1
|
||||||
// panel_rgb1 <= pixbuf_data[5:3];
|
pixbuf_addr <= {1'b0, pixnum};
|
||||||
// write it out!
|
end
|
||||||
end else begin
|
2'b11: begin // midpoint of high clk.
|
||||||
// update the bram address so it's ready at the next clock cycle.
|
// fetch pixel 2, load pixel 1
|
||||||
pixnum <= pixnum - 1;
|
pixbuf_addr <= {1'b1, pixnum};
|
||||||
end
|
panel_rgb0 <= ram_rgb_slice;
|
||||||
|
end
|
||||||
|
2'b00: begin // falling edge
|
||||||
|
// load pixel 2
|
||||||
|
panel_rgb1 <= ram_rgb_slice;
|
||||||
|
pixnum <= pixnum - 1;
|
||||||
|
end
|
||||||
|
2'b01: begin // midpoint of low clk
|
||||||
|
// decrement pixnum
|
||||||
|
end
|
||||||
|
default: begin
|
||||||
|
end
|
||||||
|
endcase
|
||||||
end
|
end
|
||||||
if (should_expose) begin
|
if (should_expose) begin
|
||||||
out_enable <= 0;
|
out_enable <= 0;
|
||||||
|
@ -122,7 +160,7 @@ module hub75e (
|
||||||
|
|
||||||
StateFinishExpose: begin
|
StateFinishExpose: begin
|
||||||
assert (bcm_shift == 0);
|
assert (bcm_shift == 0);
|
||||||
if (counter < (16 << bcm_shift)) begin
|
if (counter < (BCM_LEN << bcm_shift)) begin
|
||||||
out_enable <= 0;
|
out_enable <= 0;
|
||||||
end else begin
|
end else begin
|
||||||
out_enable <= 1;
|
out_enable <= 1;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
module lineram #(
|
module lineram #(
|
||||||
parameter DATA_WIDTH = 9,
|
parameter DATA_WIDTH = 36,
|
||||||
parameter ADDR_WIDTH = 11
|
parameter ADDR_WIDTH = 9
|
||||||
) (
|
) (
|
||||||
input [DATA_WIDTH - 1:0] din,
|
input [DATA_WIDTH - 1:0] din,
|
||||||
input [ADDR_WIDTH - 1:0] addr_w,
|
input [ADDR_WIDTH - 1:0] addr_w,
|
||||||
|
|
|
@ -36,7 +36,6 @@ module hub75e_tb;
|
||||||
hub75e dut (
|
hub75e dut (
|
||||||
.clk(clk),
|
.clk(clk),
|
||||||
.write_trig(write_trig),
|
.write_trig(write_trig),
|
||||||
.addr(addr_out),
|
|
||||||
.panel_rgb0(rgb0),
|
.panel_rgb0(rgb0),
|
||||||
.panel_rgb1(rgb1),
|
.panel_rgb1(rgb1),
|
||||||
.display_clk(display_clk),
|
.display_clk(display_clk),
|
||||||
|
@ -56,12 +55,12 @@ module hub75e_tb;
|
||||||
bram_addr_w <= 0;
|
bram_addr_w <= 0;
|
||||||
bram_write_en <= 1;
|
bram_write_en <= 1;
|
||||||
repeat (1) @(posedge clk);
|
repeat (1) @(posedge clk);
|
||||||
for (int i=0; i < 128; i=i+1) begin
|
for (int i=0; i < 512; i=i+1) begin
|
||||||
bram_data_in <= $urandom % 'hFFFFFF;
|
bram_data_in <= i + 5;
|
||||||
bram_addr_w <= i;
|
bram_addr_w <= i;
|
||||||
repeat (1) @(posedge clk);
|
repeat (1) @(posedge clk);
|
||||||
end
|
end
|
||||||
bram_write_en <= 1;
|
bram_write_en <= 0;
|
||||||
write_trig <= 1;
|
write_trig <= 1;
|
||||||
repeat (2) @(posedge clk);
|
repeat (2) @(posedge clk);
|
||||||
write_trig <= 0;
|
write_trig <= 0;
|
||||||
|
@ -71,7 +70,7 @@ module hub75e_tb;
|
||||||
$finish();
|
$finish();
|
||||||
end
|
end
|
||||||
initial begin
|
initial begin
|
||||||
repeat (100000) @(posedge clk);
|
repeat (500000) @(posedge clk);
|
||||||
$finish();
|
$finish();
|
||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
|
Loading…
Reference in a new issue