Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Swd #20

Open
wants to merge 25 commits into
base: master
Choose a base branch
from
Open

Swd #20

Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
b25a8c0
Fix clock polarity and register reset
cchr-ledger Jul 17, 2024
d78596d
Use version 10.0
cchr-ledger Jul 17, 2024
7aceffa
Add licensing information
cchr-ledger Jul 22, 2024
bb9e504
Remove useless comments
cchr-ledger Jul 22, 2024
68065a1
Add API call for debug power up
cchr-ledger Jul 29, 2024
01806ed
Better comments
cchr-ledger Jul 30, 2024
d459f3e
Fix API bugs
cchr-ledger Aug 1, 2024
f1e40b8
Take review comments into account for the API
cchr-ledger Aug 27, 2024
80ed060
Remove the type() on trigger
mmouchous-ledger Aug 30, 2024
259162f
Bump pip package version
mmouchous-ledger Aug 30, 2024
dbeb8a6
Fixing #23
mmouchous-ledger Aug 30, 2024
e51bb11
Add packaging library to requirements.txt (for documentation)
mmouchous-ledger Aug 30, 2024
2f8a405
Merge branch '21-trigger-parameter-for-i2c-transaction-is-not-well-te…
mmouchous-ledger Aug 30, 2024
4038ced
Bump version 10.0
mmouchous-ledger Aug 30, 2024
afc5707
Use to_bytes for splitting wdata, as per review recommendation
cchr-ledger Sep 3, 2024
44031a4
Remove always_ready when it is already implied by the use of always_e…
cchr-ledger Sep 3, 2024
fd50d00
Fix typo, as per review comment
cchr-ledger Sep 3, 2024
b2a7b0f
Take review comments into account
cchr-ledger Sep 3, 2024
a63e0d4
Prefer mkRegA to mkReg
cchr-ledger Sep 3, 2024
407f8c1
Update swd_module.v
cchr-ledger Sep 3, 2024
d4a316e
Reset prescaler when requests go in, and simplify out_en expression
cchr-ledger Sep 4, 2024
0c999f2
Add trigger output
cchr-ledger Sep 5, 2024
7ad9d2b
Satisfy linter
cchr-ledger Sep 5, 2024
b71173f
Take review comments into account
cchr-ledger Sep 9, 2024
f61de50
Introduce separate CMD_IN state
cchr-ledger Sep 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 114 additions & 0 deletions api/scaffold/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1605,6 +1605,107 @@ 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")
# 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):
"""
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.
"""
self.reg_cmd.write(0x80)
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 & 0b11)
self.reg_wdata.write(wdata & 0xff)
cchr-ledger marked this conversation as resolved.
Show resolved Hide resolved
self.reg_wdata.write((wdata >> 8) & 0xff)
self.reg_wdata.write((wdata >> 16) & 0xff)
self.reg_wdata.write((wdata >> 24) & 0xff)
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(int.from_bytes(self.reg_status.read(), 'little') & 0b11)
cchr-ledger marked this conversation as resolved.
Show resolved Hide resolved

def rdata(self):
"""
Retrieve the data read by the last emitted Read transaction.
"""
return int.from_bytes(self.reg_rdata.read(), 'little') << 0 | \
int.from_bytes(self.reg_rdata.read(), 'little') << 8 | \
int.from_bytes(self.reg_rdata.read(), 'little') << 16 | \
int.from_bytes(self.reg_rdata.read(), 'little') << 24
cchr-ledger marked this conversation as resolved.
Show resolved Hide resolved


class IOMode(Enum):
AUTO = 0
OPEN_DRAIN = 1
Expand Down Expand Up @@ -2098,6 +2199,7 @@ def __init__(
"0.7.2",
"0.8",
"0.9",
"0.10",
)
],
)
Expand Down Expand Up @@ -2202,6 +2304,11 @@ 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 = SWD(self)
self.__setattr__("swd", swd)
cchr-ledger marked this conversation as resolved.
Show resolved Hide resolved

# Create the ISO7816 module
self.iso7816 = ISO7816(self)

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -2290,6 +2399,9 @@ 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")

# FPGA right matrix output signals
self.add_mtxr_out("/io/a0")
Expand Down Expand Up @@ -2355,3 +2467,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()
Empty file added api/tests/__init__.py
Empty file.
59 changes: 59 additions & 0 deletions api/tests/test_swd.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# 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 <https://www.gnu.org/licenses/>.
#
#
# Copyright 2024 Ledger SAS

# from scaffold import Scaffold, Pull


# def test_dut_connection_ok():
# scaffold = Scaffold("/dev/ttyUSB3")
# swd = scaffold.swd
# swd.swclk >> scaffold.d0
# swd.swd_out >> scaffold.d1
# swd.swd_in << scaffold.d1
# scaffold.d0.pull = Pull.UP
# scaffold.d1.pull = Pull.UP
#
# status = swd.reset()
# print(f"status after: {status}")


# def test_read():
# scaffold = Scaffold("/dev/ttyUSB3")
# swd = scaffold.swd
# swd.swclk >> scaffold.d0
# swd.swd_out >> scaffold.d1
# swd.swd_in << scaffold.d1
# scaffold.d0.pull = Pull.UP
# scaffold.d1.pull = Pull.UP
#
# (status, rdata) = swd.read(0, 0)
# print(f"status after: {status}")
# print(f"rdata: {hex(rdata)}")


# def test_write():
# scaffold = Scaffold("/dev/ttyUSB3")
# swd = scaffold.swd
# swd.swclk >> scaffold.d0
# swd.swd_out >> scaffold.d1
# swd.swd_in << scaffold.d1
# scaffold.d0.pull = Pull.UP
# scaffold.d1.pull = Pull.UP
#
# status = swd.write(0, 0, 0b11010)
# print(f"status after: {status}")
cchr-ledger marked this conversation as resolved.
Show resolved Hide resolved
110 changes: 110 additions & 0 deletions fpga-arch/bsv/Counter.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
//
// 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.
//

#
cchr-ledger marked this conversation as resolved.
Show resolved Hide resolved
`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
56 changes: 56 additions & 0 deletions fpga-arch/bsv/Prescaler.bsv
Original file line number Diff line number Diff line change
@@ -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 <https://www.gnu.org/licenses/>.
//
//
// Copyright 2024 Ledger SAS, written by Charles Christen

package Prescaler;

import Counter::*;

(* always_ready, always_enabled *)
cchr-ledger marked this conversation as resolved.
Show resolved Hide resolved
interface Prescaler#(numeric type n);
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)));

(* fire_when_enabled, no_implicit_conditions *)
rule count_dow(ctr.value > 0);
ctr.down();
endrule

(* fire_when_enabled, no_implicit_conditions *)
rule reset_count(ctr.value == 0);
ctr.setF(fromInteger(valueof(ctr_max)));
endrule

method rising = (ctr.value == 0);
method pre_rising = (ctr.value == 1);
method falling = (ctr.value == fromInteger(valueof(__a)));

endmodule

endpackage
Loading
Loading