wip: 4x clock double-read bram

This commit is contained in:
saji 2024-05-09 17:31:15 -05:00
parent 2a8c70bab2
commit bcb463a8d0
6 changed files with 115 additions and 95 deletions

View file

@ -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)

View file

@ -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))

View file

@ -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

View file

@ -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;

View file

@ -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,

View file

@ -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