/*
|
/*
|
PSS
|
PSS
|
|
|
Copyright (c) 2016 Alexander Antonov <153287@niuitmo.ru>
|
Copyright (c) 2016 Alexander Antonov <153287@niuitmo.ru>
|
All rights reserved.
|
All rights reserved.
|
|
|
Version 0.9
|
Version 0.99
|
|
|
The FreeBSD license
|
The FreeBSD license
|
|
|
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
modification, are permitted provided that the following conditions
|
modification, are permitted provided that the following conditions
|
are met:
|
are met:
|
|
|
1. Redistributions of source code must retain the above copyright
|
1. Redistributions of source code must retain the above copyright
|
notice, this list of conditions and the following disclaimer.
|
notice, this list of conditions and the following disclaimer.
|
2. Redistributions in binary form must reproduce the above
|
2. Redistributions in binary form must reproduce the above
|
copyright notice, this list of conditions and the following
|
copyright notice, this list of conditions and the following
|
disclaimer in the documentation and/or other materials
|
disclaimer in the documentation and/or other materials
|
provided with the distribution.
|
provided with the distribution.
|
|
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
PSS PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
PSS PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
*/
|
*/
|
|
|
|
|
module uart_rx
|
module uart_rx
|
(
|
(
|
input clk_i, rst_i,
|
input clk_i, rst_i,
|
|
|
input rx_i,
|
input rx_i,
|
output reg rx_done_tick_o,
|
output reg rx_done_tick_o,
|
output reg [7:0] dout_bo,
|
output reg [7:0] dout_bo,
|
|
|
output reg locked_o,
|
output reg locked_o,
|
output reg [28:0] bitperiod_o
|
output reg [28:0] bitperiod_o
|
);
|
);
|
|
|
localparam ST_NOSYNC = 4'h0;
|
localparam ST_NOSYNC = 4'h0;
|
localparam ST_NOSYNC_WAIT1_1 = 4'h1;
|
localparam ST_NOSYNC_WAIT1_1 = 4'h1;
|
localparam ST_NOSYNC_WAIT0_2 = 4'h2;
|
localparam ST_NOSYNC_WAIT0_2 = 4'h2;
|
localparam ST_NOSYNC_WAIT1_3 = 4'h3;
|
localparam ST_NOSYNC_WAIT1_3 = 4'h3;
|
localparam ST_NOSYNC_WAIT0_4 = 4'h4;
|
localparam ST_NOSYNC_WAIT0_4 = 4'h4;
|
localparam ST_NOSYNC_WAIT1_5 = 4'h5;
|
localparam ST_NOSYNC_WAIT1_5 = 4'h5;
|
localparam ST_NOSYNC_WAIT0_6 = 4'h6;
|
localparam ST_NOSYNC_WAIT0_6 = 4'h6;
|
localparam ST_NOSYNC_WAIT1_7 = 4'h7;
|
localparam ST_NOSYNC_WAIT1_7 = 4'h7;
|
localparam ST_NOSYNC_WAIT0_8 = 4'h8;
|
localparam ST_NOSYNC_WAIT0_8 = 4'h8;
|
localparam ST_NOSYNC_WAIT_STOP = 4'h9;
|
localparam ST_NOSYNC_WAIT_STOP = 4'h9;
|
localparam ST_SYNC = 4'hA;
|
localparam ST_SYNC = 4'hA;
|
localparam ST_SYNC_WAIT_START = 4'hB;
|
localparam ST_SYNC_WAIT_START = 4'hB;
|
localparam ST_SYNC_RX_DATA = 4'hC;
|
localparam ST_SYNC_RX_DATA = 4'hC;
|
localparam ST_SYNC_WAIT_STOP = 4'hD;
|
localparam ST_SYNC_WAIT_STOP = 4'hD;
|
|
|
reg [4:0] state;
|
reg [4:0] state;
|
reg [31:0] clk_counter;
|
reg [31:0] clk_counter;
|
reg [2:0] bit_counter;
|
reg [2:0] bit_counter;
|
|
|
reg rx_buf;
|
reg rx_buf;
|
always @(posedge clk_i)
|
always @(posedge clk_i)
|
begin
|
begin
|
if (rst_i) rx_buf <= 1'b1;
|
if (rst_i) rx_buf <= 1'b1;
|
else rx_buf <= rx_i;
|
else rx_buf <= rx_i;
|
end
|
end
|
|
|
always @(posedge clk_i)
|
always @(posedge clk_i)
|
begin
|
begin
|
if (rst_i)
|
if (rst_i)
|
begin
|
begin
|
state <= ST_NOSYNC;
|
state <= ST_NOSYNC;
|
clk_counter <= 32'h0;
|
clk_counter <= 32'h0;
|
bit_counter <= 3'h0;
|
bit_counter <= 3'h0;
|
locked_o <= 1'b0;
|
locked_o <= 1'b0;
|
bitperiod_o <= 32'h0;
|
bitperiod_o <= 32'h0;
|
rx_done_tick_o <= 1'b0;
|
rx_done_tick_o <= 1'b0;
|
dout_bo <= 8'h0;
|
dout_bo <= 8'h0;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
|
|
rx_done_tick_o <= 1'b0;
|
rx_done_tick_o <= 1'b0;
|
|
|
case (state)
|
case (state)
|
|
|
ST_NOSYNC:
|
ST_NOSYNC:
|
begin
|
begin
|
if (rx_buf == 1'b0) state <= ST_NOSYNC_WAIT1_1;
|
if (rx_buf == 1'b0) state <= ST_NOSYNC_WAIT1_1;
|
end
|
end
|
|
|
ST_NOSYNC_WAIT1_1:
|
ST_NOSYNC_WAIT1_1:
|
begin
|
begin
|
if (rx_buf == 1'b1) state <= ST_NOSYNC_WAIT0_2;
|
if (rx_buf == 1'b1) state <= ST_NOSYNC_WAIT0_2;
|
end
|
end
|
|
|
ST_NOSYNC_WAIT0_2:
|
ST_NOSYNC_WAIT0_2:
|
begin
|
begin
|
if (rx_buf == 1'b0) state <= ST_NOSYNC_WAIT1_3;
|
if (rx_buf == 1'b0) state <= ST_NOSYNC_WAIT1_3;
|
clk_counter <= clk_counter + 32'h1;
|
clk_counter <= clk_counter + 32'h1;
|
end
|
end
|
|
|
ST_NOSYNC_WAIT1_3:
|
ST_NOSYNC_WAIT1_3:
|
begin
|
begin
|
if (rx_buf == 1'b1) state <= ST_NOSYNC_WAIT0_4;
|
if (rx_buf == 1'b1) state <= ST_NOSYNC_WAIT0_4;
|
clk_counter <= clk_counter + 32'h1;
|
clk_counter <= clk_counter + 32'h1;
|
end
|
end
|
|
|
ST_NOSYNC_WAIT0_4:
|
ST_NOSYNC_WAIT0_4:
|
begin
|
begin
|
if (rx_buf == 1'b0) state <= ST_NOSYNC_WAIT1_5;
|
if (rx_buf == 1'b0) state <= ST_NOSYNC_WAIT1_5;
|
clk_counter <= clk_counter + 32'h1;
|
clk_counter <= clk_counter + 32'h1;
|
end
|
end
|
|
|
ST_NOSYNC_WAIT1_5:
|
ST_NOSYNC_WAIT1_5:
|
begin
|
begin
|
if (rx_buf == 1'b1) state <= ST_NOSYNC_WAIT0_6;
|
if (rx_buf == 1'b1) state <= ST_NOSYNC_WAIT0_6;
|
clk_counter <= clk_counter + 32'h1;
|
clk_counter <= clk_counter + 32'h1;
|
end
|
end
|
|
|
ST_NOSYNC_WAIT0_6:
|
ST_NOSYNC_WAIT0_6:
|
begin
|
begin
|
if (rx_buf == 1'b0) state <= ST_NOSYNC_WAIT1_7;
|
if (rx_buf == 1'b0) state <= ST_NOSYNC_WAIT1_7;
|
clk_counter <= clk_counter + 32'h1;
|
clk_counter <= clk_counter + 32'h1;
|
end
|
end
|
|
|
ST_NOSYNC_WAIT1_7:
|
ST_NOSYNC_WAIT1_7:
|
begin
|
begin
|
if (rx_buf == 1'b1) state <= ST_NOSYNC_WAIT0_8;
|
if (rx_buf == 1'b1) state <= ST_NOSYNC_WAIT0_8;
|
clk_counter <= clk_counter + 32'h1;
|
clk_counter <= clk_counter + 32'h1;
|
end
|
end
|
|
|
ST_NOSYNC_WAIT0_8:
|
ST_NOSYNC_WAIT0_8:
|
begin
|
begin
|
if (rx_buf == 1'b0) state <= ST_NOSYNC_WAIT_STOP;
|
if (rx_buf == 1'b0) state <= ST_NOSYNC_WAIT_STOP;
|
clk_counter <= clk_counter + 32'h1;
|
clk_counter <= clk_counter + 32'h1;
|
end
|
end
|
|
|
ST_NOSYNC_WAIT_STOP:
|
ST_NOSYNC_WAIT_STOP:
|
begin
|
begin
|
if (rx_buf == 1'b1)
|
if (rx_buf == 1'b1)
|
begin
|
begin
|
state <= ST_SYNC;
|
state <= ST_SYNC;
|
locked_o <= 1'b1;
|
locked_o <= 1'b1;
|
bitperiod_o <= clk_counter[31:3]; // clk_counter / 8
|
bitperiod_o <= clk_counter[31:3]; // clk_counter / 8
|
dout_bo <= 32'h55;
|
dout_bo <= 32'h55;
|
rx_done_tick_o <= 1'b1;
|
rx_done_tick_o <= 1'b1;
|
end
|
end
|
clk_counter <= clk_counter + 32'h1;
|
clk_counter <= clk_counter + 32'h1;
|
end
|
end
|
|
|
ST_SYNC:
|
ST_SYNC:
|
begin
|
begin
|
if (rx_buf == 1'b0)
|
if (rx_buf == 1'b0)
|
begin
|
begin
|
state <= ST_SYNC_WAIT_START;
|
state <= ST_SYNC_WAIT_START;
|
clk_counter <= 32'h0;
|
clk_counter <= 32'h0;
|
end
|
end
|
end
|
end
|
|
|
ST_SYNC_WAIT_START:
|
ST_SYNC_WAIT_START:
|
begin
|
begin
|
clk_counter <= clk_counter + 32'h1;
|
clk_counter <= clk_counter + 32'h1;
|
if (clk_counter == {4'h0, bitperiod_o[28:1]})
|
if (clk_counter == {4'h0, bitperiod_o[28:1]})
|
begin
|
begin
|
state <= ST_SYNC_RX_DATA;
|
state <= ST_SYNC_RX_DATA;
|
clk_counter <= 32'h0;
|
clk_counter <= 32'h0;
|
bit_counter <= 3'h0;
|
bit_counter <= 3'h0;
|
end
|
end
|
end
|
end
|
|
|
ST_SYNC_RX_DATA:
|
ST_SYNC_RX_DATA:
|
begin
|
begin
|
clk_counter <= clk_counter + 32'h1;
|
clk_counter <= clk_counter + 32'h1;
|
if (clk_counter == {3'h0, bitperiod_o})
|
if (clk_counter == {3'h0, bitperiod_o})
|
begin
|
begin
|
dout_bo <= {rx_buf, dout_bo[7:1]};
|
dout_bo <= {rx_buf, dout_bo[7:1]};
|
clk_counter <= 32'h0;
|
clk_counter <= 32'h0;
|
bit_counter <= bit_counter + 3'h1;
|
bit_counter <= bit_counter + 3'h1;
|
if (bit_counter == 3'h7)
|
if (bit_counter == 3'h7)
|
begin
|
begin
|
rx_done_tick_o <= 1'b1;
|
rx_done_tick_o <= 1'b1;
|
state <= ST_SYNC_WAIT_STOP;
|
state <= ST_SYNC_WAIT_STOP;
|
end
|
end
|
end
|
end
|
end
|
end
|
|
|
ST_SYNC_WAIT_STOP:
|
ST_SYNC_WAIT_STOP:
|
begin
|
begin
|
if (rx_buf == 1'b1) state <= ST_SYNC;
|
if (rx_buf == 1'b1) state <= ST_SYNC;
|
end
|
end
|
|
|
endcase
|
endcase
|
|
|
end
|
end
|
end
|
end
|
|
|
endmodule
|
endmodule
|
|
|