diff --git a/verif/cocotb/adp_cocotb_driver.py b/verif/cocotb/adp_cocotb_driver.py index ce99d546954e191e4a5848b4dcd5d60e5563e6a5..423a19e29f2903374c121ec4a8278396d34524ab 100644 --- a/verif/cocotb/adp_cocotb_driver.py +++ b/verif/cocotb/adp_cocotb_driver.py @@ -12,63 +12,119 @@ import os # Class for ADP AXI Stream Interface class ADP(): def __init__(self, dut, send, recieve): - self.dut = dut + self.dut = dut + self.log = self.dut.log # Send Stream to NanoSoC - self.send = send + self.send = send # Send Recieve to NanoSoC - self.recieve = recieve + self.recieve = recieve self.monitor_mode = False - # Read Block from ADP - @cocotb.coroutine - async def read(self, length): - read_str = "" - for i in range(length): - data = await self.recieve.read() - read_str += chr(data[0]) - return read_str + # Logging Function + def info(self, str): + self.log.info(str.strip()) + # Reads Byte from ADP AXI Stream + @cocotb.coroutine + async def read8(self): + # Read Byte from ADP AXI Stream + data = await self.recieve.read() + return chr(data[0]) + + # Writes Byte from ADP AXI Stream + @cocotb.coroutine + async def write8(self, val): + await self.send.write([val]) + # Read ADP String @cocotb.coroutine async def readLine(self): read_str = "" while True: - # Read Bytes from ADP AXI Stream - data = await self.recieve.read() - curr_char = chr(data[0]) + curr_char = await self.read8() # Combine Bytes into String - if (curr_char != '\n'): + if (curr_char not in ['\n',"\r"]): read_str += curr_char else: - return read_str.strip() + # Return on Newline/Carrige Return + return read_str - # Write ADP String - @cocotb.coroutine - async def write8(self, val): - await self.send.write([val]) # Write ADP String @cocotb.coroutine - async def write(self, string): - for i in string: - await self.send.write([ord(i)]) - await self.send.write([0x0a]) - read_str = await self.readLine() - self.dut.log.info(read_str) - + async def write_bytes(self, buf): + for i in buf: + await self.write8(ord(i)) + # Append two additional newlines for reliability + await self.write8(0x0a) + # Enter Monitor Mode @cocotb.coroutine async def monitorModeEnter(self): self.dut.log.info("Entering ADP Monitor Mode") - await self.send.write([0x1b]) + await self.write8(0x1b) + # await self.write8(0x0a) + await self.wait_string("]", debug=True) self.monitor_mode = True # Exit Monitor Mode @cocotb.coroutine async def monitorModeExit(self): self.dut.log.info("Exiting ADP Monitor Mode") - await self.send.write([0x04]) + await self.write8(0x04) self.monitor_mode = False + + # Read Block from ADP + @cocotb.coroutine + async def wait_response(self, debug=False): + read_str = "" + while read_str in ["","]]"]: + read_str = await self.readLine() + if debug == True: + self.info(read_str) + return read_str + + # Read Block from ADP + @cocotb.coroutine + async def wait_string(self, string, debug=False): + read_str = "" + while read_str != string: + read_str = await self.readLine() + if debug == True: + self.info(read_str) + return read_str + + # Set ADP Address Pointer + @cocotb.coroutine + async def set_address(self, address): + address_string = f"A {hex(address)}" + await self.write_bytes(address_string) + resp = await self.wait_response() + # Ensure Address Read Back Matches that of what was sent + assert resp.split()[1] == hex(address) + self.info(f"ADP Address Pointer Set: {hex(address)}") + + # Get ADP Current Address Pointer + @cocotb.coroutine + async def get_address(self): + address_string = f"A" + await self.write_bytes(address_string) + resp = await self.wait_response(debug = True) + # Ensure Address Read Back Matches that of what was sent + assert resp.split()[0] == "]A" + self.info(f"ADP Address Pointer: {resp.split()[1]}") + return int(resp.split()[1],16) + + # Set Address to Read From + @cocotb.coroutine + async def read_bytes(self, reads): + read_string = f"R {str(int(reads))}\n" + self.info(read_string) + await self.write(read_string) + for i in range(reads): + resp = await self.wait_response() + self.info(resp) + self.info(f"Performing {hex(reads)} Reads") # Write Hex File into System @cocotb.coroutine @@ -77,12 +133,13 @@ class ADP(): file_stats = os.stat(file_name) file_len_in_bytes = round(file_stats.st_size/3) bytecount_hex=hex(file_len_in_bytes) - await self.write(f'A {str(hex(address))}\n') - await self.write(f'U {str(bytecount_hex)}\n') + await self.set_address(address) + await self.write_bytes(f'U {str(bytecount_hex)}\n') count = file_len_in_bytes with open(file_name, mode='r') as file: for i in range(count) : b=file.readline() await self.write8(int(str.strip(b),16)) await self.write8(0x0a) - self.dut.log.info("Finished Send Code") \ No newline at end of file + self.info(await self.wait_response()) + self.info("Finished Send Code") \ No newline at end of file diff --git a/verif/cocotb/test_adp.py b/verif/cocotb/test_adp.py index edfdd6909cdcaacf14cf78985f90c59a5652074a..43bcbe34ad70d6287a78cc763bdb2018abad6be2 100644 --- a/verif/cocotb/test_adp.py +++ b/verif/cocotb/test_adp.py @@ -24,11 +24,12 @@ CLK_PERIOD = (10, "ns") # Control ADP AXI Stream bus and create ADP Driver Object def setup_adp(dut): - adp_sender = AxiStreamSource(AxiStreamBus.from_prefix(dut, "txd8"), dut.XTAL1, dut.NRST, reset_active_level=False) - adp_reciever = AxiStreamSink(AxiStreamBus.from_prefix(dut, "rxd8"), dut.XTAL1, dut.NRST, reset_active_level=False) logging.getLogger("cocotb.nanosoc_tb.rxd8").setLevel(logging.WARNING) logging.getLogger("cocotb.nanosoc_tb.txd8").setLevel(logging.WARNING) + adp_sender = AxiStreamSource(AxiStreamBus.from_prefix(dut, "txd8"), dut.XTAL1, dut.NRST, reset_active_level=False) + adp_reciever = AxiStreamSink(AxiStreamBus.from_prefix(dut, "rxd8"), dut.XTAL1, dut.NRST, reset_active_level=False) driver = ADP(dut, adp_sender, adp_reciever) + driver.write8(0x00) return driver # Start Clocks and Reset System @@ -55,7 +56,6 @@ async def wait_bootcode(dut, driver): # Wait for bootcode to finish @cocotb.coroutine async def wait_hello(dut, driver): - test_passed = "** TEST PASSED **" while True: read_str = await driver.readLine() dut.log.info(read_str) @@ -89,10 +89,26 @@ async def test_adp_write(dut): await wait_bootcode(dut, adp_driver) dut.log.info("Bootcode Finished") await adp_driver.monitorModeEnter() - await adp_driver.write('A 0x10000000\n') - await adp_driver.write('R 4\n') - for i in range(4): - dut.log.info(await adp_driver.readLine()) + test_str = "\n\r]" + read_str = await adp_driver.read8() + while read_str != test_str: + read_str += await adp_driver.read8() + dut.log.info(repr(read_str)) + + # dut.log.info(await adp_driver.wait_response()) + # dut.log.info("Setting Address") + # await adp_driver.set_address(0x10000000) + # await adp_driver.get_address() + # await adp_driver.set_address(0x10000000) + # await adp_driver.read_bytes(4) + # adp_driver.info(await adp_driver.wait_response()) + # await adp_driver.write_bytes('A 0x10000000\n') + # adp_driver.info(await adp_driver.wait_response()) + # await adp_driver.write_bytes('A\n') + # adp_driver.info(await adp_driver.wait_response()) + # await adp_driver.write('R 4\n') + # for i in range(2): + # dut.log.info(await adp_driver.readLine()) dut.log.info("ADP Write Test Complete") # Basic Software Load Test @@ -106,10 +122,17 @@ async def test_adp_hello(dut): dut.log.info("Bootcode Finished") await adp_driver.monitorModeEnter() await adp_driver.writeHex(hello_hex, 0x20000000) + adp_driver.info("Writen the hex") + await adp_driver.monitorModeEnter() + await adp_driver.get_address() + await adp_driver.set_address(0x20000000) + await adp_driver.read_bytes("R 4") await adp_driver.monitorModeExit() dut.NRST.value = 0 await ClockCycles(dut.XTAL1, 2) dut.NRST.value = 1 + for i in range(4): + adp_driver.info(adp_driver.readLine()) await wait_hello(dut, adp_driver) dut.log.info("ADP Write Test Complete") diff --git a/verif/trace/verilog/nanosoc_ft1248x1_to_axi_streamio_v1_0.v b/verif/trace/verilog/nanosoc_ft1248x1_to_axi_streamio_v1_0.v index 983594d6858b7ce986651131cf45d53cb40e15f4..e37d38478d75a59a3d067d5320befd85e04c40a9 100644 --- a/verif/trace/verilog/nanosoc_ft1248x1_to_axi_streamio_v1_0.v +++ b/verif/trace/verilog/nanosoc_ft1248x1_to_axi_streamio_v1_0.v @@ -174,13 +174,18 @@ assign txd_tdata8_o = txstream[7:0]; // 8-bit write port with extra top-bit used as valid qualifer reg [8:0] rxstream; +reg rxstream_valid; always @(posedge aclk or negedge aresetn) - if (!aresetn) + if (!aresetn) begin rxstream <= 9'b000000000; - else if (!rxstream[8] & rxd_tvalid_i) // if empty can accept valid RX stream data + rxstream_valid <= 1'b0; + end else if (!rxstream[8] & rxd_tvalid_i) begin// if empty can accept valid RX stream data + rxstream_valid <= 1'b1; rxstream[8:0] <= {1'b1,rxd_tdata8_i}; - else if (rxstream[8] & ft_clk_rising & ft_cmd_rxd & (ft_state==5'b01110)) // hold until final shift completion + end else if (rxstream[8] & ft_clk_rising & ft_cmd_rxd & (ft_state==5'b01110)) begin// hold until final shift completion rxstream[8] <= 1'b0; + rxstream_valid <= 1'b0; + end assign rxd_tready_o = !rxstream[8]; // ready until loaded @@ -192,7 +197,7 @@ always @(posedge aclk or negedge aresetn) txd_sr <= 8'b00000000; else if (ft_ssn) // sync reset txd_sr <= 8'b00000000; - else if (ft_clk_falling & ft_cmd_rxd & rxd_tvalid_i & (ft_state == 5'b00111)) + else if (ft_clk_falling & ft_cmd_rxd & rxstream_valid & (ft_state == 5'b00111)) txd_sr <= rxstream[7:0]; else if (ft_clk_rising & ft_cmd_rxd & (ft_state[4:3] == 2'b01)) //serial shift txd_sr <= {1'b0,txd_sr[7:1]};