108 lines
1.8 KiB
Systemverilog
108 lines
1.8 KiB
Systemverilog
module tx #(parameter CLK_FREQUENCY = 100000000, BAUD_RATE = 19200)(
|
|
input wire logic clk, send, odd,
|
|
input wire logic[7:0] din,
|
|
output logic busy, tx_out,
|
|
output logic[4:0] state
|
|
);
|
|
logic EnableTimer, ResetTimer, LastCycle, LastBit, NextBit, ResetCounter,
|
|
Shift, Load, ParityBit;
|
|
localparam MAX_COUNT = CLK_FREQUENCY / BAUD_RATE;
|
|
function integer clogb2;
|
|
input [31:0] value;
|
|
begin
|
|
value = value - 1;
|
|
for (clogb2 = 0; value > 0; clogb2 = clogb2 + 1) begin
|
|
value = value >> 1;
|
|
end
|
|
end
|
|
endfunction
|
|
localparam NUM_BITS = clogb2(MAX_COUNT);
|
|
logic[NUM_BITS - 1:0] count = 0;
|
|
|
|
always_ff@ (posedge clk)
|
|
begin
|
|
if(ResetTimer || count == MAX_COUNT)
|
|
count <= 0;
|
|
else if(EnableTimer)
|
|
count <= count + 1;
|
|
end
|
|
assign LastCycle = (count == MAX_COUNT) ? 1'b1:1'b0;
|
|
|
|
assign ParityBit = ((^din)^odd);
|
|
|
|
logic[3:0] countBit = 0;
|
|
always_ff @(posedge clk)
|
|
begin
|
|
if(NextBit)
|
|
countBit <= countBit + 1;
|
|
else if(ResetCounter == 1'b1 || countBit == 4'd10)
|
|
countBit <= 0;
|
|
end
|
|
assign LastBit = (countBit == 4'b1001) ? 1'b1:1'b0;
|
|
|
|
logic[9:0] shift = 10'b1111111111;
|
|
always_ff @(posedge clk)
|
|
begin
|
|
if(Load)
|
|
shift <= {ParityBit, din, 1'b0};
|
|
else if(Shift)
|
|
shift <= {1'b1, shift[9:1]};
|
|
end
|
|
assign tx_out = shift[0];
|
|
|
|
localparam Id = 5'b00001;
|
|
localparam Lo = 5'b00010;
|
|
localparam Co = 5'b00100;
|
|
localparam Sh = 5'b01000;
|
|
localparam Wa = 5'b10000;
|
|
|
|
logic [4:0] ns, cs=Id;
|
|
assign state = cs;
|
|
always_comb
|
|
begin
|
|
ns = cs;
|
|
Load = 0;
|
|
busy = 0;
|
|
ResetCounter = 0;
|
|
ResetTimer = 0;
|
|
Shift = 0;
|
|
ResetTimer = 0;
|
|
NextBit = 0;
|
|
EnableTimer =0;
|
|
case(cs)
|
|
Id:
|
|
if(send)
|
|
ns = Lo;
|
|
Lo:
|
|
begin
|
|
Load = 1;
|
|
busy = 1;
|
|
ResetCounter = 1;
|
|
ResetTimer = 1;
|
|
ns = Co;
|
|
end
|
|
Co:
|
|
begin
|
|
busy = 1;
|
|
EnableTimer = 1;
|
|
if(LastCycle)
|
|
ns = Sh;
|
|
end
|
|
Sh:begin
|
|
Shift = 1;
|
|
ResetTimer = 1;
|
|
NextBit = 1;
|
|
busy = 1;
|
|
if(~LastBit)
|
|
ns = Co;
|
|
else
|
|
ns = Wa;
|
|
end
|
|
Wa:
|
|
if(~send)
|
|
ns = Id;
|
|
endcase
|
|
end
|
|
always_ff @(posedge clk)
|
|
cs <= ns;
|
|
endmodule |