From 0a03fde6f9255ca2d92e7a808588f216a3960c08 Mon Sep 17 00:00:00 2001 From: Andrew Kay Date: Mon, 15 Jun 2020 21:22:30 -0500 Subject: [PATCH] Initial coax_rx_bit_timer --- interface2/rtl/coax_rx_bit_timer.v | 97 +++++++++++++++++++++++++ interface2/tests/Makefile | 6 +- interface2/tests/coax_rx_bit_timer_tb.v | 85 ++++++++++++++++++++++ 3 files changed, 186 insertions(+), 2 deletions(-) create mode 100644 interface2/rtl/coax_rx_bit_timer.v create mode 100644 interface2/tests/coax_rx_bit_timer_tb.v diff --git a/interface2/rtl/coax_rx_bit_timer.v b/interface2/rtl/coax_rx_bit_timer.v new file mode 100644 index 0000000..3970699 --- /dev/null +++ b/interface2/rtl/coax_rx_bit_timer.v @@ -0,0 +1,97 @@ +`default_nettype none + +module coax_rx_bit_timer( + input clk, + input rx, + input reset, + output reg sample, + output reg synchronized +); + parameter CLOCKS_PER_BIT = 8; + + localparam IDLE = 0; + localparam SYNCHRONIZED = 1; + localparam UNSYNCHRONIZED = 2; + + reg [1:0] state = IDLE; + reg [1:0] next_state; + + reg previous_rx; + + reg [$clog2(CLOCKS_PER_BIT*2):0] transition_counter = 0; + reg [$clog2(CLOCKS_PER_BIT*2):0] next_transition_counter; + reg [$clog2(CLOCKS_PER_BIT):0] bit_counter = 0; + reg [$clog2(CLOCKS_PER_BIT):0] next_bit_counter; + + always @(*) + begin + next_state = state; + + sample = 0; + synchronized = 0; + + next_transition_counter = transition_counter; + next_bit_counter = bit_counter; + + case (state) + IDLE: + begin + if (rx != previous_rx) + begin + next_transition_counter = 0; + next_bit_counter = CLOCKS_PER_BIT / 2; + + next_state = SYNCHRONIZED; + end + end + + SYNCHRONIZED: + begin + if (transition_counter < CLOCKS_PER_BIT * 1.25) + next_transition_counter = transition_counter + 1; + else + next_state = UNSYNCHRONIZED; + + synchronized = 1; + + if (bit_counter < CLOCKS_PER_BIT) + next_bit_counter = bit_counter + 1; + else + next_bit_counter = 0; + + if (rx != previous_rx && transition_counter > CLOCKS_PER_BIT / 2) + begin + next_transition_counter = 0; + next_bit_counter = CLOCKS_PER_BIT / 2; + end + + if (bit_counter == CLOCKS_PER_BIT * 0.75) + sample = 1; + end + + UNSYNCHRONIZED: + begin + if (bit_counter < CLOCKS_PER_BIT) + next_bit_counter = bit_counter + 1; + else + next_bit_counter = 0; + + if (bit_counter == CLOCKS_PER_BIT * 0.75) + sample = 1; + end + endcase + end + + always @(posedge clk) + begin + state <= next_state; + + transition_counter <= next_transition_counter; + bit_counter <= next_bit_counter; + + if (reset) + state <= IDLE; + + previous_rx <= rx; + end +endmodule diff --git a/interface2/tests/Makefile b/interface2/tests/Makefile index 24b93db..d211b9a 100644 --- a/interface2/tests/Makefile +++ b/interface2/tests/Makefile @@ -3,7 +3,9 @@ VVP ?= vvp RTL = ../rtl -all: +all: coax_rx_bit_timer_tb.vcd + +coax_rx_bit_timer_tb: coax_rx_bit_timer_tb.v $(RTL)/coax_rx_bit_timer.v clean: rm -f *_tb *.vcd @@ -12,6 +14,6 @@ clean: $(IVERILOG) -o $@ $^ %_tb.vcd: %_tb - $(VVP) -N $< -lxt2 + $(VVP) -N $< .PHONY: all, clean diff --git a/interface2/tests/coax_rx_bit_timer_tb.v b/interface2/tests/coax_rx_bit_timer_tb.v new file mode 100644 index 0000000..b1e90dd --- /dev/null +++ b/interface2/tests/coax_rx_bit_timer_tb.v @@ -0,0 +1,85 @@ +`default_nettype none + +module coax_rx_bit_timer_tb(); + reg clk = 0; + + initial begin + forever begin + #1 clk <= ~clk; + end + end + + reg rx = 0; + reg reset = 0; + wire sample; + wire synchronized; + + coax_rx_bit_timer #( + .CLOCKS_PER_BIT(8) + ) dut ( + .clk(clk), + .rx(rx), + .reset(reset), + .sample(sample), + .synchronized(synchronized) + ); + + initial begin + $dumpfile("coax_rx_bit_timer_tb.vcd"); + $dumpvars(0, coax_rx_bit_timer_tb); + + // Idle + #32; + + // Perfect + rx_bit(1); + rx_bit(0); + rx_bit(1); + + // Delayed + rx_bit_custom(0, 9, 8); + + // Shortened + rx_bit_custom(0, 6, 7); + + // Stuck + rx_bit_custom(1, 24, 8); + + // Reset + reset = 1; + #2; + reset = 0; + + rx_bit(1); + + #32; + + $finish; + end + + task rx_bit ( + input bit + ); + begin + rx = !bit; + #8; + rx = bit; + #8; + rx = 0; + end + endtask + + task rx_bit_custom ( + input bit, + input [15:0] first_half_duration, + input [15:0] second_half_duration + ); + begin + rx = !bit; + #first_half_duration; + rx = bit; + #second_half_duration; + rx = 0; + end + endtask +endmodule