mirror of
https://github.com/lowobservable/coax.git
synced 2026-02-10 18:40:22 +00:00
Add 3299 protocol support to interface2
This commit is contained in:
@@ -24,6 +24,7 @@ module coax_buffered_rx (
|
||||
input read_strobe,
|
||||
output empty,
|
||||
output full,
|
||||
input protocol,
|
||||
input parity
|
||||
);
|
||||
parameter CLOCKS_PER_BIT = 8;
|
||||
@@ -45,6 +46,7 @@ module coax_buffered_rx (
|
||||
.error(coax_rx_error),
|
||||
.data(coax_rx_data),
|
||||
.strobe(coax_rx_strobe),
|
||||
.protocol(protocol),
|
||||
.parity(parity)
|
||||
);
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ module coax_buffered_tx (
|
||||
output empty,
|
||||
output full,
|
||||
output reg ready,
|
||||
input protocol,
|
||||
input parity
|
||||
);
|
||||
parameter CLOCKS_PER_BIT = 8;
|
||||
@@ -56,6 +57,7 @@ module coax_buffered_tx (
|
||||
.data(coax_tx_data),
|
||||
.strobe(coax_tx_strobe),
|
||||
.ready(coax_tx_ready),
|
||||
.protocol(protocol),
|
||||
.parity(parity)
|
||||
);
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ module coax_rx (
|
||||
output reg error,
|
||||
output reg [9:0] data,
|
||||
output reg strobe = 0,
|
||||
input protocol,
|
||||
input parity
|
||||
);
|
||||
parameter CLOCKS_PER_BIT = 8;
|
||||
@@ -95,6 +96,8 @@ module coax_rx (
|
||||
case (state)
|
||||
STATE_IDLE:
|
||||
begin
|
||||
next_input_data = 10'b0;
|
||||
|
||||
if (ss_detector_strobe)
|
||||
begin
|
||||
// The start sequence ends with a code violation, so reset
|
||||
@@ -111,7 +114,7 @@ module coax_rx (
|
||||
// differently and consider it part of the start sequence as
|
||||
// it must be a 1 and we don't consider the receiver active
|
||||
// until this has been detected.
|
||||
next_bit_counter = 0;
|
||||
next_bit_counter = (protocol == 1 ? 4 : 0);
|
||||
|
||||
if (rx != previous_rx && mid_bit_counter > CLOCKS_PER_HALF_BIT)
|
||||
begin
|
||||
|
||||
@@ -22,6 +22,7 @@ module coax_tx (
|
||||
input [9:0] data,
|
||||
input strobe,
|
||||
output ready,
|
||||
input protocol,
|
||||
input parity
|
||||
);
|
||||
parameter CLOCKS_PER_BIT = 8;
|
||||
@@ -48,6 +49,8 @@ module coax_tx (
|
||||
|
||||
reg next_tx;
|
||||
|
||||
reg first_word;
|
||||
reg next_first_word;
|
||||
reg end_sequence;
|
||||
reg next_end_sequence;
|
||||
|
||||
@@ -86,6 +89,7 @@ module coax_tx (
|
||||
|
||||
next_tx = 0;
|
||||
|
||||
next_first_word = first_word;
|
||||
next_end_sequence = 0;
|
||||
|
||||
next_output_data = output_data;
|
||||
@@ -188,6 +192,7 @@ module coax_tx (
|
||||
START_SEQUENCE_9:
|
||||
begin
|
||||
next_tx = 1;
|
||||
next_first_word = 1;
|
||||
|
||||
if (last_clock)
|
||||
next_state = SYNC_BIT;
|
||||
@@ -197,10 +202,21 @@ module coax_tx (
|
||||
begin
|
||||
next_tx = first_half ? 0 : 1;
|
||||
|
||||
next_bit_counter = 9;
|
||||
|
||||
if (last_clock)
|
||||
begin
|
||||
// First word is 6 bits in 3299 protocol mode.
|
||||
if (protocol == 1 && first_word)
|
||||
begin
|
||||
next_output_data = { output_data[5:0], 4'b0 };
|
||||
next_bit_counter = 5;
|
||||
end
|
||||
else
|
||||
begin
|
||||
next_bit_counter = 9;
|
||||
end
|
||||
|
||||
next_state = DATA_BIT;
|
||||
end
|
||||
end
|
||||
|
||||
DATA_BIT:
|
||||
@@ -228,6 +244,8 @@ module coax_tx (
|
||||
|
||||
if (last_clock)
|
||||
begin
|
||||
next_first_word = 0;
|
||||
|
||||
if (output_data_full)
|
||||
begin
|
||||
next_state = SYNC_BIT;
|
||||
@@ -280,6 +298,7 @@ module coax_tx (
|
||||
active <= (state != IDLE); // TODO: this causes active to remain high one additional clock cycle
|
||||
tx <= next_tx;
|
||||
|
||||
first_word <= next_first_word;
|
||||
end_sequence <= next_end_sequence;
|
||||
|
||||
output_data <= next_output_data;
|
||||
|
||||
@@ -36,6 +36,7 @@ module control (
|
||||
input tx_empty,
|
||||
input tx_full,
|
||||
input tx_ready,
|
||||
output tx_protocol,
|
||||
output tx_parity,
|
||||
|
||||
// RX
|
||||
@@ -45,6 +46,7 @@ module control (
|
||||
input [9:0] rx_data,
|
||||
output reg rx_read_strobe,
|
||||
input rx_empty,
|
||||
output rx_protocol,
|
||||
output rx_parity
|
||||
);
|
||||
parameter DEFAULT_CONTROL_REGISTER = 8'b01001000;
|
||||
@@ -342,6 +344,8 @@ module control (
|
||||
|
||||
assign loopback = control_register[0];
|
||||
|
||||
assign tx_protocol = control_register[2];
|
||||
assign tx_parity = control_register[3];
|
||||
assign rx_protocol = control_register[5];
|
||||
assign rx_parity = control_register[6];
|
||||
endmodule
|
||||
|
||||
@@ -98,6 +98,7 @@ module top (
|
||||
wire tx_empty;
|
||||
wire tx_full;
|
||||
wire tx_ready;
|
||||
wire tx_protocol;
|
||||
wire tx_parity;
|
||||
|
||||
coax_buffered_tx #(
|
||||
@@ -115,6 +116,7 @@ module top (
|
||||
.empty(tx_empty),
|
||||
.full(tx_full),
|
||||
.ready(tx_ready),
|
||||
.protocol(tx_protocol),
|
||||
.parity(tx_parity)
|
||||
);
|
||||
|
||||
@@ -125,6 +127,7 @@ module top (
|
||||
wire [9:0] rx_data;
|
||||
wire rx_read_strobe;
|
||||
wire rx_empty;
|
||||
wire rx_protocol;
|
||||
wire rx_parity;
|
||||
|
||||
coax_buffered_rx #(
|
||||
@@ -139,6 +142,7 @@ module top (
|
||||
.data(rx_data),
|
||||
.read_strobe(rx_read_strobe),
|
||||
.empty(rx_empty),
|
||||
.protocol(rx_protocol),
|
||||
.parity(rx_parity)
|
||||
);
|
||||
|
||||
@@ -184,6 +188,7 @@ module top (
|
||||
.tx_empty(tx_empty),
|
||||
.tx_full(tx_full),
|
||||
.tx_ready(tx_ready),
|
||||
.tx_protocol(tx_protocol),
|
||||
.tx_parity(tx_parity),
|
||||
|
||||
.rx_reset(rx_reset),
|
||||
@@ -192,6 +197,7 @@ module top (
|
||||
.rx_data(rx_data),
|
||||
.rx_read_strobe(rx_read_strobe),
|
||||
.rx_empty(rx_empty),
|
||||
.rx_protocol(rx_protocol),
|
||||
.rx_parity(rx_parity)
|
||||
);
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ coax_tx_tb: coax_tx_tb.v $(RTL)/coax_tx.v $(RTL)/coax_tx_bit_timer.v
|
||||
coax_rx_blanker_tb: coax_rx_blanker_tb.v $(RTL)/coax_rx_blanker.v
|
||||
coax_tx_rx_frontend_tb: coax_tx_rx_frontend_tb.v $(RTL)/coax_tx_rx_frontend.v $(RTL)/coax_tx_distorter.v $(RTL)/coax_rx_blanker.v
|
||||
control_tb: control_tb.v $(RTL)/control.v $(RTL)/coax_buffered_tx.v $(RTL)/coax_tx.v $(RTL)/coax_tx_bit_timer.v $(RTL)/coax_buffer.v $(RTL)/third_party/*.v
|
||||
tx_rx_loopback_tb: tx_rx_loopback_tb.v $(RTL)/coax_tx.v $(RTL)/coax_tx_bit_timer.v $(RTL)/coax_rx.v $(RTL)/coax_rx_ss_detector.v
|
||||
regression_memorex_tb: regression_memorex_tb.v $(RTL)/coax_rx.v $(RTL)/coax_rx_ss_detector.v
|
||||
|
||||
test: $(TESTS)
|
||||
|
||||
@@ -31,6 +31,7 @@ module coax_buffered_rx_tb;
|
||||
.reset(reset),
|
||||
.rx(rx),
|
||||
.read_strobe(read_strobe),
|
||||
.protocol(1'b0),
|
||||
.parity(1'b1)
|
||||
);
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ module coax_buffered_tx_tb;
|
||||
.data(data),
|
||||
.load_strobe(load_strobe),
|
||||
.start_strobe(start_strobe),
|
||||
.protocol(1'b0),
|
||||
.parity(1'b1)
|
||||
);
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ module coax_rx_tb;
|
||||
.clk(clk),
|
||||
.reset(reset),
|
||||
.rx(rx),
|
||||
.protocol(1'b0),
|
||||
.parity(1'b1)
|
||||
);
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ module coax_tx_tb;
|
||||
.reset(reset),
|
||||
.data(data),
|
||||
.strobe(strobe),
|
||||
.protocol(1'b0),
|
||||
.parity(1'b1)
|
||||
);
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ module regression_memorex_tb;
|
||||
.clk(clk),
|
||||
.reset(reset),
|
||||
.rx(rx),
|
||||
.protocol(1'b0),
|
||||
.parity(1'b1)
|
||||
);
|
||||
|
||||
|
||||
323
interface2/fpga/tests/tx_rx_loopback_tb.v
Normal file
323
interface2/fpga/tests/tx_rx_loopback_tb.v
Normal file
@@ -0,0 +1,323 @@
|
||||
`default_nettype none
|
||||
|
||||
`include "assert.v"
|
||||
|
||||
module tx_rx_loopback_tb;
|
||||
reg clk = 0;
|
||||
|
||||
initial
|
||||
begin
|
||||
forever
|
||||
begin
|
||||
#1 clk <= ~clk;
|
||||
end
|
||||
end
|
||||
|
||||
reg reset = 0;
|
||||
wire loopback;
|
||||
wire tx_active;
|
||||
reg [9:0] tx_data;
|
||||
reg tx_strobe = 0;
|
||||
wire tx_ready;
|
||||
reg tx_protocol = 0;
|
||||
reg tx_parity = 0;
|
||||
wire rx_error;
|
||||
wire [9:0] rx_data;
|
||||
wire rx_strobe;
|
||||
reg rx_protocol = 0;
|
||||
reg rx_parity = 0;
|
||||
|
||||
coax_tx #(
|
||||
.CLOCKS_PER_BIT(8)
|
||||
) dut_tx (
|
||||
.clk(clk),
|
||||
.reset(reset),
|
||||
.active(tx_active),
|
||||
.tx(loopback),
|
||||
.data(tx_data),
|
||||
.strobe(tx_strobe),
|
||||
.ready(tx_ready),
|
||||
.protocol(tx_protocol),
|
||||
.parity(tx_parity)
|
||||
);
|
||||
|
||||
coax_rx #(
|
||||
.CLOCKS_PER_BIT(8)
|
||||
) dut_rx (
|
||||
.clk(clk),
|
||||
.reset(reset),
|
||||
.rx(loopback),
|
||||
.error(rx_error),
|
||||
.data(rx_data),
|
||||
.strobe(rx_strobe),
|
||||
.protocol(rx_protocol),
|
||||
.parity(rx_parity)
|
||||
);
|
||||
|
||||
initial
|
||||
begin
|
||||
$dumpfile("tx_rx_loopback_tb.vcd");
|
||||
$dumpvars(0, tx_rx_loopback_tb);
|
||||
|
||||
test_3270_protocol;
|
||||
test_3299_protocol;
|
||||
test_protocol_mismatch;
|
||||
test_parity_mismatch;
|
||||
|
||||
$finish;
|
||||
end
|
||||
|
||||
task test_3270_protocol;
|
||||
begin
|
||||
$display("START: test_3270_protocol");
|
||||
|
||||
tx_protocol = 0;
|
||||
tx_parity = 1;
|
||||
rx_protocol = 0;
|
||||
rx_parity = 1;
|
||||
|
||||
`assert_equal(dut_tx.state, dut_tx.IDLE, "state should be IDLE");
|
||||
`assert_equal(dut_rx.state, dut_rx.STATE_IDLE, "state should be IDLE");
|
||||
|
||||
fork: test_3270_protocol_tx_rx_fork
|
||||
begin
|
||||
tx_data = 10'b0101110101;
|
||||
|
||||
#2;
|
||||
tx_strobe = 1;
|
||||
#2;
|
||||
tx_strobe = 0;
|
||||
|
||||
@(posedge tx_ready);
|
||||
|
||||
tx_data = 10'b1010001010;
|
||||
|
||||
#2;
|
||||
tx_strobe = 1;
|
||||
#2;
|
||||
tx_strobe = 0;
|
||||
end
|
||||
|
||||
begin
|
||||
@(posedge rx_strobe);
|
||||
|
||||
`assert_equal(rx_data, 10'b0101110101, "RX data should be equal to TX data");
|
||||
|
||||
@(posedge rx_strobe);
|
||||
|
||||
`assert_equal(rx_data, 10'b1010001010, "RX data should be equal to TX data");
|
||||
|
||||
disable test_3270_protocol_tx_rx_fork;
|
||||
end
|
||||
|
||||
begin
|
||||
#1000;
|
||||
$display("[TIMEOUT] %m (%s:%0d)", `__FILE__, `__LINE__);
|
||||
disable test_3270_protocol_tx_rx_fork;
|
||||
end
|
||||
join
|
||||
|
||||
#100;
|
||||
|
||||
`assert_equal(dut_tx.state, dut_tx.IDLE, "state should be IDLE");
|
||||
`assert_equal(dut_rx.state, dut_rx.STATE_IDLE, "state should be IDLE");
|
||||
|
||||
$display("END: test_3270_protocol");
|
||||
end
|
||||
endtask
|
||||
|
||||
task test_3299_protocol;
|
||||
begin
|
||||
$display("START: test_3299_protocol");
|
||||
|
||||
tx_protocol = 1;
|
||||
tx_parity = 1;
|
||||
rx_protocol = 1;
|
||||
rx_parity = 1;
|
||||
|
||||
`assert_equal(dut_tx.state, dut_tx.IDLE, "state should be IDLE");
|
||||
`assert_equal(dut_rx.state, dut_rx.STATE_IDLE, "state should be IDLE");
|
||||
|
||||
fork: test_3299_protocol_tx_rx_fork
|
||||
begin
|
||||
tx_data = 10'b0000110001;
|
||||
|
||||
#2;
|
||||
tx_strobe = 1;
|
||||
#2;
|
||||
tx_strobe = 0;
|
||||
|
||||
@(posedge tx_ready);
|
||||
|
||||
tx_data = 10'b0101110101;
|
||||
|
||||
#2;
|
||||
tx_strobe = 1;
|
||||
#2;
|
||||
tx_strobe = 0;
|
||||
|
||||
@(posedge tx_ready);
|
||||
|
||||
tx_data = 10'b1010001010;
|
||||
|
||||
#2;
|
||||
tx_strobe = 1;
|
||||
#2;
|
||||
tx_strobe = 0;
|
||||
end
|
||||
|
||||
begin
|
||||
@(posedge rx_strobe);
|
||||
|
||||
`assert_equal(rx_data, 10'b0000110001, "RX data should be equal to TX data");
|
||||
|
||||
@(posedge rx_strobe);
|
||||
|
||||
`assert_equal(rx_data, 10'b0101110101, "RX data should be equal to TX data");
|
||||
|
||||
@(posedge rx_strobe);
|
||||
|
||||
`assert_equal(rx_data, 10'b1010001010, "RX data should be equal to TX data");
|
||||
|
||||
disable test_3299_protocol_tx_rx_fork;
|
||||
end
|
||||
|
||||
begin
|
||||
#1000;
|
||||
$display("[TIMEOUT] %m (%s:%0d)", `__FILE__, `__LINE__);
|
||||
disable test_3299_protocol_tx_rx_fork;
|
||||
end
|
||||
join
|
||||
|
||||
#100;
|
||||
|
||||
`assert_equal(dut_tx.state, dut_tx.IDLE, "state should be IDLE");
|
||||
`assert_equal(dut_rx.state, dut_rx.STATE_IDLE, "state should be IDLE");
|
||||
|
||||
$display("END: test_3299_protocol");
|
||||
end
|
||||
endtask
|
||||
|
||||
task test_protocol_mismatch;
|
||||
begin
|
||||
$display("START: test_protocol_mismatch");
|
||||
|
||||
tx_protocol = 1;
|
||||
tx_parity = 1;
|
||||
rx_protocol = 0;
|
||||
rx_parity = 1;
|
||||
|
||||
`assert_equal(dut_tx.state, dut_tx.IDLE, "state should be IDLE");
|
||||
`assert_equal(dut_rx.state, dut_rx.STATE_IDLE, "state should be IDLE");
|
||||
|
||||
fork: test_protocol_mismatch_tx_rx_fork
|
||||
begin
|
||||
tx_data = 10'b0000110001;
|
||||
|
||||
#2;
|
||||
tx_strobe = 1;
|
||||
#2;
|
||||
tx_strobe = 0;
|
||||
|
||||
@(posedge tx_ready);
|
||||
|
||||
tx_data = 10'b0101110101;
|
||||
|
||||
#2;
|
||||
tx_strobe = 1;
|
||||
#2;
|
||||
tx_strobe = 0;
|
||||
|
||||
// Wait for TX to complete... we don't want to reset the RX
|
||||
// to soon as it could be reactivated with the remaining
|
||||
// transmission.
|
||||
@(negedge tx_active);
|
||||
|
||||
disable test_protocol_mismatch_tx_rx_fork;
|
||||
end
|
||||
|
||||
begin
|
||||
#1000;
|
||||
$display("[TIMEOUT] %m (%s:%0d)", `__FILE__, `__LINE__);
|
||||
disable test_protocol_mismatch_tx_rx_fork;
|
||||
end
|
||||
join
|
||||
|
||||
// The exact error (parity or loss of mid-bit transition) may depend
|
||||
// on the length of message and data.
|
||||
`assert_high(rx_error, "RX error should be HIGH");
|
||||
`assert_equal(rx_data, dut_rx.ERROR_LOSS_OF_MID_BIT_TRANSITION, "RX data should be ERROR_LOSS_OF_MID_BIT_TRANSITION");
|
||||
|
||||
#16;
|
||||
|
||||
dut_reset;
|
||||
|
||||
#100;
|
||||
|
||||
`assert_equal(dut_tx.state, dut_tx.IDLE, "state should be IDLE");
|
||||
`assert_equal(dut_rx.state, dut_rx.STATE_IDLE, "state should be IDLE");
|
||||
|
||||
$display("END: test_protocol_mismatch");
|
||||
end
|
||||
endtask
|
||||
|
||||
task test_parity_mismatch;
|
||||
begin
|
||||
$display("START: test_parity_mismatch");
|
||||
|
||||
tx_protocol = 0;
|
||||
tx_parity = 1;
|
||||
rx_protocol = 0;
|
||||
rx_parity = 0;
|
||||
|
||||
`assert_equal(dut_tx.state, dut_tx.IDLE, "state should be IDLE");
|
||||
`assert_equal(dut_rx.state, dut_rx.STATE_IDLE, "state should be IDLE");
|
||||
|
||||
fork: test_parity_mismatch_tx_rx_fork
|
||||
begin
|
||||
tx_data = 10'b0101110101;
|
||||
|
||||
#2;
|
||||
tx_strobe = 1;
|
||||
#2;
|
||||
tx_strobe = 0;
|
||||
|
||||
// Wait for TX to complete... we don't want to reset the RX
|
||||
// to soon as it could be reactivated with the remaining
|
||||
// transmission.
|
||||
@(negedge tx_active);
|
||||
|
||||
disable test_parity_mismatch_tx_rx_fork;
|
||||
end
|
||||
|
||||
begin
|
||||
#1000;
|
||||
$display("[TIMEOUT] %m (%s:%0d)", `__FILE__, `__LINE__);
|
||||
disable test_parity_mismatch_tx_rx_fork;
|
||||
end
|
||||
join
|
||||
|
||||
`assert_high(rx_error, "RX error should be HIGH");
|
||||
`assert_equal(rx_data, dut_rx.ERROR_PARITY, "RX data should be ERROR_PARITY");
|
||||
|
||||
#16;
|
||||
|
||||
dut_reset;
|
||||
|
||||
#100;
|
||||
|
||||
`assert_equal(dut_tx.state, dut_tx.IDLE, "state should be IDLE");
|
||||
`assert_equal(dut_rx.state, dut_rx.STATE_IDLE, "state should be IDLE");
|
||||
|
||||
$display("END: test_parity_mismatch");
|
||||
end
|
||||
endtask
|
||||
|
||||
task dut_reset;
|
||||
begin
|
||||
reset = 1;
|
||||
#2;
|
||||
reset = 0;
|
||||
end
|
||||
endtask
|
||||
endmodule
|
||||
Reference in New Issue
Block a user