pmd_io: Rename to pmd_dp83223_rx
This better reflects that this is an interface intended to be used with the DP83223. While we're at it, refactor the module to just handle the the recieve portion. Signed-off-by: Sean Anderson <seanga2@gmail.com>
This commit is contained in:
parent
494ef2a2a9
commit
cf0aed4980
|
@ -5,7 +5,7 @@
|
|||
* This roughly follows the design of XAPP225. However, we use a 2x rate DDR
|
||||
* clock instead of two clocks 90 degrees out of phase. Yosys/nextpnr cannot
|
||||
* guarantee the phase relationship of any clocks, even those from the same
|
||||
* PLL. Because of this, we assume that rx_clk_250 and rx_clk_125 are unrelated.
|
||||
* PLL. Because of this, we assume that clk_250 and clk_125 are unrelated.
|
||||
*/
|
||||
|
||||
`include "common.vh"
|
||||
|
@ -13,18 +13,15 @@
|
|||
|
||||
`timescale 1ns/1ps
|
||||
|
||||
module pmd_io (
|
||||
input tx_clk,
|
||||
input rx_clk_250,
|
||||
input rx_clk_125,
|
||||
module pmd_dp83223_rx (
|
||||
input clk_250,
|
||||
input clk_125,
|
||||
|
||||
input signal_detect,
|
||||
input indicate_data,
|
||||
output reg request_data,
|
||||
|
||||
/* PMD */
|
||||
output signal_status,
|
||||
input tx_data,
|
||||
output reg [1:0] rx_data,
|
||||
output reg [1:0] rx_data_valid
|
||||
);
|
||||
|
@ -37,7 +34,7 @@ module pmd_io (
|
|||
.PIN_TYPE(`PIN_OUTPUT_NEVER | `PIN_INPUT_REGISTERED),
|
||||
) signal_detect_pin (
|
||||
.PACKAGE_PIN(signal_detect),
|
||||
.INPUT_CLK(rx_clk_125),
|
||||
.INPUT_CLK(clk_125),
|
||||
.D_IN_0(sd_delay[0])
|
||||
);
|
||||
|
||||
|
@ -45,18 +42,18 @@ module pmd_io (
|
|||
.PIN_TYPE(`PIN_OUTPUT_NEVER | `PIN_INPUT_DDR),
|
||||
) rx_data_pin (
|
||||
.PACKAGE_PIN(indicate_data),
|
||||
.INPUT_CLK(rx_clk_250),
|
||||
.INPUT_CLK(clk_250),
|
||||
.D_IN_0(rx_p[0]),
|
||||
.D_IN_1(rx_n[0])
|
||||
);
|
||||
`else
|
||||
always @(posedge rx_clk_125)
|
||||
always @(posedge clk_125)
|
||||
sd_delay[0] <= signal_detect;
|
||||
|
||||
always @(posedge rx_clk_250)
|
||||
always @(posedge clk_250)
|
||||
rx_p[0] <= indicate_data;
|
||||
|
||||
always @(negedge rx_clk_250)
|
||||
always @(negedge clk_250)
|
||||
rx_n[0] <= indicate_data;
|
||||
`endif
|
||||
|
||||
|
@ -66,30 +63,30 @@ module pmd_io (
|
|||
* (since signal status is asserted long after we have good data), but
|
||||
* it helps out during simulation. It also helps avoid metastability.
|
||||
*/
|
||||
always @(posedge rx_clk_125)
|
||||
always @(posedge clk_125)
|
||||
sd_delay[3:1] <= sd_delay[2:0];
|
||||
|
||||
assign signal_status = sd_delay[3];
|
||||
|
||||
/*
|
||||
* Get things into the rx_clk_250 domain so that we sample posedge before
|
||||
* Get things into the clk_250 domain so that we sample posedge before
|
||||
* negedge. Without this we can have a negedge which happens before the
|
||||
* posedge.
|
||||
*/
|
||||
always @(posedge rx_clk_250) begin
|
||||
always @(posedge clk_250) begin
|
||||
rx_p[1] <= rx_p[0];
|
||||
rx_n[1] <= rx_n[0];
|
||||
end
|
||||
|
||||
reg [3:0] rx_a, rx_b, rx_c, rx_d;
|
||||
|
||||
/* Get everything in the rx_clk_125 domain */
|
||||
always @(posedge rx_clk_125) begin
|
||||
/* Get everything in the clk_125 domain */
|
||||
always @(posedge clk_125) begin
|
||||
rx_a[0] <= rx_p[1];
|
||||
rx_b[0] <= rx_n[1];
|
||||
end
|
||||
|
||||
always @(negedge rx_clk_125) begin
|
||||
always @(negedge clk_125) begin
|
||||
rx_c[0] <= rx_p[1];
|
||||
rx_d[0] <= rx_n[1];
|
||||
end
|
||||
|
@ -99,7 +96,7 @@ module pmd_io (
|
|||
* that, we need two cycles of history to detect edges, plus a final
|
||||
* cycle to select from.
|
||||
*/
|
||||
always @(posedge rx_clk_125) begin
|
||||
always @(posedge clk_125) begin
|
||||
rx_a[3:1] <= rx_a[2:0];
|
||||
rx_b[3:1] <= rx_b[2:0];
|
||||
rx_c[3:1] <= rx_c[2:0];
|
||||
|
@ -120,7 +117,7 @@ module pmd_io (
|
|||
reg [3:0] rx_r, rx_f;
|
||||
|
||||
always @(*) begin
|
||||
rx_r = {
|
||||
rx_r = {
|
||||
rx_a[1] & ~rx_a[2],
|
||||
rx_b[1] & ~rx_b[2],
|
||||
rx_c[1] & ~rx_c[2],
|
||||
|
@ -155,7 +152,7 @@ module pmd_io (
|
|||
state_next = A;
|
||||
valid_next = 0;
|
||||
end
|
||||
|
||||
|
||||
rx_data_next[0] = rx_d[3];
|
||||
rx_data_valid_next = 1;
|
||||
case (state)
|
||||
|
@ -182,7 +179,7 @@ module pmd_io (
|
|||
rx_data_valid_next = 0;
|
||||
end
|
||||
|
||||
always @(posedge rx_clk_125) begin
|
||||
always @(posedge clk_125) begin
|
||||
state <= state_next;
|
||||
valid <= valid_next;
|
||||
wraparound <= wraparound_next;
|
||||
|
@ -190,19 +187,6 @@ module pmd_io (
|
|||
rx_data_valid <= rx_data_valid_next;
|
||||
end
|
||||
|
||||
`ifdef SYNTHESIS
|
||||
SB_IO #(
|
||||
.PIN_TYPE(`PIN_OUTPUT_ALWAYS | `PIN_OUTPUT_REGISTERED),
|
||||
) tx_datap_pin (
|
||||
.PACKAGE_PIN(request_data),
|
||||
.OUTPUT_CLK(rx_clk_125),
|
||||
.D_OUT_0(tx_data)
|
||||
);
|
||||
`else
|
||||
always @(posedge tx_clk)
|
||||
request_data <= tx_data;
|
||||
`endif
|
||||
|
||||
`ifndef SYNTHESIS
|
||||
reg [255:0] state_text;
|
||||
input [13:0] delay;
|
|
@ -30,10 +30,10 @@ def maxdelays(count):
|
|||
async def test_rx(pmd, delays):
|
||||
pmd.signal_detect.value = 0
|
||||
await Timer(1)
|
||||
await cocotb.start(Clock(pmd.rx_clk_125, 8, units='ns').start())
|
||||
await cocotb.start(Clock(pmd.clk_125, 8, units='ns').start())
|
||||
# random phase
|
||||
await Timer(random.randrange(1, 8000), units='ps')
|
||||
await cocotb.start(Clock(pmd.rx_clk_250, 4, units='ns').start())
|
||||
await cocotb.start(Clock(pmd.clk_250, 4, units='ns').start())
|
||||
|
||||
ins = [random.randrange(2) for _ in range(BITS)]
|
||||
async def generate_bits():
|
||||
|
@ -54,7 +54,7 @@ async def test_rx(pmd, delays):
|
|||
await RisingEdge(pmd.signal_status)
|
||||
outs = []
|
||||
while pmd.signal_status.value:
|
||||
await RisingEdge(pmd.rx_clk_125)
|
||||
await RisingEdge(pmd.clk_125)
|
||||
valid = pmd.rx_data_valid.value
|
||||
if valid == 0:
|
||||
pass
|
Loading…
Reference in New Issue