Add initial coax_tx

This commit is contained in:
Andrew Kay
2020-07-08 19:19:19 -05:00
parent 095f1a3ba5
commit f2166cd960
3 changed files with 409 additions and 1 deletions

295
interface2/rtl/coax_tx.v Normal file
View File

@@ -0,0 +1,295 @@
`default_nettype none
module coax_tx (
input clk,
input reset,
output reg active,
output reg tx,
input [9:0] data,
input load,
output full
);
parameter CLOCKS_PER_BIT = 8;
localparam IDLE = 0;
localparam START_SEQUENCE_1 = 1;
localparam START_SEQUENCE_2 = 2;
localparam START_SEQUENCE_3 = 3;
localparam START_SEQUENCE_4 = 4;
localparam START_SEQUENCE_5 = 5;
localparam START_SEQUENCE_6 = 6;
localparam START_SEQUENCE_7 = 7;
localparam START_SEQUENCE_8 = 8;
localparam SYNC_BIT = 9;
localparam DATA_BIT = 10;
localparam PARITY_BIT = 11;
localparam END_SEQUENCE_1 = 12;
localparam END_SEQUENCE_2 = 13;
localparam END_SEQUENCE_3 = 14;
reg [3:0] state = IDLE;
reg [3:0] next_state;
reg next_active;
reg next_tx;
reg previous_load;
reg [9:0] holding_data;
reg [9:0] next_holding_data;
reg holding_data_full = 0;
reg next_holding_data_full;
reg [9:0] output_data;
reg [9:0] next_output_data;
reg output_data_full = 0;
reg next_output_data_full;
reg [3:0] bit_counter = 0;
reg [3:0] next_bit_counter;
reg bit_timer_reset = 0;
reg next_bit_timer_reset;
wire first_half;
wire second_half;
wire last_clock;
coax_tx_bit_timer #(
.CLOCKS_PER_BIT(CLOCKS_PER_BIT)
) bit_timer (
.clk(clk),
.reset(bit_timer_reset),
.first_half(first_half),
.second_half(second_half),
.last_clock(last_clock)
);
always @(*)
begin
next_state = state;
next_tx = 0;
next_holding_data = holding_data;
next_holding_data_full = holding_data_full;
next_output_data = output_data;
next_output_data_full = output_data_full;
if (!load && previous_load)
begin
if (!holding_data_full && !output_data_full)
begin
next_output_data = data;
next_output_data_full = 1;
end
else if (!holding_data_full)
begin
next_holding_data = data;
next_holding_data_full = 1;
end
end
next_bit_counter = bit_counter;
next_bit_timer_reset = 0;
case (state)
IDLE:
begin
if (output_data_full)
begin
next_bit_timer_reset = 1;
next_state = START_SEQUENCE_1;
end
end
START_SEQUENCE_1:
begin
next_tx = first_half ? 0 : 1;
if (last_clock)
next_state = START_SEQUENCE_2;
end
START_SEQUENCE_2:
begin
next_tx = first_half ? 0 : 1;
if (last_clock)
next_state = START_SEQUENCE_3;
end
START_SEQUENCE_3:
begin
next_tx = first_half ? 0 : 1;
if (last_clock)
next_state = START_SEQUENCE_4;
end
START_SEQUENCE_4:
begin
next_tx = first_half ? 0 : 1;
if (last_clock)
next_state = START_SEQUENCE_5;
end
START_SEQUENCE_5:
begin
next_tx = first_half ? 0 : 1;
if (last_clock)
next_state = START_SEQUENCE_6;
end
START_SEQUENCE_6:
begin
next_tx = 0;
if (last_clock)
next_state = START_SEQUENCE_7;
end
START_SEQUENCE_7:
begin
next_tx = first_half ? 0 : 1;
if (last_clock)
next_state = START_SEQUENCE_8;
end
START_SEQUENCE_8:
begin
next_tx = 1;
if (last_clock)
next_state = SYNC_BIT;
end
SYNC_BIT:
begin
next_tx = first_half ? 0 : 1;
if (last_clock)
begin
next_bit_counter = 9;
next_state = DATA_BIT;
end
end
DATA_BIT:
begin
next_tx = first_half ? ~output_data[9] : output_data[9];
if (last_clock)
begin
if (bit_counter == 0)
begin
next_state = PARITY_BIT;
end
else
begin
next_output_data = { output_data[8:0], output_data[9] };
next_bit_counter = bit_counter - 1;
end
end
end
PARITY_BIT:
begin
// Even parity includes the sync bit.
next_tx = first_half ? ~^{ 1'b1, output_data } : ^{ 1'b1, output_data };
if (last_clock)
begin
next_output_data_full = 0;
if (holding_data_full)
begin
next_output_data = holding_data;
next_output_data_full = 1;
next_holding_data_full = 0;
next_state = SYNC_BIT;
end
else
begin
next_state = END_SEQUENCE_1;
end
end
end
END_SEQUENCE_1:
begin
next_tx = first_half ? 1 : 0;
if (last_clock)
next_state = END_SEQUENCE_2;
end
END_SEQUENCE_2:
begin
next_tx = 1;
if (last_clock)
next_state = END_SEQUENCE_3;
end
END_SEQUENCE_3:
begin
next_tx = 1;
if (last_clock)
begin
next_tx = 0;
next_state = IDLE;
end
end
endcase
end
always @(*)
begin
next_active = (next_state != IDLE);
end
always @(posedge clk)
begin
state <= next_state;
active <= next_active;
tx <= next_tx;
holding_data <= next_holding_data;
holding_data_full <= next_holding_data_full;
output_data <= next_output_data;
output_data_full <= next_output_data_full;
bit_counter <= next_bit_counter;
bit_timer_reset <= next_bit_timer_reset;
if (reset)
begin
state <= IDLE;
active <= 0;
tx <= 0;
holding_data <= 10'b0000000000;
holding_data_full <= 0;
output_data <= 10'b0000000000;
output_data_full <= 0;
bit_counter <= 0;
bit_timer_reset <= 0;
end
previous_load <= load;
end
assign full = holding_data_full;
endmodule

View File

@@ -3,9 +3,10 @@ VVP ?= vvp
RTL = ../rtl
all: coax_tx_bit_timer_tb.vcd coax_rx_bit_timer_tb.vcd coax_rx_tb.vcd
all: coax_tx_bit_timer_tb.vcd coax_tx_tb.vcd coax_rx_bit_timer_tb.vcd coax_rx_tb.vcd
coax_tx_bit_timer_tb: coax_tx_bit_timer_tb.v $(RTL)/coax_tx_bit_timer.v
coax_tx_tb: coax_tx_tb.v $(RTL)/coax_tx.v $(RTL)/coax_tx_bit_timer.v
coax_rx_bit_timer_tb: coax_rx_bit_timer_tb.v $(RTL)/coax_rx_bit_timer.v
coax_rx_tb: coax_rx_tb.v $(RTL)/coax_rx.v $(RTL)/coax_rx_bit_timer.v

View File

@@ -0,0 +1,112 @@
`default_nettype none
`include "assert.v"
module coax_tx_tb;
reg clk = 0;
initial
begin
forever
begin
#1 clk <= ~clk;
end
end
reg reset = 0;
reg [9:0] data;
reg load = 0;
coax_tx #(
.CLOCKS_PER_BIT(8)
) dut (
.clk(clk),
.reset(reset),
.data(data),
.load(load)
);
initial
begin
$dumpfile("coax_tx_tb.vcd");
$dumpvars(0, coax_tx_tb);
test_1;
test_2;
test_3;
$finish;
end
task test_1;
begin
$display("START: test_1");
`assert_equal(dut.state, dut.IDLE, "state should be IDLE");
dut_reset;
#8;
`assert_equal(dut.state, dut.IDLE, "state should be IDLE");
$display("END: test_1");
end
endtask
task test_2;
begin
$display("START: test_2");
`assert_equal(dut.state, dut.IDLE, "state should be IDLE");
data = 10'b0101110101;
load = 1;
#2;
load = 0;
#400;
`assert_equal(dut.state, dut.IDLE, "state should be IDLE");
$display("END: test_2");
end
endtask
task test_3;
begin
$display("START: test_3");
`assert_equal(dut.state, dut.IDLE, "state should be IDLE");
data = 10'b0101110101;
load = 1;
#2;
load = 0;
#32;
data = 10'b1010001110;
load = 1;
#2;
load = 0;
#600;
`assert_equal(dut.state, dut.IDLE, "state should be IDLE");
$display("END: test_3");
end
endtask
task dut_reset;
begin
reset = 1;
#2;
reset = 0;
end
endtask
endmodule