From e2974b236510834a429543b37084bcfd77342d20 Mon Sep 17 00:00:00 2001 From: Andrew Kay Date: Sun, 5 Jul 2020 18:38:59 -0500 Subject: [PATCH] Implement read --- interface2/rtl/coax_rx.v | 37 +++++++++++++++---- interface2/rtl/pins.pcf | 6 ++-- interface2/rtl/top.v | 14 ++++++-- interface2/tests/coax_rx_tb.v | 67 ++++++++++++++++++++++++++++++++--- 4 files changed, 108 insertions(+), 16 deletions(-) diff --git a/interface2/rtl/coax_rx.v b/interface2/rtl/coax_rx.v index 68703c5..6a4f307 100644 --- a/interface2/rtl/coax_rx.v +++ b/interface2/rtl/coax_rx.v @@ -6,13 +6,16 @@ module coax_rx ( input reset, output active, output error, - output reg [9:0] data + output reg [9:0] data, + output reg data_available = 0, + input read ); parameter CLOCKS_PER_BIT = 8; localparam LOSS_OF_MID_BIT_TRANSITION_ERROR = 10'b0000000001; localparam PARITY_ERROR = 10'b0000000010; localparam INVALID_END_SEQUENCE_ERROR = 10'b0000000100; + localparam OVERFLOW_ERROR = 10'b0000001000; localparam IDLE = 0; localparam START_SEQUENCE_1 = 1; @@ -42,12 +45,15 @@ module coax_rx ( reg next_bit_timer_reset; reg [9:0] next_data; + reg next_data_available; reg [9:0] internal_data; reg [9:0] next_internal_data; reg [3:0] bit_counter = 0; reg [3:0] next_bit_counter; + reg previous_read; + wire sample; wire synchronized; @@ -68,9 +74,10 @@ module coax_rx ( next_bit_timer_reset = 0; next_data = data; + next_data_available = data_available; - next_bit_counter = bit_counter; next_internal_data = internal_data; + next_bit_counter = bit_counter; case (state) IDLE: @@ -254,7 +261,17 @@ module coax_rx ( // Even parity includes the sync bit. if (rx == ^{ 1'b1, internal_data }) begin - next_state = SYNC_BIT; + if (!data_available) + begin + next_data_available = 1; + next_data = internal_data; + next_state = SYNC_BIT; + end + else + begin + next_data = OVERFLOW_ERROR; + next_state = ERROR; + end end else begin @@ -294,31 +311,37 @@ module coax_rx ( always @(posedge clk) begin state <= next_state; - state_counter <= (state == next_state) ? state_counter + 1 : 0; bit_timer_reset <= next_bit_timer_reset; data <= next_data; + data_available <= next_data_available; - bit_counter <= next_bit_counter; internal_data <= next_internal_data; + bit_counter <= next_bit_counter; if (reset) begin bit_timer_reset <= 1; - state_counter <= 0; state <= IDLE; + state_counter <= 0; data <= 10'b0000000000; + data_available <= 0; - bit_counter <= 0; internal_data <= 10'b0000000000; + bit_counter <= 0; + end + else if (data_available && !read && previous_read) + begin + data_available <= 0; end previous_rx <= rx; previous_state <= state; + previous_read <= read; end assign active = (state >= SYNC_BIT && state <= PARITY_BIT); diff --git a/interface2/rtl/pins.pcf b/interface2/rtl/pins.pcf index edf75b2..df77d55 100644 --- a/interface2/rtl/pins.pcf +++ b/interface2/rtl/pins.pcf @@ -17,8 +17,8 @@ set_io --warn-no-port reset E1 # 9 #set_io --warn-no-port rx_enable E1 # 9 set_io --warn-no-port rx_active G2 # 10 set_io --warn-no-port rx_error H1 # 11 -#set_io --warn-no-port rx_data_available xx # xx -#set_io --warn-no-port rx_data_read J1 # 12 +set_io --warn-no-port rx_data_available J1 # 12 +set_io --warn-no-port rx_read H2 # 13 # Shared data bus set_io --warn-no-port data[9] B6 # 23 @@ -32,6 +32,6 @@ set_io --warn-no-port data[2] D8 set_io --warn-no-port data[1] D9 set_io --warn-no-port data[0] H9 # 14 -set_io --warn-no-port debug H2 # 13 +set_io --warn-no-port debug A6 # 24 set_io --warn-no-port usb_pu A3 diff --git a/interface2/rtl/top.v b/interface2/rtl/top.v index 229f37b..c1fbcde 100644 --- a/interface2/rtl/top.v +++ b/interface2/rtl/top.v @@ -7,6 +7,8 @@ module top ( input rx, output rx_active, output rx_error, + output rx_data_available, + input rx_read, // Shared data bus inout [9:0] data, @@ -35,12 +37,18 @@ module top ( ); reg rx_0 = 0; - reg rx_1 = 1; + reg rx_1 = 0; + + reg rx_read_0 = 0; + reg rx_read_1 = 0; always @(posedge clk_38mhz) begin rx_0 <= rx; rx_1 <= rx_0; + + rx_read_0 <= rx_read; + rx_read_1 <= rx_read_0; end wire [9:0] rx_data; @@ -53,7 +61,9 @@ module top ( .reset(reset), .active(rx_active), .error(rx_error), - .data(rx_data) + .data(rx_data), + .data_available(rx_data_available), + .read(rx_read_1) ); assign data = rx_data; diff --git a/interface2/tests/coax_rx_tb.v b/interface2/tests/coax_rx_tb.v index cabe7f4..370c083 100644 --- a/interface2/tests/coax_rx_tb.v +++ b/interface2/tests/coax_rx_tb.v @@ -13,20 +13,21 @@ module coax_rx_tb; reg rx = 0; reg reset = 0; + reg read = 0; coax_rx #( .CLOCKS_PER_BIT(8) ) dut ( .clk(clk), .rx(rx), - .reset(reset) + .reset(reset), + .read(read) ); initial begin $dumpfile("coax_rx_tb.vcd"); $dumpvars(0, coax_rx_tb); - /* test_1; test_2; test_3; @@ -42,8 +43,8 @@ module coax_rx_tb; test_13; test_14; test_15; - */ test_16; + test_17; $finish; end @@ -437,7 +438,7 @@ module coax_rx_tb; rx_bit(1); // LSB DATA_BIT rx_bit(1); // PARITY_BIT rx_bit(0); - + rx = 1; #16; rx = 0; @@ -446,10 +447,68 @@ module coax_rx_tb; `assert_equal(dut.state, dut.IDLE, "state should be IDLE"); + `assert_high(dut.data_available, "data_available should be HIGH"); + `assert_equal(dut.data, 10'b0110110011, "data not correct") + + read = 1; + #2; + read = 0; + + #2; + + `assert_low(dut.data_available, "data_available should be LOW"); + $display("END: test_16"); end endtask + task test_17; + begin + $display("START: test_17"); + + `assert_equal(dut.state, dut.IDLE, "state should be IDLE"); + + rx_start_sequence; + rx_bit(1); // SYNC_BIT + rx_bit(0); // MSB DATA_BIT + rx_bit(1); + rx_bit(1); + rx_bit(0); + rx_bit(1); + rx_bit(1); + rx_bit(0); + rx_bit(0); + rx_bit(1); + rx_bit(1); // LSB DATA_BIT + rx_bit(1); // PARITY_BIT + rx_bit(1); // SYNC_BIT + rx_bit(1); // MSB DATA_BIT + rx_bit(0); + rx_bit(1); + rx_bit(1); + rx_bit(0); + rx_bit(1); + rx_bit(1); + rx_bit(0); + rx_bit(1); + rx_bit(1); // LSB DATA_BIT + rx_bit(0); // PARITY_BIT + + `assert_equal(dut.state, dut.ERROR, "State should be ERROR"); + + `assert_high(dut.error, "error should be HIGH"); + `assert_equal(dut.data, dut.OVERFLOW_ERROR, "data should be OVERFLOW_ERROR"); + + dut_reset; + + #16; + + `assert_equal(dut.state, dut.IDLE, "state should be IDLE"); + + $display("END: test_17"); + end + endtask + task dut_reset; begin reset = 1;