From f00eb4e1129656c9cbac1123d5cfe6520c5c2978 Mon Sep 17 00:00:00 2001 From: Hans Baier Date: Tue, 9 May 2023 15:26:27 +0700 Subject: [PATCH 1/2] AvalonMM2Wishbone: use same addressing on avalon and wishbone, leave address translation to the user --- .../avalon/avalon_mm_to_wishbone.py | 21 +++++++--------- test/test_avalon_mm.py | 24 +++++++++---------- 2 files changed, 21 insertions(+), 24 deletions(-) diff --git a/litex/soc/interconnect/avalon/avalon_mm_to_wishbone.py b/litex/soc/interconnect/avalon/avalon_mm_to_wishbone.py index 5a75157c0..29d22bf30 100644 --- a/litex/soc/interconnect/avalon/avalon_mm_to_wishbone.py +++ b/litex/soc/interconnect/avalon/avalon_mm_to_wishbone.py @@ -15,13 +15,9 @@ from litex.soc.interconnect.avalon import AvalonMMInterface # Avalon MM <--> Wishbone Bridge ------------------------------------------------------------------- class AvalonMM2Wishbone(Module): - def __init__(self, data_width=32, address_width=32, wishbone_base_address=0x0, wishbone_extend_address_bits=0, avoid_combinatorial_loop=True): - word_width = data_width // 8 - word_width_bits = log2_int(word_width) - wishbone_address_width = address_width - word_width_bits + wishbone_extend_address_bits - + def __init__(self, data_width=32, avalon_address_width=32, wishbone_address_width=32, wishbone_base_address=0x0, burst_increment=1, avoid_combinatorial_loop=True): + self.a2w_avl = avl = AvalonMMInterface (data_width=data_width, adr_width=avalon_address_width) self.a2w_wb = wb = wishbone.Interface(data_width=data_width, adr_width=wishbone_address_width, bursting=True) - self.a2w_avl = avl = AvalonMMInterface (data_width=data_width, adr_width=address_width) read_access = Signal() readdatavalid = Signal() @@ -30,7 +26,7 @@ class AvalonMM2Wishbone(Module): burst_cycle = Signal() burst_cycle_last = Signal() burst_count = Signal(len(avl.burstcount)) - burst_address = Signal(address_width) + burst_address = Signal(wishbone_address_width) burst_read = Signal() self.sync += burst_cycle_last.eq(burst_cycle) @@ -65,9 +61,9 @@ class AvalonMM2Wishbone(Module): # Avalon -> Wishbone self.comb += [ # Avalon is byte addresses, Wishbone word addressed - wb.adr.eq(avl.address[word_width_bits:] + wishbone_base_address), + wb.adr.eq(avl.address + wishbone_base_address), If(burst_cycle & burst_cycle_last, - wb.adr.eq(burst_address[word_width_bits:] + wishbone_base_address) + wb.adr.eq(burst_address + wishbone_base_address) ), wb.dat_w.eq(avl.writedata), wb.we.eq(avl.write), @@ -87,7 +83,7 @@ class AvalonMM2Wishbone(Module): If(~avl.waitrequest & (avl.burstcount > 1), burst_cycle.eq(1), NextValue(burst_count, avl.burstcount - 1), - NextValue(burst_address, avl.address + word_width), + NextValue(burst_address, avl.address + burst_increment), If(avl.write, NextState("BURST-WRITE") ), @@ -104,7 +100,7 @@ class AvalonMM2Wishbone(Module): wb.cti.eq(wishbone.CTI_BURST_END) ), If(~avl.waitrequest, - NextValue(burst_address, burst_address + word_width), + NextValue(burst_address, burst_address + burst_increment), NextValue(burst_count, burst_count - 1), ), If(burst_count == 0, @@ -122,7 +118,8 @@ class AvalonMM2Wishbone(Module): wb.cti.eq(wishbone.CTI_BURST_END) ), If(wb.ack, - NextValue(burst_address, burst_address + word_width), + avl.readdatavalid.eq(1), + NextValue(burst_address, burst_address + burst_increment), NextValue(burst_count, burst_count - 1) ), If(burst_count == 0, diff --git a/test/test_avalon_mm.py b/test/test_avalon_mm.py index 4e7dbbd81..87723a8e7 100644 --- a/test/test_avalon_mm.py +++ b/test/test_avalon_mm.py @@ -17,16 +17,16 @@ class TestAvalon2Wishbone(unittest.TestCase): def test_sram(self): def generator(dut): yield from dut.avl.bus_write(0x0000, 0x01234567) - yield from dut.avl.bus_write(0x0004, 0x89abcdef) - yield from dut.avl.bus_write(0x0008, 0xdeadbeef) - yield from dut.avl.bus_write(0x000c, 0xc0ffee00) - yield from dut.avl.bus_write(0x0010, 0x76543210) + yield from dut.avl.bus_write(0x0001, 0x89abcdef) + yield from dut.avl.bus_write(0x0002, 0xdeadbeef) + yield from dut.avl.bus_write(0x0003, 0xc0ffee00) + yield from dut.avl.bus_write(0x0004, 0x76543210) yield self.assertEqual((yield from dut.avl.bus_read(0x0000)), 0x01234567) - self.assertEqual((yield from dut.avl.bus_read(0x0004)), 0x89abcdef) - self.assertEqual((yield from dut.avl.bus_read(0x0008)), 0xdeadbeef) - self.assertEqual((yield from dut.avl.bus_read(0x000c)), 0xc0ffee00) - self.assertEqual((yield from dut.avl.bus_read(0x0010)), 0x76543210) + self.assertEqual((yield from dut.avl.bus_read(0x0001)), 0x89abcdef) + self.assertEqual((yield from dut.avl.bus_read(0x0002)), 0xdeadbeef) + self.assertEqual((yield from dut.avl.bus_read(0x0003)), 0xc0ffee00) + self.assertEqual((yield from dut.avl.bus_read(0x0004)), 0x76543210) class DUT(Module): def __init__(self): @@ -53,10 +53,10 @@ class TestAvalon2Wishbone(unittest.TestCase): yield yield self.assertEqual((yield from dut.avl.bus_read(0x0000)), 0x01234567) - self.assertEqual((yield from dut.avl.bus_read(0x0004)), 0x89abcdef) - self.assertEqual((yield from dut.avl.bus_read(0x0008)), 0xdeadbeef) - self.assertEqual((yield from dut.avl.bus_read(0x000c)), 0xc0ffee00) - self.assertEqual((yield from dut.avl.bus_read(0x0010)), 0x76543210) + self.assertEqual((yield from dut.avl.bus_read(0x0001)), 0x89abcdef) + self.assertEqual((yield from dut.avl.bus_read(0x0002)), 0xdeadbeef) + self.assertEqual((yield from dut.avl.bus_read(0x0003)), 0xc0ffee00) + self.assertEqual((yield from dut.avl.bus_read(0x0004)), 0x76543210) yield yield From 90581a2f13224edeb1dff4a1b3e06fd29bea8901 Mon Sep 17 00:00:00 2001 From: Hans Baier Date: Tue, 9 May 2023 15:28:00 +0700 Subject: [PATCH 2/2] add some low resolution video modes --- litex/soc/cores/video.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/litex/soc/cores/video.py b/litex/soc/cores/video.py index 62b867c7b..50a2f9edf 100644 --- a/litex/soc/cores/video.py +++ b/litex/soc/cores/video.py @@ -28,6 +28,28 @@ vbits = 12 # Video Timings ------------------------------------------------------------------------------------ video_timings = { + "160x100@60Hz" : { + "pix_clk" : 1.655e6, + "h_active" : 160, + "h_blanking" : 80, + "h_sync_offset" : 8, + "h_sync_width" : 32, + "v_active" : 100, + "v_blanking" : 15, + "v_sync_offset" : 1, + "v_sync_width" : 8, + }, + "320x200@60Hz" : { + "pix_clk" : 5.16e6, + "h_active" : 320, + "h_blanking" : 80, + "h_sync_offset" : 8, + "h_sync_width" : 32, + "v_active" : 200, + "v_blanking" : 15, + "v_sync_offset" : 1, + "v_sync_width" : 8, + }, "640x480@60Hz" : { "pix_clk" : 25.175e6, "h_active" : 640,