Logic Registers Across a Clock Boundary (USB 2.0)
The SetWireInValue and GetWireOutValue methods in the okCFrontPanel class allow you to set and get up to 32-bit bus values across the entire defined Wire address space (0x00-0x1F for WireIn, 0x20-0x3F for WireOut). You can set the WireIn values by passing in the address of the WireIn and its new value. You can read WireOut values by passing the address of the WireOut and a bit mask to extract only the relevant bits. After setting a wire in value and before reading a wire out value, remember to update the WireIns and WireOuts, respectively. Otherwise, the values will not be accurate.
These techniques are also available on USB 3.0 devices, but those devices include the okRegisterBridge module along with methods and structs for reading registers. If you are using Wires on a USB 3.0 device, note that instead of 16-bit bus values, you can set and get up to 32-bit bus values.
Wires (both in and out) are synchronized to the host interface clock which may not be the same clock used for your internal logic. Therefore, when reading values via wires, it’s a good idea to consider the implications of this mismatch. Below is an example of a recommended synchronizer.
C/C++
okCFrontPanel dev;
UINT32 A;
// Send 0x0A to wire at endpoint 0x03
dev.OpenBySerial();
dev.SetWireInValue(0x03, 0x0A);
dev.UpdateWireIns();
// Read value from WireOut endpoint at 0x20
dev.UpdateWireOuts();
A = dev.GetWireOutValue(0x20);
Code language: JavaScript (javascript)
C#
okCFrontPanel dev = new okCFrontPanel();
UInt32 A;
// Send 0x0A to wire at endpoint 0x03
dev.OpenBySerial("");
dev.SetWireInValue(0x03, 0x0A);
dev.UpdateWireIns();
// Read value from WireOut endpoint at 0x20
dev.UpdateWireOuts();
A = dev.GetWireOutValue(0x20);
Code language: JavaScript (javascript)
Python
dev = ok.okCFrontPanel()
# Send 0x0A to wire at endpoint 0x03
dev.OpenBySerial("")
dev.SetWireInValue(0x03, 0x0A)
dev.UpdateWireIns();
# Read value from WireOut endpoint at 0x20
dev.UpdateWireOuts()
A = dev.GetWireOutValue(0x20)
Code language: PHP (php)
Java
public class example{
okCFrontPanel dev;
long A;
okCFrontPanel.ErrorCode error;
public void Initialize(){
dev = new okCFrontPanel();
dev.OpenBySerial("");
error = dev.ConfigureFPGA("example.bit");
// It’s a good idea to check for errors here!
}
public void SetWires(){
// Send 0x0A to wire at endpoint 0x03
dev.SetWireInValue(0x03, 0x0A);
dev.UpdateWireIns();
}
public long GetWires(){
// Read value from WireOut endpoint at 0x20
dev.UpdateWireIns();
A = dev.GetWireOutValue(0x20);
return A;
}
}
Code language: PHP (php)
Verilog
// Circuit behavior
always @ (posedge clk1) begin
counter <= counter + count_by;
end
reg [31:0] counter_dff1, counter_dff2;
always @(posedge ti_clk) begin
counter_dff1 <= counter; // Potentially metastable capture.
counter_dff2 <= counter_dff1; // Much less likely metastable.
end
// FrontPanel endpoint instantiation
okWireIn inA(
.ok1(ok1),
.ep_addr(8'h03),
.ep_dataout(dataA)
);
okWireOut outA(
.ok1(ok1),
.ok2(ok2x[0*17 +: 17]),
.ep_addr(8'h20),
.ep_datain(dataA)
);
Code language: Verilog (verilog)
VHDL
-- Wire declarations
signal dataA : STD_LOGIC_VECTOR(15 downto 0);
signal counter : STD_LOGIC_VECTOR(31 downto 0);
signal counter_dff1 : STD_LOGIC_VECTOR(31 downto 0);
signal counter_dff2 : STD_LOGIC_VECTOR(31 downto 0);
-- Circuit behavior
process (clk1) begin
if rising_edge(clk1) then
led <= not dataA (7 downto 0);
counter <= counter + "1";
end if;
end process;
process (ti_clk) begin
if rising_edge(ti_clk) then
counter_dff1 <= counter; --Potentially metastable output
counter_dff2 <= counter_dff1; --Much less likely metastable
end if;
end process;
-- FrontPanel endpoint instantiation
inA : okWireIn
port map(
ok1=>ok1,
ep_addr=>x"03",
ep_dataout=>dataA
);
outA : okWireOut
port map(
ok1=>ok1,
ok2=>ok2s( 1*17-1 downto 0*17 ),
ep_addr=>x"20",
ep_datain=>dataA
);
Code language: VHDL (vhdl)