// ============================================================================
|
// ============================================================================
|
// (C) 2011,2013 Robert Finch
|
// (C) 2011,2013,2015 Robert Finch
|
// All rights reserved.
|
// All rights reserved.
|
// robfinch@<remove>finitron.ca
|
// robfinch@<remove>finitron.ca
|
//
|
//
|
// rtfSimpleUartRx.v
|
// rtfSimpleUartRx.v
|
//
|
//
|
// 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 are met:
|
// modification, are permitted provided that the following conditions are met:
|
// * Redistributions of source code must retain the above copyright
|
// * 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.
|
// * Redistributions in binary form must reproduce the above copyright
|
// * Redistributions in binary form must reproduce the above copyright
|
// notice, this list of conditions and the following disclaimer in the
|
// notice, this list of conditions and the following disclaimer in the
|
// documentation and/or other materials provided with the distribution.
|
// documentation and/or other materials provided with the distribution.
|
// * Neither the name of the <organization> nor the
|
// * Neither the name of the <organization> nor the
|
// names of its contributors may be used to endorse or promote products
|
// names of its contributors may be used to endorse or promote products
|
// derived from this software without specific prior written permission.
|
// derived from this software without specific prior written permission.
|
//
|
//
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
//
|
//
|
// Simple UART receiver core
|
// Simple UART receiver core
|
// Features:
|
// Features:
|
// false start bit detection
|
// false start bit detection
|
// framing error detection
|
// framing error detection
|
// overrun state detection
|
// overrun state detection
|
// resynchronization on every character
|
// resynchronization on every character
|
// fixed format 1 start - 8 data - 1 stop bits
|
// fixed format 1 start - 8 data - 1 stop bits
|
// uses 16x clock rate
|
// uses 16x clock rate
|
//
|
//
|
// This core may be used as a standalone peripheral
|
// This core may be used as a standalone peripheral
|
// on a SoC bus if all that is desired is recieve
|
// on a SoC bus if all that is desired is recieve
|
// capability. It requires a 16x baud rate clock.
|
// capability. It requires a 16x baud rate clock.
|
//
|
//
|
// +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// |WISHBONE Datasheet
|
// |WISHBONE Datasheet
|
// |WISHBONE SoC Architecture Specification, Revision B.3
|
// |WISHBONE SoC Architecture Specification, Revision B.3
|
// |
|
// |
|
// |Description: Specifications:
|
// |Description: Specifications:
|
// +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// |General Description: simple serial UART receiver
|
// |General Description: simple serial UART receiver
|
// +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// |Supported Cycles: SLAVE,READ
|
// |Supported Cycles: SLAVE,READ
|
// | SLAVE,BLOCK READ
|
// | SLAVE,BLOCK READ
|
// +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// |Data port, size: 8 bit
|
// |Data port, size: 8 bit
|
// |Data port, granularity: 8 bit
|
// |Data port, granularity: 8 bit
|
// |Data port, maximum operand size: 8 bit
|
// |Data port, maximum operand size: 8 bit
|
// |Data transfer ordering: Undefined
|
// |Data transfer ordering: Undefined
|
// |Data transfer sequencing: Undefined
|
// |Data transfer sequencing: Undefined
|
// +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// |Clock frequency constraints: none
|
// |Clock frequency constraints: none
|
// +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// |Supported signal list and Signal Name WISHBONE equiv.
|
// |Supported signal list and Signal Name WISHBONE equiv.
|
// |cross reference to equivalent ack_o ACK_O
|
// |cross reference to equivalent ack_o ACK_O
|
// |WISHBONE signals
|
// |WISHBONE signals
|
// | clk_i CLK_I
|
// | clk_i CLK_I
|
// | rst_i RST_I
|
// | rst_i RST_I
|
// | dat_o(7:0) DAT_O()
|
// | dat_o(7:0) DAT_O()
|
// | cyc_i CYC_I
|
// | cyc_i CYC_I
|
// | stb_i STB_I
|
// | stb_i STB_I
|
// | we_i WE_I
|
// | we_i WE_I
|
// |
|
// |
|
// +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// |Special requirements:
|
// |Special requirements:
|
// +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
//
|
//
|
// Ref: Spartan3 -4
|
// Ref: Spartan3 -4
|
// 27 LUTs / 24 slices / 170 MHz
|
// 27 LUTs / 24 slices / 170 MHz
|
//==============================================================================
|
//==============================================================================
|
|
|
`define IDLE 0
|
`define IDLE 0
|
`define CNT 1
|
`define CNT 1
|
|
|
module rtfSimpleUartRx(
|
module rtfSimpleUartRx(
|
// WISHBONE SoC bus interface
|
// WISHBONE SoC bus interface
|
input rst_i, // reset
|
input rst_i, // reset
|
input clk_i, // clock
|
input clk_i, // clock
|
input cyc_i, // cycle is valid
|
input cyc_i, // cycle is valid
|
input stb_i, // strobe
|
input stb_i, // strobe
|
output ack_o, // data is ready
|
output ack_o, // data is ready
|
input we_i, // write (this signal is used to qualify reads)
|
input we_i, // write (this signal is used to qualify reads)
|
output [7:0] dat_o, // data out
|
output [7:0] dat_o, // data out
|
//------------------------
|
//------------------------
|
input cs_i, // chip select
|
input cs_i, // chip select
|
input baud16x_ce, // baud rate clock enable
|
input baud16x_ce, // baud rate clock enable
|
input tri0 baud8x, // switches to mode baudX8
|
input tri0 baud8x, // switches to mode baudX8
|
input clear, // clear reciever
|
input clear, // clear reciever
|
input rxd, // external serial input
|
input rxd, // external serial input
|
output reg data_present, // data present in fifo
|
output reg data_present, // data present in fifo
|
output reg frame_err, // framing error
|
output reg frame_err, // framing error
|
output reg overrun // receiver overrun
|
output reg overrun // receiver overrun
|
);
|
);
|
|
|
//0 - simple sampling at middle of symbol period
|
//0 - simple sampling at middle of symbol period
|
//>0 - sampling of 3 middle ticks of sumbol perion and results as majority
|
//>0 - sampling of 3 middle ticks of sumbol perion and results as majority
|
parameter SamplerStyle = 0;
|
parameter SamplerStyle = 0;
|
|
|
// variables
|
// variables
|
reg [7:0] cnt; // sample bit rate counter
|
reg [7:0] cnt; // sample bit rate counter
|
reg [9:0] rx_data; // working receive data register
|
reg [9:0] rx_data; // working receive data register
|
reg state; // state machine
|
reg state; // state machine
|
reg wf; // buffer write
|
reg wf; // buffer write
|
reg [7:0] dat;
|
reg [7:0] dat;
|
|
|
wire isX8;
|
wire isX8;
|
buf(isX8, baud8x);
|
buf(isX8, baud8x);
|
reg modeX8;
|
reg modeX8;
|
|
|
assign ack_o = cyc_i & stb_i & cs_i;
|
assign ack_o = cyc_i & stb_i & cs_i;
|
assign dat_o = ack_o ? dat : 8'b0;
|
assign dat_o = ack_o ? dat : 8'b0;
|
|
|
// update data register
|
// update data register
|
always @(posedge clk_i)
|
always @(posedge clk_i)
|
if (wf) dat <= rx_data[8:1];
|
if (wf) dat <= rx_data[8:1];
|
|
|
// on a read clear the data present status
|
// on a read clear the data present status
|
// but set the status when the data register
|
// but set the status when the data register
|
// is updated by the receiver
|
// is updated by the receiver
|
always @(posedge clk_i)
|
always @(posedge clk_i)
|
if (rst_i)
|
if (rst_i)
|
data_present <= 0;
|
data_present <= 0;
|
else if (wf)
|
else if (wf)
|
data_present <= 1;
|
data_present <= 1;
|
else if (ack_o & ~we_i) data_present <= 0;
|
else if (ack_o & ~we_i) data_present <= 0;
|
|
|
|
|
// Three stage synchronizer to synchronize incoming data to
|
// Three stage synchronizer to synchronize incoming data to
|
// the local clock (avoids metastability).
|
// the local clock (avoids metastability).
|
reg [5:0] rxdd /* synthesis ramstyle = "logic" */; // synchronizer flops
|
reg [5:0] rxdd /* synthesis ramstyle = "logic" */; // synchronizer flops
|
reg rxdsmp; // majority samples
|
reg rxdsmp; // majority samples
|
reg rdxstart; // for majority style sample solid 3tik-wide sample
|
reg rdxstart; // for majority style sample solid 3tik-wide sample
|
reg [1:0] rxdsum;
|
reg [1:0] rxdsum;
|
always @(posedge clk_i)
|
always @(posedge clk_i)
|
if (baud16x_ce) begin
|
if (baud16x_ce) begin
|
rxdd <= {rxdd[4:0],rxd};
|
rxdd <= {rxdd[4:0],rxd};
|
if (SamplerStyle == 0) begin
|
if (SamplerStyle == 0) begin
|
rxdsmp <= rxdd[3];
|
rxdsmp <= rxdd[3];
|
rdxstart <= rxdd[4]&~rxdd[3];
|
rdxstart <= rxdd[4]&~rxdd[3];
|
end
|
end
|
else begin
|
else begin
|
rxdsum[1] <= rxdsum[0];
|
rxdsum[1] <= rxdsum[0];
|
rxdsum[0] <= {1'b0,rxdd[3]} + {1'b0,rxdd[4]} + {1'b0,rxdd[5]};
|
rxdsum[0] <= {1'b0,rxdd[3]} + {1'b0,rxdd[4]} + {1'b0,rxdd[5]};
|
rxdsmp <= rxdsum[1];
|
rxdsmp <= rxdsum[1];
|
rdxstart <= (rxdsum[0] == 2'b00) & ((rxdsum[1] == 2'b11));
|
rdxstart <= (rxdsum[0] == 2'b00) & ((rxdsum[1] == 2'b11));
|
end
|
end
|
end
|
end
|
|
|
|
|
`define CNT_FRAME (8'h97)
|
`define CNT_FRAME (8'h97)
|
`define CNT_FINISH (8'h9D)
|
`define CNT_FINISH (8'h9D)
|
|
|
always @(posedge clk_i) begin
|
always @(posedge clk_i) begin
|
if (rst_i) begin
|
if (rst_i) begin
|
state <= `IDLE;
|
state <= `IDLE;
|
wf <= 1'b0;
|
wf <= 1'b0;
|
overrun <= 1'b0;
|
overrun <= 1'b0;
|
frame_err <= 1'b0;
|
frame_err <= 1'b0;
|
end
|
end
|
else begin
|
else begin
|
|
|
// Clear write flag
|
// Clear write flag
|
wf <= 1'b0;
|
wf <= 1'b0;
|
|
|
if (clear) begin
|
if (clear) begin
|
wf <= 1'b0;
|
wf <= 1'b0;
|
state <= `IDLE;
|
state <= `IDLE;
|
overrun <= 1'b0;
|
overrun <= 1'b0;
|
frame_err <= 1'b0;
|
frame_err <= 1'b0;
|
end
|
end
|
|
|
else if (baud16x_ce) begin
|
else if (baud16x_ce) begin
|
|
|
case (state)
|
case (state)
|
|
|
// Sit in the idle state until a start bit is
|
// Sit in the idle state until a start bit is
|
// detected.
|
// detected.
|
`IDLE:
|
`IDLE:
|
// look for start bit
|
// look for start bit
|
if (rdxstart)
|
if (rdxstart)
|
state <= `CNT;
|
state <= `CNT;
|
|
|
`CNT:
|
`CNT:
|
begin
|
begin
|
// End of the frame ?
|
// End of the frame ?
|
// - check for framing error
|
// - check for framing error
|
// - write data to read buffer
|
// - write data to read buffer
|
if (cnt==`CNT_FRAME)
|
if (cnt==`CNT_FRAME)
|
begin
|
begin
|
frame_err <= ~rxdsmp;
|
frame_err <= ~rxdsmp;
|
overrun <= data_present;
|
overrun <= data_present;
|
if (!data_present)
|
if (!data_present)
|
wf <= 1'b1;
|
wf <= 1'b1;
|
state <= `IDLE;
|
state <= `IDLE;
|
end
|
end
|
// Switch back to the idle state a little
|
// Switch back to the idle state a little
|
// bit too soon.
|
// bit too soon.
|
//if (cnt==`CNT_FINISH) begin
|
//if (cnt==`CNT_FINISH) begin
|
// state <= `IDLE;
|
// state <= `IDLE;
|
//end
|
//end
|
|
|
// On start bit check make sure the start
|
// On start bit check make sure the start
|
// bit is low, otherwise go back to the
|
// bit is low, otherwise go back to the
|
// idle state because it's a false start.
|
// idle state because it's a false start.
|
if (cnt==8'h07 && rxdsmp)
|
if (cnt==8'h07 && rxdsmp)
|
state <= `IDLE;
|
state <= `IDLE;
|
|
|
if (cnt[3:0]==4'h7)
|
if (cnt[3:0]==4'h7)
|
rx_data <= {rxdsmp,rx_data[9:1]};
|
rx_data <= {rxdsmp,rx_data[9:1]};
|
end
|
end
|
|
|
endcase
|
endcase
|
end
|
end
|
end
|
end
|
end
|
end
|
|
|
|
|
// bit rate counter
|
// bit rate counter
|
always @(posedge clk_i)
|
always @(posedge clk_i)
|
if (baud16x_ce) begin
|
if (baud16x_ce) begin
|
if (state == `IDLE) begin
|
if (state == `IDLE) begin
|
cnt <= modeX8;
|
cnt <= modeX8;
|
modeX8 <= isX8;
|
modeX8 <= isX8;
|
end
|
end
|
else begin
|
else begin
|
cnt[7:1] <= cnt[7:1] + cnt[0];
|
cnt[7:1] <= cnt[7:1] + cnt[0];
|
cnt[0] <= ~cnt[0] | (modeX8);
|
cnt[0] <= ~cnt[0] | (modeX8);
|
end
|
end
|
end
|
end
|
|
|
endmodule
|
endmodule
|
|
|
|
|