diff --git a/api/scaffold/__init__.py b/api/scaffold/__init__.py
index b90f88e..9df200d 100644
--- a/api/scaffold/__init__.py
+++ b/api/scaffold/__init__.py
@@ -1117,11 +1117,11 @@ def raw_transaction(self, data, read_size, trigger=None):
# Verify trigger parameter before doing anything
t_start = False
t_end = False
- if isinstance(type(trigger), int):
+ if isinstance(trigger, int):
if trigger not in range(2):
raise ValueError("Invalid trigger parameter")
t_start = trigger == 1
- elif isinstance(type(trigger), str):
+ elif isinstance(trigger, str):
t_start = "a" in trigger
t_end = "b" in trigger
else:
@@ -1605,6 +1605,106 @@ def glitch_count(self, value):
self.reg_count.set(value)
+class SWDStatus(Enum):
+ OK = 0
+ WAIT = 1
+ FAULT = 2
+ ERROR = 3
+
+
+class SWD(Module):
+ """
+ SWD peripheral of Scaffold.
+ """
+
+ __REG_STATUS_BIT_READY = 0
+
+ def __init__(self, parent):
+ """
+ :param parent: The Scaffold instance owning the SWD module.
+ """
+ super().__init__(parent, "/swd")
+ # Declare the signals
+ self.add_signals("swclk", "swd_in", "swd_out", "trigger")
+ # Declare the registers
+ self.__addr_base = base = 0x0b00
+ self.add_register("rdata", "rv", base)
+ self.add_register("wdata", "w", base + 4, reset=0x00)
+ self.add_register("status", "rv", base + 0x10)
+ self.add_register("cmd", "w", base + 0x20)
+
+ def reset(self, trigger=False):
+ """
+ Reset the debug interface. This emits a reset sequence, followed by
+ the JTAG-to-SWD select sequence and a second reset sequence. The deviceid
+ register is then read.
+ """
+ val = 0x80
+ if trigger:
+ val = val | (1 << 6)
+ self.reg_cmd.write(val)
+ self.read(0, 0)
+ return self.status()
+
+ def read(self, apndp, addr):
+ """
+ Emits a read command to a given debug register.
+
+ :param apndp: Address space of the register (0 for DP, 1 for AP).
+ :param addr: Address of the register.
+ """
+ val = 0b0000_0100 | ((apndp & 0b1) << 3) | (((addr >> 2) & 1) << 1) \
+ | ((addr >> 3) & 1)
+ self.reg_cmd.write(val)
+ return (self.status(), self.rdata())
+
+ def write(self, apndp, addr, wdata: int):
+ """
+ Emits a write command to a given debug register.
+
+ :param apndp: Address space of the register (0 for DP, 1 for AP).
+ :param addr: Address of the register.
+ :param wdata: 32-bit integer to write into the register.
+ """
+ val = 0b0000_0000 | ((apndp & 0b1) << 3) | (((addr >> 2) & 1) << 1) \
+ | ((addr >> 3) & 1)
+ wdata_bytes = wdata.to_bytes(4, "little")
+ self.reg_wdata.write(wdata_bytes)
+ self.reg_cmd.write(val)
+ return self.status()
+
+ def clear_errors(self):
+ """
+ Clear any previous errors.
+ """
+ self.write(0, 0, 0b11110)
+
+ def debug_power_up(self, retry=10):
+ """
+ Fully powers up the debug interface by writing to the CRTL/STAT register.
+ """
+ self.write(0, 0x4, (1 << 28) | (1 << 30))
+ self.clear_errors()
+ self.read(0, 0)
+ for _ in range(retry):
+ (status, ctrl_stat) = self.read(0, 0x4)
+ if ((ctrl_stat >> 29) & 0x1) == 1 and ((ctrl_stat >> 31) & 0x1) == 1:
+ return True
+ return False
+
+ def status(self):
+ """
+ Retrieve the status of the last emitted SWD transaction.
+ """
+ return SWDStatus(self.reg_status.read()[0] & 0b11)
+
+ def rdata(self):
+ """
+ Retrieve the data read by the last emitted Read transaction.
+ """
+ return int.from_bytes(self.reg_rdata.read(4), 'little')
+
+
class IOMode(Enum):
AUTO = 0
OPEN_DRAIN = 1
@@ -2098,6 +2198,7 @@ def __init__(
"0.7.2",
"0.8",
"0.9",
+ "0.10",
)
],
)
@@ -2202,6 +2303,10 @@ def connect(
self.clocks.append(clock)
self.__setattr__(f"clock{i}", clock)
+ # Declare the swd module
+ if self.version >= parse_version("0.10"):
+ self.swd = SWD(self)
+
# Create the ISO7816 module
self.iso7816 = ISO7816(self)
@@ -2238,6 +2343,8 @@ def connect(
self.add_mtxl_in(f"/pgen{i}/out")
for i in range(len(self.chains)):
self.add_mtxl_in(f"/chain{i}/trigger")
+ if self.version >= parse_version("0.10"):
+ self.add_mtxl_in("/swd/trigger")
# FPGA left matrix output signals
# Update this section when adding new modules with inputs
@@ -2259,6 +2366,8 @@ def connect(
self.add_mtxl_out(f"/chain{i}/event{j}")
for i in range(len(self.clocks)):
self.add_mtxl_out(f"/clock{i}/glitch")
+ if self.version >= parse_version("0.10"):
+ self.add_mtxl_out("/swd/swd_in")
# FPGA right matrix input signals
# Update this section when adding new modules with outpus
@@ -2290,6 +2399,10 @@ def connect(
self.add_mtxr_in(f"/chain{i}/trigger")
for i in range(len(self.clocks)):
self.add_mtxr_in(f"/clock{i}/out")
+ if self.version >= parse_version("0.10"):
+ self.add_mtxr_in("/swd/swclk")
+ self.add_mtxr_in("/swd/swd_out")
+ self.add_mtxr_in("/swd/trigger")
# FPGA right matrix output signals
self.add_mtxr_out("/io/a0")
@@ -2355,3 +2468,5 @@ def reset_config(self, init_ios=False):
i2c.reset_config()
for spi in self.spis:
spi.reset_registers()
+ if self.version >= parse_version("0.10"):
+ self.swd.reset_registers()
diff --git a/api/setup.py b/api/setup.py
index 291ed18..d77f770 100755
--- a/api/setup.py
+++ b/api/setup.py
@@ -26,13 +26,13 @@
setup(
name="donjon-scaffold",
- version="0.9.0",
+ version="0.10.0",
author="Olivier Heriveaux",
description="Python3 API for the Scaffold board",
long_description=long_description,
long_description_content_type="text/markdown",
url="https://github.com/Ledger-Donjon/scaffold",
- install_requires=["pyserial", "crcmod", "requests"],
+ install_requires=["pyserial", "crcmod", "requests", "packaging"],
packages=find_packages(),
python_requires=">=3.6",
)
diff --git a/api/tests/__init__.py b/api/tests/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/docs/requirements.txt b/docs/requirements.txt
index 22117ad..af3c4fe 100644
--- a/docs/requirements.txt
+++ b/docs/requirements.txt
@@ -2,5 +2,6 @@ sphinxcontrib-wavedrom
sphinxcontrib-spelling
matplotlib
pyserial
+packaging
crcmod
sphinx-rtd-theme>=1.3.0rc1
diff --git a/fpga-arch/bsv/Counter.v b/fpga-arch/bsv/Counter.v
new file mode 100644
index 0000000..0259385
--- /dev/null
+++ b/fpga-arch/bsv/Counter.v
@@ -0,0 +1,109 @@
+//
+// Copied without modifications from:
+// https://github.com/B-Lang-org/bsc/blob/9a97f9d037c462e42441b6af8d0000314302214f/src/Verilog/Counter.v
+//
+// Copyright (c) 2020 Bluespec, Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the
+// distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+
+`ifdef BSV_ASSIGNMENT_DELAY
+`else
+ `define BSV_ASSIGNMENT_DELAY
+`endif
+
+`ifdef BSV_POSITIVE_RESET
+ `define BSV_RESET_VALUE 1'b1
+ `define BSV_RESET_EDGE posedge
+`else
+ `define BSV_RESET_VALUE 1'b0
+ `define BSV_RESET_EDGE negedge
+`endif
+
+
+`ifdef BSV_ASYNC_RESET
+ `define BSV_ARESET_EDGE_META or `BSV_RESET_EDGE RST
+`else
+ `define BSV_ARESET_EDGE_META
+`endif
+
+
+// N -bit counter with load, set and 2 increment
+module Counter(CLK,
+ RST,
+ Q_OUT,
+ DATA_A, ADDA,
+ DATA_B, ADDB,
+ DATA_C, SETC,
+ DATA_F, SETF);
+
+ parameter width = 1;
+ parameter init = 0;
+
+ input CLK;
+ input RST;
+ input [width - 1 : 0] DATA_A;
+ input ADDA;
+ input [width - 1 : 0] DATA_B;
+ input ADDB;
+ input [width - 1 : 0] DATA_C;
+ input SETC;
+ input [width - 1 : 0] DATA_F;
+ input SETF;
+
+ output [width - 1 : 0] Q_OUT;
+
+
+
+ reg [width - 1 : 0] q_state ;
+
+ assign Q_OUT = q_state ;
+
+ always@(posedge CLK `BSV_ARESET_EDGE_META) begin
+ if (RST == `BSV_RESET_VALUE)
+ q_state <= `BSV_ASSIGNMENT_DELAY init;
+ else
+ begin
+ if ( SETF )
+ q_state <= `BSV_ASSIGNMENT_DELAY DATA_F ;
+ else
+ q_state <= `BSV_ASSIGNMENT_DELAY (SETC ? DATA_C : q_state ) + (ADDA ? DATA_A : {width {1'b0}}) + (ADDB ? DATA_B : {width {1'b0}} ) ;
+ end // else: !if(RST == `BSV_RESET_VALUE)
+ end // always@ (posedge CLK)
+
+`ifdef BSV_NO_INITIAL_BLOCKS
+`else // not BSV_NO_INITIAL_BLOCKS
+ // synopsys translate_off
+ initial begin
+ q_state = {((width + 1)/2){2'b10}} ;
+ end
+ // synopsys translate_on
+`endif // BSV_NO_INITIAL_BLOCKS
+
+endmodule
diff --git a/fpga-arch/bsv/Prescaler.bsv b/fpga-arch/bsv/Prescaler.bsv
new file mode 100644
index 0000000..3471970
--- /dev/null
+++ b/fpga-arch/bsv/Prescaler.bsv
@@ -0,0 +1,56 @@
+// This file is part of Scaffold
+//
+// Scaffold is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program. If not, see .
+//
+//
+// Copyright 2024 Ledger SAS, written by Charles Christen
+
+package Prescaler;
+
+import Counter::*;
+
+(* always_enabled *)
+interface Prescaler#(numeric type n);
+ method Action reset;
+ method Bool rising;
+ method Bool falling;
+ method Bool pre_rising;
+endinterface
+
+module mkPrescaler (Prescaler#(prescale))
+ provisos (
+ Mul#(__a, 2, prescale),
+ Add#(ctr_max, 1, prescale),
+ Log#(ctr_max, __b),
+ Add#(__b, 1, ctr_sz)
+ );
+
+ Counter#(ctr_sz) ctr <- mkCounter(fromInteger(valueof(ctr_max)));
+
+ rule count_dow (ctr.value > 0);
+ ctr.down();
+ endrule
+
+ rule reset_count (ctr.value == 0);
+ ctr.setF(fromInteger(valueof(ctr_max)));
+ endrule
+
+ method reset = ctr.setF(fromInteger(valueof(ctr_max)));
+ method rising = (ctr.value == 0);
+ method pre_rising = (ctr.value == 1);
+ method falling = (ctr.value == fromInteger(valueof(__a)));
+
+endmodule
+
+endpackage
diff --git a/fpga-arch/bsv/SWD.bsv b/fpga-arch/bsv/SWD.bsv
new file mode 100644
index 0000000..bdcb5c8
--- /dev/null
+++ b/fpga-arch/bsv/SWD.bsv
@@ -0,0 +1,197 @@
+// This file is part of Scaffold
+//
+// Scaffold is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program. If not, see .
+//
+//
+// Copyright 2024 Ledger SAS, written by Charles Christen
+
+import SWDInner::*;
+
+import GetPut::*;
+import Vector::*;
+import ClientServer::*;
+
+(* always_enabled *)
+interface ScaffoldBus;
+ // bus_in_t
+ (* prefix="" *) method Action address((* port="address" *) Bit#(16) a);
+ (* prefix="" *) method Action write_data((* port="write_data" *) Bit#(8) w);
+ (* prefix="" *) method Action write((* port="write" *) Bit#(1) b);
+ (* prefix="" *) method Action read((* port="read" *) Bit#(1) b);
+
+ // register selection
+ (* prefix="" *) method Action en_rdata((* port="en_rdata" *) Bit#(1) en);
+ (* prefix="" *) method Action en_wdata((* port="en_wdata" *) Bit#(1) en);
+ (* prefix="" *) method Action en_cmd((* port="en_cmd" *) Bit#(1) en);
+ (* prefix="" *) method Action en_status((* port="en_status" *) Bit#(1) en);
+
+ // readable register out
+ (* prefix="" *) method Bit#(8) reg_rdata;
+ (* prefix="" *) method Bit#(8) reg_status;
+endinterface
+
+interface ScaffoldSWDModule;
+ (* prefix="" *) interface ScaffoldBus bus;
+ (* prefix="" *) interface SWDControllerPins pins;
+ (* always_ready, prefix="" *) method Bit#(1) trigger;
+endinterface
+
+typedef struct {
+ Bit#(1) reset;
+ Bit#(1) trigger;
+ Bit#(2) reserved;
+ Bit#(1) apndp;
+ Bit#(1) rnw;
+ Bit#(2) addr;
+} Cmd deriving (Eq, Bits);
+
+typedef enum {
+ IDLE,
+ CMD_IN,
+ RESET,
+ RW
+} State deriving (Eq, Bits);
+
+(* synthesize *)
+module swd_module (ScaffoldSWDModule);
+ SWDController#(100) swd_controller <- mkSWDController();
+
+ Wire#(Bit#(16)) bus_address <- mkDWire(0);
+ Wire#(Bit#(8)) bus_write_data <- mkDWire(0);
+ Wire#(Bit#(1)) bus_write <- mkDWire(0);
+ Wire#(Bit#(1)) bus_read <- mkDWire(0);
+ Wire#(Bit#(1)) bus_en_rdata <- mkDWire(0);
+ Wire#(Bit#(1)) bus_en_wdata <- mkDWire(0);
+ Wire#(Bit#(1)) bus_en_cmd <- mkDWire(0);
+ Wire#(Bit#(1)) bus_en_status <- mkDWire(0);
+
+ Reg#(Bit#(8)) bus_reg_rdata <- mkRegA(0);
+ Reg#(Bit#(8)) bus_reg_status <- mkRegA(0);
+
+ PulseWire trig <- mkPulseWire();
+
+ Reg#(Vector#(4, Bit#(8))) rdata <- mkRegA(unpack(0));
+ Reg#(Status) status <- mkRegA(unpack(0));
+ Reg#(Vector#(4, Bit#(8))) wdata <- mkRegA(unpack(0));
+ Reg#(Maybe#(Cmd)) cmd <- mkRegA(tagged Invalid);
+
+ Reg#(Bool) ready <- mkRegA(False);
+ Reg#(State) state <- mkRegA(IDLE);
+
+ rule do_bus_read_rdata ((bus_read == 1) && (bus_en_rdata == 1) && (state != RW));
+ bus_reg_rdata <= rdata[0];
+ rdata <= shiftInAtN(rdata, 0);
+ endrule
+
+ rule do_bus_read_status ((bus_read == 1) && (bus_en_status == 1));
+ bus_reg_status <= {pack(state == IDLE), 5'b0, pack(status)};
+ endrule
+
+ // Only register writes if we are currently idling
+ rule do_bus_write ((bus_write == 1) && (state == IDLE));
+ if (bus_en_wdata == 1) begin
+ wdata <= shiftInAt0(wdata, bus_write_data);
+ end
+
+ if (bus_en_cmd == 1) begin
+ cmd <= tagged Valid(unpack(bus_write_data));
+ state <= CMD_IN;
+ end
+ endrule
+
+ rule do_ready;
+ ready <= swd_controller.ready;
+ endrule
+
+ rule do_cmd ((state == CMD_IN) && isValid(cmd));
+ let new_cmd = fromMaybe(?, cmd);
+
+ if (new_cmd.reset == 1) begin
+ swd_controller.reset();
+ state <= RESET;
+ end
+
+ else if (new_cmd.rnw == 1) begin
+ swd_controller.rw.request.put(
+ tagged Read { register: Register { apndp: new_cmd.apndp, addr: new_cmd.addr } }
+ );
+ state <= RW;
+ end
+
+ else begin
+ swd_controller.rw.request.put(
+ tagged Write { register: Register { apndp: new_cmd.apndp, addr: new_cmd.addr }, wdata: pack(reverse(wdata)) }
+ );
+ state <= RW;
+ end
+
+ if (new_cmd.trigger == 1) begin
+ trig.send();
+ end
+ endrule
+
+ rule do_reset (state == RESET);
+ if (ready) begin
+ swd_controller.rw.request.put(
+ tagged Read { register: Register { apndp: 0, addr: 0 } }
+ );
+ state <= RW;
+ end
+ endrule
+
+ rule do_rw (state == RW);
+ let response <- swd_controller.rw.response.get();
+ case (response) matches
+ tagged Write .w_resp: begin
+ status <= w_resp.status;
+ rdata <= unpack(0);
+ end
+ tagged Read .r_resp: begin
+ Vector#(32, Bit#(1)) resp_rdata;
+ resp_rdata = take(unpack(r_resp.rdata));
+
+ if (parity(r_resp.rdata) != 0) begin
+ status <= ERROR;
+ rdata <= unpack(0);
+ end
+ else begin
+ status <= r_resp.status;
+ rdata <= unpack(pack(resp_rdata));
+ end
+ end
+ endcase
+
+ cmd <= tagged Invalid;
+ state <= IDLE;
+ endrule
+
+ interface ScaffoldBus bus;
+ method Action address(a) = bus_address._write(a);
+ method Action write_data(w) = bus_write_data._write(w);
+ method Action write(b) = bus_write._write(b);
+ method Action read(b) = bus_read._write(b);
+
+ method Action en_rdata(en) = bus_en_rdata._write(en);
+ method Action en_wdata(en) = bus_en_wdata._write(en);
+ method Action en_cmd(en) = bus_en_cmd._write(en);
+ method Action en_status(en) = bus_en_status._write(en);
+
+ method Bit#(8) reg_rdata = bus_reg_rdata;
+ method Bit#(8) reg_status = bus_reg_status;
+ endinterface
+
+ interface SWDControllerPins pins = swd_controller.pins;
+
+ method Bit#(1) trigger = pack(trig);
+endmodule
\ No newline at end of file
diff --git a/fpga-arch/bsv/SWDInner.bsv b/fpga-arch/bsv/SWDInner.bsv
new file mode 100644
index 0000000..650c701
--- /dev/null
+++ b/fpga-arch/bsv/SWDInner.bsv
@@ -0,0 +1,453 @@
+// This file is part of Scaffold
+//
+// Scaffold is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program. If not, see .
+//
+//
+// Copyright 2024 Ledger SAS, written by Charles Christen
+
+package SWDInner;
+
+import Prescaler::*;
+
+import GetPut::*;
+import Vector::*;
+import ClientServer::*;
+
+/// An AP or DP register.
+typedef struct {
+ Bit#(1) apndp;
+ Bit#(2) addr;
+} Register deriving (Eq, Bits);
+
+/// A full 8-bits request packet.
+typedef struct {
+ Bit#(1) start;
+ Bit#(1) apndp;
+ Bit#(1) rnw;
+ Bit#(2) addr;
+ Bit#(1) parity;
+ Bit#(1) stop;
+ Bit#(1) park;
+} RequestPacket deriving (Eq, Bits);
+
+/// A transaction status.
+typedef enum {
+ OK,
+ WAIT,
+ FAULT,
+ ERROR
+} Status deriving (Eq, Bits, FShow);
+
+/// The internal state of the SWD controller.
+typedef enum {
+ IDLE,
+ PACKET,
+ P_TRN,
+ ACK,
+ A_TRN,
+ RDATA,
+ WDATA,
+ DONE,
+ RESET
+} State deriving (Eq, Bits, FShow);
+
+/// A request, for either a Read or a Write
+/// transaction.
+typedef union tagged {
+ struct {
+ Register register;
+ Bit#(32) wdata;
+ } Write;
+
+ struct {
+ Register register;
+ } Read;
+} Request deriving (Eq, Bits);
+
+/// A response, to either a Read or a Write
+/// transaction.
+typedef union tagged {
+ struct {
+ Status status;
+ } Write;
+
+ struct {
+ Status status;
+ Bit#(33) rdata;
+ } Read;
+} Response deriving (Eq, Bits);
+
+/// The peripheral-facing pins of the SWD controller,
+/// with swdio split into swd_in and swd_out.
+(* always_enabled *)
+interface SWDControllerPins;
+ (* prefix="" *) method Bit#(1) swclk;
+ (* prefix="" *) method Action swd_in((* port="swd_in" *) Bit#(1) b);
+ (* prefix="" *) method Bit#(1) swd_out;
+ (* prefix="" *) method Bool out_en;
+endinterface
+
+/// The full SWD controller interface, with endpoints for
+/// issuing Read and Write requests, and peripheral-facing
+/// pins.
+interface SWDController#(numeric type clk_divider);
+ method Action reset;
+ interface Server#(Request, Response) rw;
+ (* always_enabled *) method Bool ready;
+ (* always_enabled *) interface SWDControllerPins pins;
+endinterface
+
+module mkSWDController (SWDController#(clk_divider))
+ provisos (
+ Mul#(__a, 2, clk_divider),
+ Add#(__b, 1, clk_divider)
+ );
+
+ // When a request comes in, the packet (and data, in case of a write request)
+ // are registered, and swclk is kicked-off.
+ // We then move sequencially through the steps of the transaction, shifting out
+ // or in bits at a time, synchronously with the generated swclk falling/rising edges.
+ // When the transaction is done, the transaction status is updated and marked
+ // as Valid, triggering the release of the Get interface of the R/W server.
+ //
+ // The tricky thing, however, is to coordinate the state changes with the rising
+ // and falling edges of the SWD clock.
+ // Indeed we want to say that on the rising edge of the prescaler, meaning when it is zero
+ // but will be one in the next cycle, we want to do a certain operation, that depends
+ // on which step of the transaction we are in, i.e. which state.
+ // Thus the state must have been updated *before*, on the cycle immediately preceding
+ // the cycle itself preceding swclk == 0.
+ // This is what [prescaler.pre_rising] is for.
+
+ Prescaler#(clk_divider) prescaler <- mkPrescaler();
+
+ // Status and ACK of the current transaction.
+ Reg#(Maybe#(Status)) status <- mkRegA(tagged Invalid);
+ Reg#(Vector#(3, Bit#(1))) ack <- mkRegA(unpack(0));
+
+ // Controller pins.
+ Reg#(Bit#(1)) swd_out <- mkRegA(0);
+ Wire#(Bit#(1)) swd_in <- mkDWire(0);
+ Reg#(Bool) out_en <- mkRegA(True);
+ Reg#(Bit#(1)) swclk <- mkRegA(0);
+
+ // Inner state.
+ Reg#(State) state <- mkRegA(IDLE);
+ Reg#(Bool) rnw <- mkRegU;
+ Reg#(Vector#(8, Bit#(1))) packet <- mkRegU;
+ Reg#(Vector#(33, Bit#(1))) data <- mkRegU;
+
+ // Counter for tracking bits in the transfered packet/data.
+ Reg#(Bit#(7)) cnt <- mkRegU;
+
+ // Same-cycle signals
+ PulseWire request_in <- mkPulseWire();
+ PulseWire reset_in <- mkPulseWire();
+
+ rule do_prescaler;
+ if (request_in || reset_in) begin
+ prescaler.reset();
+ end
+ endrule
+
+ // Generate the SWD clock, whenever there is an
+ // ongoing transaction.
+ // Note that the polarity is inverted (the peripheral samples the IO line on rising edges of swclk)
+ rule do_swclk (state != IDLE);
+ if (prescaler.rising) begin
+ swclk <= 0;
+ end
+ else if (prescaler.falling) begin
+ swclk <= 1;
+ end
+ endrule
+
+ // SWDIO is treated as an input only when in
+ // the ACK or RDATA phase.
+ rule do_out_en;
+ out_en <= ((state == RESET) || (state == PACKET) || (state == WDATA));
+ endrule
+
+ // Stop idling when a request has been received.
+ rule do_idle (state == IDLE);
+ if (request_in) begin
+ state <= PACKET;
+ cnt <= 10;
+ end
+ else if (reset_in) begin
+ state <= RESET;
+ cnt <= 126;
+ end
+ else begin
+ swclk <= 1;
+ swd_out <= 1;
+ end
+ endrule
+
+ // Shift out the reset and switch sequence
+ rule do_reset (state == RESET);
+ if (prescaler.rising) begin
+ // > 50 cycles with swdio high (the specification says
+ // "more than 50", we err on the side on caution and
+ // take it to mean strictly more)
+ if (cnt > 71) begin
+ swd_out <= 1;
+ cnt <= cnt - 1;
+ end
+ // followed by the 16 bits of the JTAG-to-SWD switching
+ // sequence
+ else if (cnt > 55) begin
+ let switch_sequence = 16'hE79E;
+ swd_out <= switch_sequence[71 - cnt];
+ cnt <= cnt - 1;
+ end
+ // and finally > 50 more cycles high
+ // (bits xx to 1, because the case cnt == 0 is preempted
+ // by the pre_rising condition below)
+ else begin
+ swd_out <= 1;
+ cnt <= cnt - 1;
+ end
+ end
+
+ if (prescaler.pre_rising && (cnt == 0)) begin
+ state <= IDLE;
+ end
+ endrule
+
+ // Shift out the command packet.
+ rule do_packet (state == PACKET);
+ if (prescaler.rising) begin
+ if (cnt > 8) begin
+ swd_out <= 0;
+ cnt <= cnt - 1;
+ end
+
+ else begin
+ // On every falling edge of the generated swclk, we need to shift out a
+ // new bit of the packet
+ swd_out <= last(packet);
+ packet <= shiftInAt0(packet, 0);
+ cnt <= cnt - 1;
+ end
+ end
+
+ // If we have shifted out the last bit of the packet,
+ // and the next swclk falling edge is upcoming shortly,
+ // we need to pre-emptively transition to the next state (the TRN period)
+ // so that the corresponding rule is enabled when prescaler.rising becomes true,
+ // so that it can actually do something useful on the very same cycle
+ // where swclk is going to be low.
+ else if (prescaler.pre_rising && (cnt == 0)) begin
+ state <= P_TRN;
+ end
+
+ endrule
+
+ // Shift out a TRN bit immediately following the packet.
+ rule do_p_trn (state == P_TRN);
+ if (prescaler.rising) begin
+ swd_out <= 0;
+ end
+
+ else if (prescaler.pre_rising) begin
+ cnt <= 3;
+ state <= ACK;
+ end
+ endrule
+
+ // Shift in the received ACK, by sampling the swd_in line in the
+ // middle of the swclk cycles.
+ rule do_ack (state == ACK);
+ if (prescaler.rising) begin
+ cnt <= cnt - 1;
+ ack <= shiftInAt0(ack, swd_in);
+ end
+
+ else begin
+ // if (prescaler.falling) begin
+ // ack <= shiftInAt0(ack, swd_in);
+ // end
+
+ if (prescaler.pre_rising && (cnt == 0)) begin
+ // If we're shifting in the last ACK bit, next up will either
+ // be a TRN period or the RDATA, depending on wether the current
+ // request is a Read or a Write.
+ if (rnw) begin
+ cnt <= 33;
+ state <= RDATA;
+ end
+ else begin
+ state <= A_TRN;
+ end
+ end
+ end
+ endrule
+
+ // Shift out a TRN bit immediately following the ACK.
+ // If the ACK is OK, go through with the DATA phase,
+ // otherwise abort.
+ rule do_a_trn (state == A_TRN);
+ if (prescaler.rising) begin
+ swd_out <= 0;
+ end
+
+ else if (prescaler.pre_rising) begin
+ case (pack(ack)) matches
+ 3'b100:
+ begin
+ cnt <= 33;
+ state <= WDATA;
+ end
+ default:
+ begin
+ cnt <= 1;
+ state <= DONE;
+ end
+ endcase
+ end
+ endrule
+
+ // Shift in the 32-bits read data, plus parity bit.
+ rule do_rdata (state == RDATA);
+ if (prescaler.rising) begin
+ cnt <= cnt - 1;
+ data <= shiftInAtN(data, swd_in);
+ end
+
+ else begin
+ // if (prescaler.falling) begin
+ // data <= shiftInAtN(data, swd_in);
+ // end
+
+ if (prescaler.pre_rising && (cnt == 0)) begin
+ cnt <= 1;
+ state <= DONE;
+ end
+ end
+ endrule
+
+ // Shift out the 32-bits write data, and parity bit.
+ rule do_wdata (state == WDATA);
+ if (prescaler.rising) begin
+ swd_out <= data[0];
+ data <= shiftInAtN(data, 0);
+ cnt <= cnt - 1;
+ end
+
+ else if (prescaler.pre_rising && (cnt == 0)) begin
+ cnt <= 1;
+ state <= DONE;
+ end
+ endrule
+
+ // We're done. Update the status but keep swclk going for
+ // a full period, and then go back to IDLE.
+ rule do_done (state == DONE);
+ if (prescaler.rising) begin
+ cnt <= cnt - 1;
+
+ case (pack(ack)) matches
+ 3'b100: status <= Valid(OK);
+ 3'b010: status <= Valid(WAIT);
+ 3'b001: status <= Valid(FAULT);
+ default: status <= Valid(ERROR);
+ endcase
+ end
+
+ else if (prescaler.pre_rising && (cnt == 0)) begin
+ state <= IDLE;
+ end
+ endrule
+
+ // For debug purposes.
+ rule log;
+ $display($format("state: ") + fshow(state), ", swclk: %b, swd_out: %b, swd_in: %b, out_en: %b",
+ swclk, swd_out, swd_in, out_en);
+ endrule
+
+ // Interface methods and subinterfaces
+ //
+ method Bool ready = (state == IDLE);
+ method Action reset if (state == IDLE);
+ reset_in.send();
+ endmethod
+
+ interface Server rw;
+ interface Put request;
+ method Action put(req) if ((state == IDLE) && !isValid(status));
+ case (req) matches
+ tagged Write .w_in : begin
+ let apndp = w_in.register.apndp;
+ let addr = w_in.register.addr;
+ let p = apndp ^ 0 ^ addr[0] ^ addr[1];
+ packet <= unpack(pack(RequestPacket {
+ start: 1,
+ apndp: apndp,
+ rnw: 0,
+ addr: addr,
+ parity: p,
+ stop: 0,
+ park: 1 }));
+ data <= append(unpack(w_in.wdata), replicate(parity(w_in.wdata)));
+ rnw <= False;
+ request_in.send();
+ end
+ tagged Read .r_in : begin
+ let apndp = r_in.register.apndp;
+ let addr = r_in.register.addr;
+ let p = apndp ^ 1 ^ addr[0] ^ addr[1];
+ packet <= unpack(pack(RequestPacket {
+ start: 1,
+ apndp: apndp,
+ rnw: 1,
+ addr: addr,
+ parity: p,
+ stop: 0,
+ park: 1 }));
+ rnw <= True;
+ request_in.send();
+ end
+ endcase
+ endmethod
+ endinterface
+
+ interface Get response;
+ method ActionValue#(Response) get() if ((state == IDLE) && isValid(status));
+ let transaction_status = fromMaybe(?, status);
+ Response ret;
+ ret = rnw ? tagged Read { status: transaction_status, rdata: pack(data) } :
+ tagged Write { status: transaction_status };
+
+ // reset state
+ status <= tagged Invalid;
+ data <= unpack(0);
+ packet <= unpack(0);
+
+ return ret;
+ endmethod
+ endinterface
+ endinterface
+
+ interface SWDControllerPins pins;
+ method swclk = swclk;
+ method swd_out = swd_out;
+ method Action swd_in(b);
+ swd_in <= b;
+ endmethod
+ method out_en = out_en;
+ endinterface
+endmodule
+
+endpackage
\ No newline at end of file
diff --git a/fpga-arch/swd_module.v b/fpga-arch/swd_module.v
new file mode 100644
index 0000000..f6512cb
--- /dev/null
+++ b/fpga-arch/swd_module.v
@@ -0,0 +1,1062 @@
+//
+// Generated by Bluespec Compiler, version 2024.01-9-gc481d7f5 (build c481d7f5)
+//
+// On Mon Sep 9 13:18:32 CEST 2024
+//
+//
+// Ports:
+// Name I/O size props
+// reg_rdata O 8 reg
+// reg_status O 8 reg
+// swclk O 1 reg
+// swd_out O 1 reg
+// out_en O 1 reg
+// trigger O 1
+// CLK I 1 clock
+// RST_N I 1 reset
+// address I 16 unused
+// write_data I 8
+// write I 1
+// read I 1
+// en_rdata I 1
+// en_wdata I 1
+// en_cmd I 1
+// en_status I 1
+// swd_in I 1
+//
+// No combinational paths from inputs to outputs
+//
+//
+
+`ifdef BSV_ASSIGNMENT_DELAY
+`else
+ `define BSV_ASSIGNMENT_DELAY
+`endif
+
+`ifdef BSV_POSITIVE_RESET
+ `define BSV_RESET_VALUE 1'b1
+ `define BSV_RESET_EDGE posedge
+`else
+ `define BSV_RESET_VALUE 1'b0
+ `define BSV_RESET_EDGE negedge
+`endif
+
+module swd_module(CLK,
+ RST_N,
+
+ address,
+
+ write_data,
+
+ write,
+
+ read,
+
+ en_rdata,
+
+ en_wdata,
+
+ en_cmd,
+
+ en_status,
+
+ reg_rdata,
+
+ reg_status,
+
+ swclk,
+
+ swd_in,
+
+ swd_out,
+
+ out_en,
+
+ trigger);
+ input CLK;
+ input RST_N;
+
+ // action method bus_address
+ input [15 : 0] address;
+
+ // action method bus_write_data
+ input [7 : 0] write_data;
+
+ // action method bus_write
+ input write;
+
+ // action method bus_read
+ input read;
+
+ // action method bus_en_rdata
+ input en_rdata;
+
+ // action method bus_en_wdata
+ input en_wdata;
+
+ // action method bus_en_cmd
+ input en_cmd;
+
+ // action method bus_en_status
+ input en_status;
+
+ // value method bus_reg_rdata
+ output [7 : 0] reg_rdata;
+
+ // value method bus_reg_status
+ output [7 : 0] reg_status;
+
+ // value method pins_swclk
+ output swclk;
+
+ // action method pins_swd_in
+ input swd_in;
+
+ // value method pins_swd_out
+ output swd_out;
+
+ // value method pins_out_en
+ output out_en;
+
+ // value method trigger
+ output trigger;
+
+ // signals for module outputs
+ wire [7 : 0] reg_rdata, reg_status;
+ wire out_en, swclk, swd_out, trigger;
+
+ // inlined wires
+ wire swd_controller_request_in$whas, swd_controller_reset_in$whas;
+
+ // register bus_reg_rdata
+ reg [7 : 0] bus_reg_rdata;
+ wire [7 : 0] bus_reg_rdata$D_IN;
+ wire bus_reg_rdata$EN;
+
+ // register bus_reg_status
+ reg [7 : 0] bus_reg_status;
+ wire [7 : 0] bus_reg_status$D_IN;
+ wire bus_reg_status$EN;
+
+ // register cmd
+ reg [8 : 0] cmd;
+ wire [8 : 0] cmd$D_IN;
+ wire cmd$EN;
+
+ // register rdata
+ reg [31 : 0] rdata;
+ wire [31 : 0] rdata$D_IN;
+ wire rdata$EN;
+
+ // register ready
+ reg ready;
+ wire ready$D_IN, ready$EN;
+
+ // register state
+ reg [1 : 0] state;
+ reg [1 : 0] state$D_IN;
+ wire state$EN;
+
+ // register status
+ reg [1 : 0] status;
+ wire [1 : 0] status$D_IN;
+ wire status$EN;
+
+ // register swd_controller_ack
+ reg [2 : 0] swd_controller_ack;
+ wire [2 : 0] swd_controller_ack$D_IN;
+ wire swd_controller_ack$EN;
+
+ // register swd_controller_cnt
+ reg [6 : 0] swd_controller_cnt;
+ reg [6 : 0] swd_controller_cnt$D_IN;
+ wire swd_controller_cnt$EN;
+
+ // register swd_controller_data
+ reg [32 : 0] swd_controller_data;
+ reg [32 : 0] swd_controller_data$D_IN;
+ wire swd_controller_data$EN;
+
+ // register swd_controller_out_en
+ reg swd_controller_out_en;
+ wire swd_controller_out_en$D_IN, swd_controller_out_en$EN;
+
+ // register swd_controller_packet
+ reg [7 : 0] swd_controller_packet;
+ reg [7 : 0] swd_controller_packet$D_IN;
+ wire swd_controller_packet$EN;
+
+ // register swd_controller_rnw
+ reg swd_controller_rnw;
+ wire swd_controller_rnw$D_IN, swd_controller_rnw$EN;
+
+ // register swd_controller_state
+ reg [3 : 0] swd_controller_state;
+ reg [3 : 0] swd_controller_state$D_IN;
+ wire swd_controller_state$EN;
+
+ // register swd_controller_status
+ reg [2 : 0] swd_controller_status;
+ wire [2 : 0] swd_controller_status$D_IN;
+ wire swd_controller_status$EN;
+
+ // register swd_controller_swclk
+ reg swd_controller_swclk;
+ wire swd_controller_swclk$D_IN, swd_controller_swclk$EN;
+
+ // register swd_controller_swd_out
+ reg swd_controller_swd_out;
+ reg swd_controller_swd_out$D_IN;
+ wire swd_controller_swd_out$EN;
+
+ // register wdata
+ reg [31 : 0] wdata;
+ wire [31 : 0] wdata$D_IN;
+ wire wdata$EN;
+
+ // ports of submodule swd_controller_prescaler_ctr
+ wire [7 : 0] swd_controller_prescaler_ctr$DATA_A,
+ swd_controller_prescaler_ctr$DATA_B,
+ swd_controller_prescaler_ctr$DATA_C,
+ swd_controller_prescaler_ctr$DATA_F,
+ swd_controller_prescaler_ctr$Q_OUT;
+ wire swd_controller_prescaler_ctr$ADDA,
+ swd_controller_prescaler_ctr$ADDB,
+ swd_controller_prescaler_ctr$SETC,
+ swd_controller_prescaler_ctr$SETF;
+
+ // rule scheduling signals
+ wire WILL_FIRE_RL_do_bus_read_rdata,
+ WILL_FIRE_RL_do_bus_write,
+ WILL_FIRE_RL_do_cmd,
+ WILL_FIRE_RL_do_reset,
+ WILL_FIRE_RL_do_rw;
+
+ // inputs to muxes for submodule ports
+ reg [2 : 0] MUX_swd_controller_status$write_1__VAL_1;
+ wire [32 : 0] MUX_swd_controller_data$write_1__VAL_1,
+ MUX_swd_controller_data$write_1__VAL_2,
+ MUX_swd_controller_data$write_1__VAL_3;
+ wire [31 : 0] MUX_rdata$write_1__VAL_1, MUX_rdata$write_1__VAL_2;
+ wire [8 : 0] MUX_cmd$write_1__VAL_1;
+ wire [7 : 0] MUX_swd_controller_packet$write_1__VAL_2,
+ MUX_swd_controller_packet$write_1__VAL_3;
+ wire [6 : 0] MUX_swd_controller_cnt$write_1__VAL_2,
+ MUX_swd_controller_cnt$write_1__VAL_4,
+ MUX_swd_controller_cnt$write_1__VAL_5,
+ MUX_swd_controller_cnt$write_1__VAL_6;
+ wire [3 : 0] MUX_swd_controller_state$write_1__VAL_1,
+ MUX_swd_controller_state$write_1__VAL_3,
+ MUX_swd_controller_state$write_1__VAL_7;
+ wire [1 : 0] MUX_state$write_1__VAL_3;
+ wire MUX_cmd$write_1__SEL_1,
+ MUX_state$write_1__SEL_1,
+ MUX_swd_controller_cnt$write_1__PSEL_1,
+ MUX_swd_controller_cnt$write_1__PSEL_6,
+ MUX_swd_controller_cnt$write_1__SEL_1,
+ MUX_swd_controller_cnt$write_1__SEL_2,
+ MUX_swd_controller_cnt$write_1__SEL_3,
+ MUX_swd_controller_cnt$write_1__SEL_4,
+ MUX_swd_controller_cnt$write_1__SEL_5,
+ MUX_swd_controller_cnt$write_1__SEL_6,
+ MUX_swd_controller_data$write_1__SEL_1,
+ MUX_swd_controller_data$write_1__SEL_2,
+ MUX_swd_controller_data$write_1__SEL_3,
+ MUX_swd_controller_packet$write_1__SEL_2,
+ MUX_swd_controller_packet$write_1__SEL_3,
+ MUX_swd_controller_state$write_1__PSEL_4,
+ MUX_swd_controller_state$write_1__SEL_3,
+ MUX_swd_controller_state$write_1__SEL_4,
+ MUX_swd_controller_state$write_1__SEL_5,
+ MUX_swd_controller_state$write_1__SEL_6,
+ MUX_swd_controller_status$write_1__SEL_1,
+ MUX_swd_controller_swclk$write_1__SEL_1,
+ MUX_swd_controller_swclk$write_1__SEL_2,
+ MUX_swd_controller_swd_out$write_1__PSEL_4,
+ MUX_swd_controller_swd_out$write_1__SEL_2,
+ MUX_swd_controller_swd_out$write_1__SEL_3,
+ MUX_swd_controller_swd_out$write_1__SEL_4,
+ MUX_swd_controller_swd_out$write_1__VAL_2,
+ MUX_swd_controller_swd_out$write_1__VAL_3;
+
+ // remaining internal signals
+ wire [15 : 0] _0xE79E__q2;
+ wire [6 : 0] i__h1457, x__h15006;
+ wire [1 : 0] cmd_BITS_1_TO_0__q1;
+ wire swd_controller_cnt_2_ULE_8___d35,
+ swd_controller_data_2_BIT_0_5_XOR_swd_controll_ETC___d298,
+ x__h1438,
+ x__h20247,
+ x__h20260,
+ x__h20262,
+ x__h21446,
+ x__h21459,
+ z__h24693,
+ z__h24700,
+ z__h24707,
+ z__h24714,
+ z__h24721,
+ z__h24728,
+ z__h24735,
+ z__h24742,
+ z__h24749,
+ z__h24756,
+ z__h24763,
+ z__h24770,
+ z__h24777,
+ z__h24784,
+ z__h24791,
+ z__h24798,
+ z__h24805,
+ z__h24812,
+ z__h24819,
+ z__h24826,
+ z__h24833,
+ z__h24840,
+ z__h24847,
+ z__h24854,
+ z__h24861,
+ z__h24868,
+ z__h24875,
+ z__h24882,
+ z__h24889,
+ z__h24896,
+ z__h35341,
+ z__h35348,
+ z__h35355,
+ z__h35362,
+ z__h35369,
+ z__h35376,
+ z__h35383,
+ z__h35390,
+ z__h35397,
+ z__h35404,
+ z__h35411,
+ z__h35418,
+ z__h35425,
+ z__h35432,
+ z__h35439,
+ z__h35446,
+ z__h35453,
+ z__h35460,
+ z__h35467,
+ z__h35474,
+ z__h35481,
+ z__h35488,
+ z__h35495,
+ z__h35502,
+ z__h35509,
+ z__h35516,
+ z__h35523,
+ z__h35530,
+ z__h35537,
+ z__h35544,
+ z__h35551;
+
+ // value method bus_reg_rdata
+ assign reg_rdata = bus_reg_rdata ;
+
+ // value method bus_reg_status
+ assign reg_status = bus_reg_status ;
+
+ // value method pins_swclk
+ assign swclk = swd_controller_swclk ;
+
+ // value method pins_swd_out
+ assign swd_out = swd_controller_swd_out ;
+
+ // value method pins_out_en
+ assign out_en = swd_controller_out_en ;
+
+ // value method trigger
+ assign trigger = WILL_FIRE_RL_do_cmd && cmd[6] ;
+
+ // submodule swd_controller_prescaler_ctr
+ Counter #(.width(32'd8),
+ .init(8'd99)) swd_controller_prescaler_ctr(.CLK(CLK),
+ .RST(RST_N),
+ .DATA_A(swd_controller_prescaler_ctr$DATA_A),
+ .DATA_B(swd_controller_prescaler_ctr$DATA_B),
+ .DATA_C(swd_controller_prescaler_ctr$DATA_C),
+ .DATA_F(swd_controller_prescaler_ctr$DATA_F),
+ .ADDA(swd_controller_prescaler_ctr$ADDA),
+ .ADDB(swd_controller_prescaler_ctr$ADDB),
+ .SETC(swd_controller_prescaler_ctr$SETC),
+ .SETF(swd_controller_prescaler_ctr$SETF),
+ .Q_OUT(swd_controller_prescaler_ctr$Q_OUT));
+
+ // rule RL_do_bus_read_rdata
+ assign WILL_FIRE_RL_do_bus_read_rdata = read && en_rdata && state != 2'd3 ;
+
+ // rule RL_do_bus_write
+ assign WILL_FIRE_RL_do_bus_write = write && state == 2'd0 ;
+
+ // rule RL_do_cmd
+ assign WILL_FIRE_RL_do_cmd =
+ swd_controller_state == 4'd0 && !swd_controller_status[2] &&
+ state == 2'd1 &&
+ cmd[8] ;
+
+ // rule RL_do_reset
+ assign WILL_FIRE_RL_do_reset =
+ swd_controller_state == 4'd0 && !swd_controller_status[2] &&
+ state == 2'd2 ;
+
+ // rule RL_do_rw
+ assign WILL_FIRE_RL_do_rw =
+ swd_controller_state == 4'd0 && swd_controller_status[2] &&
+ state == 2'd3 ;
+
+ // inputs to muxes for submodule ports
+ assign MUX_cmd$write_1__SEL_1 = WILL_FIRE_RL_do_bus_write && en_cmd ;
+ assign MUX_state$write_1__SEL_1 = WILL_FIRE_RL_do_reset && ready ;
+ assign MUX_swd_controller_cnt$write_1__PSEL_1 =
+ swd_controller_state == 4'd7 || swd_controller_state == 4'd1 ||
+ swd_controller_state == 4'd8 ;
+ assign MUX_swd_controller_cnt$write_1__SEL_1 =
+ MUX_swd_controller_cnt$write_1__PSEL_1 &&
+ swd_controller_prescaler_ctr$Q_OUT == 8'd0 ;
+ assign MUX_swd_controller_cnt$write_1__SEL_2 =
+ swd_controller_state == 4'd4 &&
+ swd_controller_prescaler_ctr$Q_OUT == 8'd1 ;
+ assign MUX_swd_controller_cnt$write_1__SEL_3 =
+ swd_controller_state == 4'd2 &&
+ swd_controller_prescaler_ctr$Q_OUT == 8'd1 ;
+ assign MUX_swd_controller_cnt$write_1__SEL_4 =
+ swd_controller_state == 4'd0 &&
+ (swd_controller_request_in$whas ||
+ swd_controller_reset_in$whas) ;
+ assign MUX_swd_controller_cnt$write_1__SEL_5 =
+ swd_controller_state == 4'd3 &&
+ (swd_controller_prescaler_ctr$Q_OUT == 8'd0 ||
+ swd_controller_prescaler_ctr$Q_OUT == 8'd1 &&
+ swd_controller_cnt == 7'd0 &&
+ swd_controller_rnw) ;
+ assign MUX_swd_controller_cnt$write_1__PSEL_6 =
+ swd_controller_state == 4'd6 || swd_controller_state == 4'd5 ;
+ assign MUX_swd_controller_cnt$write_1__SEL_6 =
+ MUX_swd_controller_cnt$write_1__PSEL_6 &&
+ (swd_controller_prescaler_ctr$Q_OUT == 8'd0 ||
+ swd_controller_prescaler_ctr$Q_OUT == 8'd1 &&
+ swd_controller_cnt == 7'd0) ;
+ assign MUX_swd_controller_data$write_1__SEL_1 =
+ swd_controller_state == 4'd5 &&
+ swd_controller_prescaler_ctr$Q_OUT == 8'd0 ;
+ assign MUX_swd_controller_data$write_1__SEL_2 =
+ swd_controller_state == 4'd6 &&
+ swd_controller_prescaler_ctr$Q_OUT == 8'd0 ;
+ assign MUX_swd_controller_data$write_1__SEL_3 =
+ WILL_FIRE_RL_do_cmd && !cmd[7] && !cmd[2] ;
+ assign MUX_swd_controller_packet$write_1__SEL_2 =
+ WILL_FIRE_RL_do_cmd && !cmd[7] ;
+ assign MUX_swd_controller_packet$write_1__SEL_3 =
+ swd_controller_state == 4'd1 &&
+ swd_controller_prescaler_ctr$Q_OUT == 8'd0 &&
+ swd_controller_cnt_2_ULE_8___d35 ;
+ assign MUX_swd_controller_state$write_1__SEL_3 =
+ swd_controller_state == 4'd3 &&
+ swd_controller_prescaler_ctr$Q_OUT == 8'd1 &&
+ swd_controller_cnt == 7'd0 ;
+ assign MUX_swd_controller_state$write_1__PSEL_4 =
+ swd_controller_state == 4'd7 || swd_controller_state == 4'd8 ;
+ assign MUX_swd_controller_state$write_1__SEL_4 =
+ MUX_swd_controller_state$write_1__PSEL_4 &&
+ swd_controller_prescaler_ctr$Q_OUT == 8'd1 &&
+ swd_controller_cnt == 7'd0 ;
+ assign MUX_swd_controller_state$write_1__SEL_5 =
+ swd_controller_state == 4'd1 &&
+ swd_controller_prescaler_ctr$Q_OUT == 8'd1 &&
+ swd_controller_cnt == 7'd0 ;
+ assign MUX_swd_controller_state$write_1__SEL_6 =
+ MUX_swd_controller_cnt$write_1__PSEL_6 &&
+ swd_controller_prescaler_ctr$Q_OUT == 8'd1 &&
+ swd_controller_cnt == 7'd0 ;
+ assign MUX_swd_controller_status$write_1__SEL_1 =
+ swd_controller_state == 4'd7 &&
+ swd_controller_prescaler_ctr$Q_OUT == 8'd0 ;
+ assign MUX_swd_controller_swclk$write_1__SEL_1 =
+ swd_controller_state != 4'd0 &&
+ (swd_controller_prescaler_ctr$Q_OUT == 8'd0 ||
+ swd_controller_prescaler_ctr$Q_OUT == 8'd50) ;
+ assign MUX_swd_controller_swclk$write_1__SEL_2 =
+ swd_controller_state == 4'd0 &&
+ !swd_controller_request_in$whas &&
+ !swd_controller_reset_in$whas ;
+ assign MUX_swd_controller_swd_out$write_1__SEL_2 =
+ swd_controller_state == 4'd8 &&
+ swd_controller_prescaler_ctr$Q_OUT == 8'd0 ;
+ assign MUX_swd_controller_swd_out$write_1__SEL_3 =
+ swd_controller_state == 4'd1 &&
+ swd_controller_prescaler_ctr$Q_OUT == 8'd0 ;
+ assign MUX_swd_controller_swd_out$write_1__PSEL_4 =
+ swd_controller_state == 4'd4 || swd_controller_state == 4'd2 ;
+ assign MUX_swd_controller_swd_out$write_1__SEL_4 =
+ MUX_swd_controller_swd_out$write_1__PSEL_4 &&
+ swd_controller_prescaler_ctr$Q_OUT == 8'd0 ;
+ assign MUX_cmd$write_1__VAL_1 = { 1'd1, write_data } ;
+ assign MUX_rdata$write_1__VAL_1 = { 8'd0, rdata[31:8] } ;
+ assign MUX_rdata$write_1__VAL_2 =
+ swd_controller_rnw ?
+ (swd_controller_data_2_BIT_0_5_XOR_swd_controll_ETC___d298 ?
+ 32'd0 :
+ swd_controller_data[31:0]) :
+ 32'd0 ;
+ assign MUX_state$write_1__VAL_3 = cmd[7] ? 2'd2 : 2'd3 ;
+ assign MUX_swd_controller_cnt$write_1__VAL_2 =
+ (swd_controller_ack == 3'b100) ? 7'd33 : 7'd1 ;
+ assign MUX_swd_controller_cnt$write_1__VAL_4 =
+ swd_controller_request_in$whas ? 7'd10 : 7'd126 ;
+ assign MUX_swd_controller_cnt$write_1__VAL_5 =
+ (swd_controller_prescaler_ctr$Q_OUT == 8'd0) ?
+ x__h15006 :
+ 7'd33 ;
+ assign MUX_swd_controller_cnt$write_1__VAL_6 =
+ (swd_controller_prescaler_ctr$Q_OUT == 8'd0) ? x__h15006 : 7'd1 ;
+ assign MUX_swd_controller_data$write_1__VAL_1 =
+ { swd_in, swd_controller_data[32:1] } ;
+ assign MUX_swd_controller_data$write_1__VAL_2 =
+ { 1'd0, swd_controller_data[32:1] } ;
+ assign MUX_swd_controller_data$write_1__VAL_3 =
+ { z__h24896 ^ wdata[7],
+ wdata[7:0],
+ wdata[15:8],
+ wdata[23:16],
+ wdata[31:24] } ;
+ assign MUX_swd_controller_packet$write_1__VAL_2 =
+ { 1'd1, cmd[3:0], cmd[2] ? x__h20247 : x__h21446, 2'd1 } ;
+ assign MUX_swd_controller_packet$write_1__VAL_3 =
+ { swd_controller_packet[6:0], 1'd0 } ;
+ assign MUX_swd_controller_state$write_1__VAL_1 =
+ (swd_controller_ack == 3'b100) ? 4'd6 : 4'd7 ;
+ assign MUX_swd_controller_state$write_1__VAL_3 =
+ swd_controller_rnw ? 4'd5 : 4'd4 ;
+ assign MUX_swd_controller_state$write_1__VAL_7 =
+ swd_controller_request_in$whas ? 4'd1 : 4'd8 ;
+ always@(swd_controller_ack)
+ begin
+ case (swd_controller_ack)
+ 3'b001: MUX_swd_controller_status$write_1__VAL_1 = 3'd6;
+ 3'b010: MUX_swd_controller_status$write_1__VAL_1 = 3'd5;
+ 3'b100: MUX_swd_controller_status$write_1__VAL_1 = swd_controller_ack;
+ default: MUX_swd_controller_status$write_1__VAL_1 = 3'd7;
+ endcase
+ end
+ assign MUX_swd_controller_swd_out$write_1__VAL_2 =
+ swd_controller_cnt > 7'd71 || swd_controller_cnt <= 7'd55 ||
+ x__h1438 ;
+ assign MUX_swd_controller_swd_out$write_1__VAL_3 =
+ swd_controller_cnt_2_ULE_8___d35 && swd_controller_packet[7] ;
+
+ // inlined wires
+ assign swd_controller_request_in$whas =
+ WILL_FIRE_RL_do_reset && ready ||
+ WILL_FIRE_RL_do_cmd && !cmd[7] ;
+ assign swd_controller_reset_in$whas = WILL_FIRE_RL_do_cmd && cmd[7] ;
+
+ // register bus_reg_rdata
+ assign bus_reg_rdata$D_IN = rdata[7:0] ;
+ assign bus_reg_rdata$EN = WILL_FIRE_RL_do_bus_read_rdata ;
+
+ // register bus_reg_status
+ assign bus_reg_status$D_IN = { state == 2'd0, 5'b0, status } ;
+ assign bus_reg_status$EN = read && en_status ;
+
+ // register cmd
+ assign cmd$D_IN = MUX_cmd$write_1__SEL_1 ? MUX_cmd$write_1__VAL_1 : 9'd170 ;
+ assign cmd$EN = WILL_FIRE_RL_do_bus_write && en_cmd || WILL_FIRE_RL_do_rw ;
+
+ // register rdata
+ assign rdata$D_IN =
+ WILL_FIRE_RL_do_bus_read_rdata ?
+ MUX_rdata$write_1__VAL_1 :
+ MUX_rdata$write_1__VAL_2 ;
+ assign rdata$EN = WILL_FIRE_RL_do_bus_read_rdata || WILL_FIRE_RL_do_rw ;
+
+ // register ready
+ assign ready$D_IN = swd_controller_state == 4'd0 ;
+ assign ready$EN = 1'd1 ;
+
+ // register state
+ always@(MUX_state$write_1__SEL_1 or
+ MUX_cmd$write_1__SEL_1 or
+ WILL_FIRE_RL_do_cmd or
+ MUX_state$write_1__VAL_3 or WILL_FIRE_RL_do_rw)
+ begin
+ case (1'b1) // synopsys parallel_case
+ MUX_state$write_1__SEL_1: state$D_IN = 2'd3;
+ MUX_cmd$write_1__SEL_1: state$D_IN = 2'd1;
+ WILL_FIRE_RL_do_cmd: state$D_IN = MUX_state$write_1__VAL_3;
+ WILL_FIRE_RL_do_rw: state$D_IN = 2'd0;
+ default: state$D_IN = 2'b10 /* unspecified value */ ;
+ endcase
+ end
+ assign state$EN =
+ WILL_FIRE_RL_do_reset && ready ||
+ WILL_FIRE_RL_do_bus_write && en_cmd ||
+ WILL_FIRE_RL_do_cmd ||
+ WILL_FIRE_RL_do_rw ;
+
+ // register status
+ assign status$D_IN =
+ swd_controller_rnw ?
+ (swd_controller_data_2_BIT_0_5_XOR_swd_controll_ETC___d298 ?
+ 2'd3 :
+ swd_controller_status[1:0]) :
+ swd_controller_status[1:0] ;
+ assign status$EN = WILL_FIRE_RL_do_rw ;
+
+ // register swd_controller_ack
+ assign swd_controller_ack$D_IN = { swd_controller_ack[1:0], swd_in } ;
+ assign swd_controller_ack$EN =
+ swd_controller_state == 4'd3 &&
+ swd_controller_prescaler_ctr$Q_OUT == 8'd0 ;
+
+ // register swd_controller_cnt
+ always@(MUX_swd_controller_cnt$write_1__SEL_1 or
+ x__h15006 or
+ MUX_swd_controller_cnt$write_1__SEL_2 or
+ MUX_swd_controller_cnt$write_1__VAL_2 or
+ MUX_swd_controller_cnt$write_1__SEL_3 or
+ MUX_swd_controller_cnt$write_1__SEL_4 or
+ MUX_swd_controller_cnt$write_1__VAL_4 or
+ MUX_swd_controller_cnt$write_1__SEL_5 or
+ MUX_swd_controller_cnt$write_1__VAL_5 or
+ MUX_swd_controller_cnt$write_1__SEL_6 or
+ MUX_swd_controller_cnt$write_1__VAL_6)
+ begin
+ case (1'b1) // synopsys parallel_case
+ MUX_swd_controller_cnt$write_1__SEL_1:
+ swd_controller_cnt$D_IN = x__h15006;
+ MUX_swd_controller_cnt$write_1__SEL_2:
+ swd_controller_cnt$D_IN = MUX_swd_controller_cnt$write_1__VAL_2;
+ MUX_swd_controller_cnt$write_1__SEL_3: swd_controller_cnt$D_IN = 7'd3;
+ MUX_swd_controller_cnt$write_1__SEL_4:
+ swd_controller_cnt$D_IN = MUX_swd_controller_cnt$write_1__VAL_4;
+ MUX_swd_controller_cnt$write_1__SEL_5:
+ swd_controller_cnt$D_IN = MUX_swd_controller_cnt$write_1__VAL_5;
+ MUX_swd_controller_cnt$write_1__SEL_6:
+ swd_controller_cnt$D_IN = MUX_swd_controller_cnt$write_1__VAL_6;
+ default: swd_controller_cnt$D_IN = 7'b0101010 /* unspecified value */ ;
+ endcase
+ end
+ assign swd_controller_cnt$EN =
+ (swd_controller_state == 4'd7 || swd_controller_state == 4'd1 ||
+ swd_controller_state == 4'd8) &&
+ swd_controller_prescaler_ctr$Q_OUT == 8'd0 ||
+ swd_controller_state == 4'd4 &&
+ swd_controller_prescaler_ctr$Q_OUT == 8'd1 ||
+ swd_controller_state == 4'd2 &&
+ swd_controller_prescaler_ctr$Q_OUT == 8'd1 ||
+ swd_controller_state == 4'd0 &&
+ (swd_controller_request_in$whas ||
+ swd_controller_reset_in$whas) ||
+ MUX_swd_controller_cnt$write_1__SEL_5 ||
+ (swd_controller_state == 4'd6 || swd_controller_state == 4'd5) &&
+ (swd_controller_prescaler_ctr$Q_OUT == 8'd0 ||
+ swd_controller_prescaler_ctr$Q_OUT == 8'd1 &&
+ swd_controller_cnt == 7'd0) ;
+
+ // register swd_controller_data
+ always@(MUX_swd_controller_data$write_1__SEL_1 or
+ MUX_swd_controller_data$write_1__VAL_1 or
+ MUX_swd_controller_data$write_1__SEL_2 or
+ MUX_swd_controller_data$write_1__VAL_2 or
+ MUX_swd_controller_data$write_1__SEL_3 or
+ MUX_swd_controller_data$write_1__VAL_3 or WILL_FIRE_RL_do_rw)
+ begin
+ case (1'b1) // synopsys parallel_case
+ MUX_swd_controller_data$write_1__SEL_1:
+ swd_controller_data$D_IN = MUX_swd_controller_data$write_1__VAL_1;
+ MUX_swd_controller_data$write_1__SEL_2:
+ swd_controller_data$D_IN = MUX_swd_controller_data$write_1__VAL_2;
+ MUX_swd_controller_data$write_1__SEL_3:
+ swd_controller_data$D_IN = MUX_swd_controller_data$write_1__VAL_3;
+ WILL_FIRE_RL_do_rw: swd_controller_data$D_IN = 33'd0;
+ default: swd_controller_data$D_IN =
+ 33'h0AAAAAAAA /* unspecified value */ ;
+ endcase
+ end
+ assign swd_controller_data$EN =
+ swd_controller_state == 4'd5 &&
+ swd_controller_prescaler_ctr$Q_OUT == 8'd0 ||
+ swd_controller_state == 4'd6 &&
+ swd_controller_prescaler_ctr$Q_OUT == 8'd0 ||
+ WILL_FIRE_RL_do_cmd && !cmd[7] && !cmd[2] ||
+ WILL_FIRE_RL_do_rw ;
+
+ // register swd_controller_out_en
+ assign swd_controller_out_en$D_IN =
+ swd_controller_state == 4'd8 || swd_controller_state == 4'd1 ||
+ swd_controller_state == 4'd6 ;
+ assign swd_controller_out_en$EN = 1'd1 ;
+
+ // register swd_controller_packet
+ always@(MUX_state$write_1__SEL_1 or
+ MUX_swd_controller_packet$write_1__SEL_2 or
+ MUX_swd_controller_packet$write_1__VAL_2 or
+ MUX_swd_controller_packet$write_1__SEL_3 or
+ MUX_swd_controller_packet$write_1__VAL_3 or WILL_FIRE_RL_do_rw)
+ begin
+ case (1'b1) // synopsys parallel_case
+ MUX_state$write_1__SEL_1: swd_controller_packet$D_IN = 8'd165;
+ MUX_swd_controller_packet$write_1__SEL_2:
+ swd_controller_packet$D_IN =
+ MUX_swd_controller_packet$write_1__VAL_2;
+ MUX_swd_controller_packet$write_1__SEL_3:
+ swd_controller_packet$D_IN =
+ MUX_swd_controller_packet$write_1__VAL_3;
+ WILL_FIRE_RL_do_rw: swd_controller_packet$D_IN = 8'd0;
+ default: swd_controller_packet$D_IN =
+ 8'b10101010 /* unspecified value */ ;
+ endcase
+ end
+ assign swd_controller_packet$EN =
+ WILL_FIRE_RL_do_reset && ready ||
+ WILL_FIRE_RL_do_cmd && !cmd[7] ||
+ swd_controller_state == 4'd1 &&
+ swd_controller_prescaler_ctr$Q_OUT == 8'd0 &&
+ swd_controller_cnt_2_ULE_8___d35 ||
+ WILL_FIRE_RL_do_rw ;
+
+ // register swd_controller_rnw
+ assign swd_controller_rnw$D_IN = MUX_state$write_1__SEL_1 || cmd[2] ;
+ assign swd_controller_rnw$EN = swd_controller_request_in$whas ;
+
+ // register swd_controller_state
+ always@(MUX_swd_controller_cnt$write_1__SEL_2 or
+ MUX_swd_controller_state$write_1__VAL_1 or
+ MUX_swd_controller_cnt$write_1__SEL_3 or
+ MUX_swd_controller_state$write_1__SEL_3 or
+ MUX_swd_controller_state$write_1__VAL_3 or
+ MUX_swd_controller_state$write_1__SEL_4 or
+ MUX_swd_controller_state$write_1__SEL_5 or
+ MUX_swd_controller_state$write_1__SEL_6 or
+ MUX_swd_controller_cnt$write_1__SEL_4 or
+ MUX_swd_controller_state$write_1__VAL_7)
+ begin
+ case (1'b1) // synopsys parallel_case
+ MUX_swd_controller_cnt$write_1__SEL_2:
+ swd_controller_state$D_IN = MUX_swd_controller_state$write_1__VAL_1;
+ MUX_swd_controller_cnt$write_1__SEL_3: swd_controller_state$D_IN = 4'd3;
+ MUX_swd_controller_state$write_1__SEL_3:
+ swd_controller_state$D_IN = MUX_swd_controller_state$write_1__VAL_3;
+ MUX_swd_controller_state$write_1__SEL_4:
+ swd_controller_state$D_IN = 4'd0;
+ MUX_swd_controller_state$write_1__SEL_5:
+ swd_controller_state$D_IN = 4'd2;
+ MUX_swd_controller_state$write_1__SEL_6:
+ swd_controller_state$D_IN = 4'd7;
+ MUX_swd_controller_cnt$write_1__SEL_4:
+ swd_controller_state$D_IN = MUX_swd_controller_state$write_1__VAL_7;
+ default: swd_controller_state$D_IN = 4'b1010 /* unspecified value */ ;
+ endcase
+ end
+ assign swd_controller_state$EN =
+ swd_controller_state == 4'd4 &&
+ swd_controller_prescaler_ctr$Q_OUT == 8'd1 ||
+ swd_controller_state == 4'd2 &&
+ swd_controller_prescaler_ctr$Q_OUT == 8'd1 ||
+ swd_controller_state == 4'd3 &&
+ swd_controller_prescaler_ctr$Q_OUT == 8'd1 &&
+ swd_controller_cnt == 7'd0 ||
+ (swd_controller_state == 4'd7 || swd_controller_state == 4'd8) &&
+ swd_controller_prescaler_ctr$Q_OUT == 8'd1 &&
+ swd_controller_cnt == 7'd0 ||
+ swd_controller_state == 4'd1 &&
+ swd_controller_prescaler_ctr$Q_OUT == 8'd1 &&
+ swd_controller_cnt == 7'd0 ||
+ (swd_controller_state == 4'd6 || swd_controller_state == 4'd5) &&
+ swd_controller_prescaler_ctr$Q_OUT == 8'd1 &&
+ swd_controller_cnt == 7'd0 ||
+ swd_controller_state == 4'd0 &&
+ (swd_controller_request_in$whas ||
+ swd_controller_reset_in$whas) ;
+
+ // register swd_controller_status
+ assign swd_controller_status$D_IN =
+ MUX_swd_controller_status$write_1__SEL_1 ?
+ MUX_swd_controller_status$write_1__VAL_1 :
+ 3'd2 ;
+ assign swd_controller_status$EN =
+ swd_controller_state == 4'd7 &&
+ swd_controller_prescaler_ctr$Q_OUT == 8'd0 ||
+ WILL_FIRE_RL_do_rw ;
+
+ // register swd_controller_swclk
+ assign swd_controller_swclk$D_IN =
+ !MUX_swd_controller_swclk$write_1__SEL_1 ||
+ swd_controller_prescaler_ctr$Q_OUT != 8'd0 ;
+ assign swd_controller_swclk$EN =
+ swd_controller_state != 4'd0 &&
+ (swd_controller_prescaler_ctr$Q_OUT == 8'd0 ||
+ swd_controller_prescaler_ctr$Q_OUT == 8'd50) ||
+ swd_controller_state == 4'd0 &&
+ !swd_controller_request_in$whas &&
+ !swd_controller_reset_in$whas ;
+
+ // register swd_controller_swd_out
+ always@(MUX_swd_controller_data$write_1__SEL_2 or
+ swd_controller_data or
+ MUX_swd_controller_swd_out$write_1__SEL_2 or
+ MUX_swd_controller_swd_out$write_1__VAL_2 or
+ MUX_swd_controller_swd_out$write_1__SEL_3 or
+ MUX_swd_controller_swd_out$write_1__VAL_3 or
+ MUX_swd_controller_swd_out$write_1__SEL_4 or
+ MUX_swd_controller_swclk$write_1__SEL_2)
+ begin
+ case (1'b1) // synopsys parallel_case
+ MUX_swd_controller_data$write_1__SEL_2:
+ swd_controller_swd_out$D_IN = swd_controller_data[0];
+ MUX_swd_controller_swd_out$write_1__SEL_2:
+ swd_controller_swd_out$D_IN =
+ MUX_swd_controller_swd_out$write_1__VAL_2;
+ MUX_swd_controller_swd_out$write_1__SEL_3:
+ swd_controller_swd_out$D_IN =
+ MUX_swd_controller_swd_out$write_1__VAL_3;
+ MUX_swd_controller_swd_out$write_1__SEL_4:
+ swd_controller_swd_out$D_IN = 1'd0;
+ MUX_swd_controller_swclk$write_1__SEL_2:
+ swd_controller_swd_out$D_IN = 1'd1;
+ default: swd_controller_swd_out$D_IN = 1'b0 /* unspecified value */ ;
+ endcase
+ end
+ assign swd_controller_swd_out$EN =
+ swd_controller_state == 4'd6 &&
+ swd_controller_prescaler_ctr$Q_OUT == 8'd0 ||
+ swd_controller_state == 4'd8 &&
+ swd_controller_prescaler_ctr$Q_OUT == 8'd0 ||
+ swd_controller_state == 4'd1 &&
+ swd_controller_prescaler_ctr$Q_OUT == 8'd0 ||
+ (swd_controller_state == 4'd4 || swd_controller_state == 4'd2) &&
+ swd_controller_prescaler_ctr$Q_OUT == 8'd0 ||
+ swd_controller_state == 4'd0 &&
+ !swd_controller_request_in$whas &&
+ !swd_controller_reset_in$whas ;
+
+ // register wdata
+ assign wdata$D_IN = { wdata[23:0], write_data } ;
+ assign wdata$EN = WILL_FIRE_RL_do_bus_write && en_wdata ;
+
+ // submodule swd_controller_prescaler_ctr
+ assign swd_controller_prescaler_ctr$DATA_A = 8'h0 ;
+ assign swd_controller_prescaler_ctr$DATA_B = 8'd255 ;
+ assign swd_controller_prescaler_ctr$DATA_C = 8'h0 ;
+ assign swd_controller_prescaler_ctr$DATA_F = 8'd99 ;
+ assign swd_controller_prescaler_ctr$ADDA = 1'b0 ;
+ assign swd_controller_prescaler_ctr$ADDB =
+ swd_controller_prescaler_ctr$Q_OUT != 8'd0 ;
+ assign swd_controller_prescaler_ctr$SETC = 1'b0 ;
+ assign swd_controller_prescaler_ctr$SETF =
+ swd_controller_request_in$whas || swd_controller_reset_in$whas ||
+ swd_controller_prescaler_ctr$Q_OUT == 8'd0 ;
+
+ // remaining internal signals
+ assign _0xE79E__q2 = 16'hE79E ;
+ assign cmd_BITS_1_TO_0__q1 = cmd[1:0] ;
+ assign i__h1457 = 7'd71 - swd_controller_cnt ;
+ assign swd_controller_cnt_2_ULE_8___d35 = swd_controller_cnt <= 7'd8 ;
+ assign swd_controller_data_2_BIT_0_5_XOR_swd_controll_ETC___d298 =
+ z__h35551 ^ swd_controller_data[32] ;
+ assign x__h1438 = _0xE79E__q2[i__h1457[3:0]] ;
+ assign x__h15006 = swd_controller_cnt - 7'd1 ;
+ assign x__h20247 = x__h20260 ^ cmd_BITS_1_TO_0__q1[1] ;
+ assign x__h20260 = x__h20262 ^ cmd_BITS_1_TO_0__q1[0] ;
+ assign x__h20262 = ~cmd[3] ;
+ assign x__h21446 = x__h21459 ^ cmd_BITS_1_TO_0__q1[1] ;
+ assign x__h21459 = cmd[3] ^ cmd_BITS_1_TO_0__q1[0] ;
+ assign z__h24693 = wdata[24] ^ wdata[25] ;
+ assign z__h24700 = z__h24693 ^ wdata[26] ;
+ assign z__h24707 = z__h24700 ^ wdata[27] ;
+ assign z__h24714 = z__h24707 ^ wdata[28] ;
+ assign z__h24721 = z__h24714 ^ wdata[29] ;
+ assign z__h24728 = z__h24721 ^ wdata[30] ;
+ assign z__h24735 = z__h24728 ^ wdata[31] ;
+ assign z__h24742 = z__h24735 ^ wdata[16] ;
+ assign z__h24749 = z__h24742 ^ wdata[17] ;
+ assign z__h24756 = z__h24749 ^ wdata[18] ;
+ assign z__h24763 = z__h24756 ^ wdata[19] ;
+ assign z__h24770 = z__h24763 ^ wdata[20] ;
+ assign z__h24777 = z__h24770 ^ wdata[21] ;
+ assign z__h24784 = z__h24777 ^ wdata[22] ;
+ assign z__h24791 = z__h24784 ^ wdata[23] ;
+ assign z__h24798 = z__h24791 ^ wdata[8] ;
+ assign z__h24805 = z__h24798 ^ wdata[9] ;
+ assign z__h24812 = z__h24805 ^ wdata[10] ;
+ assign z__h24819 = z__h24812 ^ wdata[11] ;
+ assign z__h24826 = z__h24819 ^ wdata[12] ;
+ assign z__h24833 = z__h24826 ^ wdata[13] ;
+ assign z__h24840 = z__h24833 ^ wdata[14] ;
+ assign z__h24847 = z__h24840 ^ wdata[15] ;
+ assign z__h24854 = z__h24847 ^ wdata[0] ;
+ assign z__h24861 = z__h24854 ^ wdata[1] ;
+ assign z__h24868 = z__h24861 ^ wdata[2] ;
+ assign z__h24875 = z__h24868 ^ wdata[3] ;
+ assign z__h24882 = z__h24875 ^ wdata[4] ;
+ assign z__h24889 = z__h24882 ^ wdata[5] ;
+ assign z__h24896 = z__h24889 ^ wdata[6] ;
+ assign z__h35341 = swd_controller_data[0] ^ swd_controller_data[1] ;
+ assign z__h35348 = z__h35341 ^ swd_controller_data[2] ;
+ assign z__h35355 = z__h35348 ^ swd_controller_data[3] ;
+ assign z__h35362 = z__h35355 ^ swd_controller_data[4] ;
+ assign z__h35369 = z__h35362 ^ swd_controller_data[5] ;
+ assign z__h35376 = z__h35369 ^ swd_controller_data[6] ;
+ assign z__h35383 = z__h35376 ^ swd_controller_data[7] ;
+ assign z__h35390 = z__h35383 ^ swd_controller_data[8] ;
+ assign z__h35397 = z__h35390 ^ swd_controller_data[9] ;
+ assign z__h35404 = z__h35397 ^ swd_controller_data[10] ;
+ assign z__h35411 = z__h35404 ^ swd_controller_data[11] ;
+ assign z__h35418 = z__h35411 ^ swd_controller_data[12] ;
+ assign z__h35425 = z__h35418 ^ swd_controller_data[13] ;
+ assign z__h35432 = z__h35425 ^ swd_controller_data[14] ;
+ assign z__h35439 = z__h35432 ^ swd_controller_data[15] ;
+ assign z__h35446 = z__h35439 ^ swd_controller_data[16] ;
+ assign z__h35453 = z__h35446 ^ swd_controller_data[17] ;
+ assign z__h35460 = z__h35453 ^ swd_controller_data[18] ;
+ assign z__h35467 = z__h35460 ^ swd_controller_data[19] ;
+ assign z__h35474 = z__h35467 ^ swd_controller_data[20] ;
+ assign z__h35481 = z__h35474 ^ swd_controller_data[21] ;
+ assign z__h35488 = z__h35481 ^ swd_controller_data[22] ;
+ assign z__h35495 = z__h35488 ^ swd_controller_data[23] ;
+ assign z__h35502 = z__h35495 ^ swd_controller_data[24] ;
+ assign z__h35509 = z__h35502 ^ swd_controller_data[25] ;
+ assign z__h35516 = z__h35509 ^ swd_controller_data[26] ;
+ assign z__h35523 = z__h35516 ^ swd_controller_data[27] ;
+ assign z__h35530 = z__h35523 ^ swd_controller_data[28] ;
+ assign z__h35537 = z__h35530 ^ swd_controller_data[29] ;
+ assign z__h35544 = z__h35537 ^ swd_controller_data[30] ;
+ assign z__h35551 = z__h35544 ^ swd_controller_data[31] ;
+
+ // handling of inlined registers
+
+ always@(posedge CLK)
+ begin
+ if (swd_controller_cnt$EN)
+ swd_controller_cnt <= `BSV_ASSIGNMENT_DELAY swd_controller_cnt$D_IN;
+ if (swd_controller_data$EN)
+ swd_controller_data <= `BSV_ASSIGNMENT_DELAY swd_controller_data$D_IN;
+ if (swd_controller_packet$EN)
+ swd_controller_packet <= `BSV_ASSIGNMENT_DELAY
+ swd_controller_packet$D_IN;
+ if (swd_controller_rnw$EN)
+ swd_controller_rnw <= `BSV_ASSIGNMENT_DELAY swd_controller_rnw$D_IN;
+ end
+
+ always@(posedge CLK or `BSV_RESET_EDGE RST_N)
+ if (RST_N == `BSV_RESET_VALUE)
+ begin
+ bus_reg_rdata <= `BSV_ASSIGNMENT_DELAY 8'd0;
+ bus_reg_status <= `BSV_ASSIGNMENT_DELAY 8'd0;
+ cmd <= `BSV_ASSIGNMENT_DELAY 9'd170;
+ rdata <= `BSV_ASSIGNMENT_DELAY 32'd0;
+ ready <= `BSV_ASSIGNMENT_DELAY 1'd0;
+ state <= `BSV_ASSIGNMENT_DELAY 2'd0;
+ status <= `BSV_ASSIGNMENT_DELAY 2'd0;
+ swd_controller_ack <= `BSV_ASSIGNMENT_DELAY 3'd0;
+ swd_controller_out_en <= `BSV_ASSIGNMENT_DELAY 1'd1;
+ swd_controller_state <= `BSV_ASSIGNMENT_DELAY 4'd0;
+ swd_controller_status <= `BSV_ASSIGNMENT_DELAY 3'd2;
+ swd_controller_swclk <= `BSV_ASSIGNMENT_DELAY 1'd0;
+ swd_controller_swd_out <= `BSV_ASSIGNMENT_DELAY 1'd0;
+ wdata <= `BSV_ASSIGNMENT_DELAY 32'd0;
+ end
+ else
+ begin
+ if (bus_reg_rdata$EN)
+ bus_reg_rdata <= `BSV_ASSIGNMENT_DELAY bus_reg_rdata$D_IN;
+ if (bus_reg_status$EN)
+ bus_reg_status <= `BSV_ASSIGNMENT_DELAY bus_reg_status$D_IN;
+ if (cmd$EN) cmd <= `BSV_ASSIGNMENT_DELAY cmd$D_IN;
+ if (rdata$EN) rdata <= `BSV_ASSIGNMENT_DELAY rdata$D_IN;
+ if (ready$EN) ready <= `BSV_ASSIGNMENT_DELAY ready$D_IN;
+ if (state$EN) state <= `BSV_ASSIGNMENT_DELAY state$D_IN;
+ if (status$EN) status <= `BSV_ASSIGNMENT_DELAY status$D_IN;
+ if (swd_controller_ack$EN)
+ swd_controller_ack <= `BSV_ASSIGNMENT_DELAY swd_controller_ack$D_IN;
+ if (swd_controller_out_en$EN)
+ swd_controller_out_en <= `BSV_ASSIGNMENT_DELAY
+ swd_controller_out_en$D_IN;
+ if (swd_controller_state$EN)
+ swd_controller_state <= `BSV_ASSIGNMENT_DELAY
+ swd_controller_state$D_IN;
+ if (swd_controller_status$EN)
+ swd_controller_status <= `BSV_ASSIGNMENT_DELAY
+ swd_controller_status$D_IN;
+ if (swd_controller_swclk$EN)
+ swd_controller_swclk <= `BSV_ASSIGNMENT_DELAY
+ swd_controller_swclk$D_IN;
+ if (swd_controller_swd_out$EN)
+ swd_controller_swd_out <= `BSV_ASSIGNMENT_DELAY
+ swd_controller_swd_out$D_IN;
+ if (wdata$EN) wdata <= `BSV_ASSIGNMENT_DELAY wdata$D_IN;
+ end
+
+ // synopsys translate_off
+ `ifdef BSV_NO_INITIAL_BLOCKS
+ `else // not BSV_NO_INITIAL_BLOCKS
+ initial
+ begin
+ bus_reg_rdata = 8'hAA;
+ bus_reg_status = 8'hAA;
+ cmd = 9'h0AA;
+ rdata = 32'hAAAAAAAA;
+ ready = 1'h0;
+ state = 2'h2;
+ status = 2'h2;
+ swd_controller_ack = 3'h2;
+ swd_controller_cnt = 7'h2A;
+ swd_controller_data = 33'h0AAAAAAAA;
+ swd_controller_out_en = 1'h0;
+ swd_controller_packet = 8'hAA;
+ swd_controller_rnw = 1'h0;
+ swd_controller_state = 4'hA;
+ swd_controller_status = 3'h2;
+ swd_controller_swclk = 1'h0;
+ swd_controller_swd_out = 1'h0;
+ wdata = 32'hAAAAAAAA;
+ end
+ `endif // BSV_NO_INITIAL_BLOCKS
+ // synopsys translate_on
+
+ // handling of system tasks
+
+ // synopsys translate_off
+ always@(negedge CLK)
+ begin
+ #0;
+ if (RST_N != `BSV_RESET_VALUE) $write("state: ");
+ if (RST_N != `BSV_RESET_VALUE)
+ if (swd_controller_state == 4'd0) $write("IDLE");
+ if (RST_N != `BSV_RESET_VALUE)
+ if (swd_controller_state == 4'd1) $write("PACKET");
+ if (RST_N != `BSV_RESET_VALUE)
+ if (swd_controller_state == 4'd2) $write("P_TRN");
+ if (RST_N != `BSV_RESET_VALUE)
+ if (swd_controller_state == 4'd3) $write("ACK");
+ if (RST_N != `BSV_RESET_VALUE)
+ if (swd_controller_state == 4'd4) $write("A_TRN");
+ if (RST_N != `BSV_RESET_VALUE)
+ if (swd_controller_state == 4'd5) $write("RDATA");
+ if (RST_N != `BSV_RESET_VALUE)
+ if (swd_controller_state == 4'd6) $write("WDATA");
+ if (RST_N != `BSV_RESET_VALUE)
+ if (swd_controller_state == 4'd7) $write("DONE");
+ if (RST_N != `BSV_RESET_VALUE)
+ if (swd_controller_state != 4'd0 && swd_controller_state != 4'd1 &&
+ swd_controller_state != 4'd2 &&
+ swd_controller_state != 4'd3 &&
+ swd_controller_state != 4'd4 &&
+ swd_controller_state != 4'd5 &&
+ swd_controller_state != 4'd6 &&
+ swd_controller_state != 4'd7)
+ $write("RESET");
+ if (RST_N != `BSV_RESET_VALUE)
+ $write(", swclk: %b, swd_out: %b, swd_in: %b, out_en: %b",
+ swd_controller_swclk,
+ swd_controller_swd_out,
+ swd_in,
+ swd_controller_out_en,
+ "\n");
+ end
+ // synopsys translate_on
+endmodule // swd_module
+
diff --git a/fpga-arch/system.vhd b/fpga-arch/system.vhd
index 4047acb..0d851fd 100644
--- a/fpga-arch/system.vhd
+++ b/fpga-arch/system.vhd
@@ -109,6 +109,31 @@ architecture behavior of system is
-- | | | | | | | | | |
-- +----+ +------+ +----------+ +------+ +-----+
+ -- Declaration of Verilog module as a component
+ COMPONENT swd_module
+ PORT
+ (
+ CLK : IN STD_LOGIC;
+ RST_N : IN STD_LOGIC;
+ address : IN STD_LOGIC_VECTOR(15 DOWNTO 0);
+ write_data : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
+ write : IN STD_LOGIC;
+ read : IN STD_LOGIC;
+ en_rdata : IN STD_LOGIC;
+ en_wdata : IN STD_LOGIC;
+ en_cmd : IN STD_LOGIC;
+ en_status : IN STD_LOGIC;
+ reg_rdata : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
+ reg_status : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
+ swclk : OUT STD_LOGIC;
+ swd_in : IN STD_LOGIC;
+ swd_out : OUT STD_LOGIC;
+ out_en : OUT STD_LOGIC;
+ trigger : OUT STD_LOGIC
+ );
+ END COMPONENT;
+
+
-- Function for easier address decoding.
function addr_en (
bus_in: bus_in_t;
@@ -150,6 +175,7 @@ architecture behavior of system is
+ 1 -- ISO7816 trigger
+ 1 -- I2C trigger
+ 1 -- SPI trigger
+ + 1 -- SWD trigger
+ pulse_gen_count -- Pulse generator outputs
+ chain_count; -- Chain trigger
signal mtxl_in: std_logic_vector(mtxl_in_count-1 downto 0);
@@ -161,7 +187,8 @@ architecture behavior of system is
+ 2 -- I2C
+ 1 -- SPI
+ 2 -- SPI slave
- + 1; -- Clock
+ + 1 -- Clock
+ + 1; -- SWD
signal mtxl_out: std_logic_vector(mtxl_out_count-1 downto 0);
signal mtxl_out_uart_rx: std_logic_vector(uart_count-1 downto 0);
signal mtxl_out_pulse_gen_start: std_logic_vector(pulse_gen_count-1 downto 0);
@@ -172,6 +199,7 @@ architecture behavior of system is
signal mtxl_out_spi_slave_sck: std_logic;
signal mtxl_out_spi_slave_ss: std_logic;
signal mtxl_out_clock_glitch_start: std_logic;
+ signal mtxl_out_swd_swdio: std_logic;
signal mtxl_out_chain_events:
std_logic_vector_array_t(chain_count-1 downto 0)(chain_size-1 downto 0);
@@ -184,7 +212,8 @@ architecture behavior of system is
+ 3 -- I2C module
+ 4 -- SPI module
+ 1 -- SPI slave module
- + 1; -- Clock
+ + 1 -- Clock
+ + 3; -- SWD
signal mtxr_in: tristate_array_t(mtxr_in_count-1 downto 0);
signal mtxr_in_uart_tx: std_logic_vector(uart_count-1 downto 0);
signal mtxr_in_uart_trigger: std_logic_vector(uart_count-1 downto 0);
@@ -203,6 +232,10 @@ architecture behavior of system is
signal mtxr_in_spi_trigger: std_logic;
signal mtxr_in_spi_slave_miso: std_logic;
signal mtxr_in_clock_out: std_logic;
+ signal mtxr_in_swd_swdio: std_logic;
+ signal mtxr_in_swd_swdio_en: std_logic;
+ signal mtxr_in_swd_swclk: std_logic;
+ signal mtxr_in_swd_trigger: std_logic;
signal mtxr_in_chain_out: std_logic_vector(chain_count-1 downto 0);
-- Output signals of the output matrix
@@ -258,6 +291,10 @@ architecture behavior of system is
constant addr_clock_divisor_a: address_t := x"0a01";
constant addr_clock_divisor_b: address_t := x"0a02";
constant addr_clock_count: address_t := x"0a03";
+ constant addr_swd_rdata: address_t := x"0b00";
+ constant addr_swd_wdata: address_t := x"0b04";
+ constant addr_swd_status: address_t := x"0b10";
+ constant addr_swd_cmd: address_t := x"0b20";
constant addr_io_value_base: address_t := x"e000";
constant addr_io_config_base: address_t := x"e001";
constant addr_mtxl_base: address_t := x"f000";
@@ -307,6 +344,10 @@ architecture behavior of system is
signal en_clock_divisor_a: std_logic;
signal en_clock_divisor_b: std_logic;
signal en_clock_count: std_logic;
+ signal en_swd_rdata: std_logic;
+ signal en_swd_wdata: std_logic;
+ signal en_swd_cmd: std_logic;
+ signal en_swd_status: std_logic;
signal en_io_value: std_logic_vector(io_count-1 downto 0);
signal en_io_config: std_logic_vector(io_count-1 downto 0);
signal en_mtxl_sel: std_logic_vector(mtxl_out_count-1 downto 0);
@@ -323,7 +364,8 @@ architecture behavior of system is
+ 1 -- Power control
+ 2 -- ISO7816 status and data
+ 4 -- I2C
- + 2; -- SPI
+ + 2 -- SPI
+ + 2; -- SWD
signal reg_io_value: std_logic_vector_array_t(io_count-1 downto 0)
(7 downto 0);
signal reg_version_data: byte_t;
@@ -335,6 +377,7 @@ architecture behavior of system is
signal reg_power_control: byte_t;
signal reg_i2c_status, reg_i2c_data, reg_i2c_size_h, reg_i2c_size_l: byte_t;
signal reg_spi_status, reg_spi_data: byte_t;
+ signal reg_swd_status, reg_swd_rdata: byte_t;
-- State of the LEDs (when override is disabled in LEDs module).
signal leds: std_logic_vector(23 downto 0);
@@ -434,6 +477,10 @@ begin
en_clock_divisor_a <= addr_en(bus_in, addr_clock_divisor_a);
en_clock_divisor_b <= addr_en(bus_in, addr_clock_divisor_b);
en_clock_count <= addr_en(bus_in, addr_clock_count);
+ en_swd_rdata <= addr_en(bus_in, addr_swd_rdata);
+ en_swd_wdata <= addr_en(bus_in, addr_swd_wdata);
+ en_swd_cmd <= addr_en(bus_in, addr_swd_cmd);
+ en_swd_status <= addr_en(bus_in, addr_swd_status);
en_io_value <= addr_en_loop(bus_in, addr_io_value_base, x"0010", io_count);
en_io_config <=
addr_en_loop(bus_in, addr_io_config_base, x"0010", io_count);
@@ -461,7 +508,9 @@ begin
reg_iso7816_status &
reg_iso7816_data &
reg_spi_status &
- reg_spi_data,
+ reg_spi_data &
+ reg_swd_rdata &
+ reg_swd_status,
enables =>
en_io_value &
en_pulse_gen_status &
@@ -476,7 +525,9 @@ begin
en_iso7816_status &
en_iso7816_data &
en_spi_status &
- en_spi_data,
+ en_spi_data &
+ en_swd_rdata &
+ en_swd_status,
value => bus_out.read_data );
-- I/O modules
@@ -520,7 +571,7 @@ begin
-- Version module
e_version_module: entity work.version_module
- generic map (version => "scaffold-0.9")
+ generic map (version => "scaffold-0.10")
port map (
clock => clock,
reset_n => reset_n,
@@ -694,6 +745,27 @@ begin
output => mtxr_in_clock_out,
glitch_start => mtxl_out_clock_glitch_start );
+ -- SWD module
+ c_swd: component swd_module
+ port map (
+ CLK => clock,
+ RST_N => reset_n,
+ address => bus_in.address,
+ write_data => bus_in.write_data,
+ write => bus_in.write,
+ read => bus_in.read,
+ en_rdata => en_swd_rdata,
+ en_wdata => en_swd_wdata,
+ en_cmd => en_swd_cmd,
+ en_status => en_swd_status,
+ reg_rdata => reg_swd_rdata,
+ reg_status => reg_swd_status,
+ swclk => mtxr_in_swd_swclk,
+ swd_in => mtxl_out_swd_swdio,
+ swd_out => mtxr_in_swd_swdio,
+ out_en => mtxr_in_swd_swdio_en,
+ trigger => mtxr_in_swd_trigger );
+
-- Left matrix module
e_left_matrix_module: entity work.left_matrix_module
generic map (
@@ -733,6 +805,8 @@ begin
end loop;
mtxl_out_clock_glitch_start <= mtxl_out(i);
i := i + 1;
+ mtxl_out_swd_swdio <= mtxl_out(i);
+ i := i + 1;
assert i = mtxl_out_count;
end process;
@@ -740,6 +814,7 @@ begin
-- mtxr signals are feedback outputs of modules.
-- Warning: signals order is inversed regarding Python API code.
mtxl_in <=
+ mtxr_in_swd_trigger &
mtxr_in_chain_out &
mtxr_in_pulse_gen_out &
mtxr_in_spi_trigger &
@@ -783,7 +858,12 @@ begin
mtxr_in_spi_trigger,
mtxr_in_spi_slave_miso,
mtxr_in_chain_out,
- mtxr_in_clock_out )
+ mtxr_in_clock_out,
+ mtxr_in_swd_swclk,
+ mtxr_in_swd_swdio,
+ mtxr_in_swd_swdio_en,
+ mtxr_in_swd_trigger
+ )
variable i: integer;
begin
mtxr_in(0) <= "00"; -- Z
@@ -831,6 +911,11 @@ begin
-- Clock module
mtxr_in(i) <= "1" & mtxr_in_clock_out;
i := i + 1;
+ -- SWD module
+ mtxr_in(i) <= "1" & mtxr_in_swd_swclk;
+ mtxr_in(i+1) <= mtxr_in_swd_swdio_en & mtxr_in_swd_swdio;
+ mtxr_in(i+2) <= "1" & mtxr_in_swd_trigger;
+ i := i + 3;
-- If you add other signals, please dont forget to update the sensivity
-- list for simulation support.
assert i = mtxr_in_count;