314 lines
7.8 KiB
Coq
314 lines
7.8 KiB
Coq
|
/*Copyright 2020-2021 T-Head Semiconductor Co., Ltd.
|
||
|
|
||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
you may not use this file except in compliance with the License.
|
||
|
You may obtain a copy of the License at
|
||
|
|
||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||
|
|
||
|
Unless required by applicable law or agreed to in writing, software
|
||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
See the License for the specific language governing permissions and
|
||
|
limitations under the License.
|
||
|
*/
|
||
|
|
||
|
|
||
|
// &ModuleBeg; @22
|
||
|
module uart_receive(
|
||
|
ctrl_receive_data_length,
|
||
|
ctrl_receive_parity_bit,
|
||
|
ctrl_receive_parity_en,
|
||
|
ctrl_receive_stop_length,
|
||
|
ctrl_trans_parity_en,
|
||
|
receive_clk_en,
|
||
|
receive_ctrl_busy,
|
||
|
receive_ctrl_fe,
|
||
|
receive_ctrl_pe,
|
||
|
receive_ctrl_rdata,
|
||
|
receive_ctrl_redata_over,
|
||
|
rst_b,
|
||
|
s_in,
|
||
|
sys_clk
|
||
|
);
|
||
|
|
||
|
// &Ports; @23
|
||
|
input [1:0] ctrl_receive_data_length;
|
||
|
input ctrl_receive_parity_bit;
|
||
|
input ctrl_receive_parity_en;
|
||
|
input ctrl_receive_stop_length;
|
||
|
input ctrl_trans_parity_en;
|
||
|
input receive_clk_en;
|
||
|
input rst_b;
|
||
|
input s_in;
|
||
|
input sys_clk;
|
||
|
output receive_ctrl_busy;
|
||
|
output receive_ctrl_fe;
|
||
|
output receive_ctrl_pe;
|
||
|
output [7:0] receive_ctrl_rdata;
|
||
|
output receive_ctrl_redata_over;
|
||
|
|
||
|
// &Regs; @24
|
||
|
reg [3:0] counter;
|
||
|
reg [5:0] cur_state;
|
||
|
reg [2:0] da_conter;
|
||
|
reg di_reg1;
|
||
|
reg di_reg2;
|
||
|
reg fram_error;
|
||
|
reg [5:0] next_state;
|
||
|
reg parity_cout;
|
||
|
reg [7:0] receive_shift_reg;
|
||
|
reg sync1;
|
||
|
reg sync2;
|
||
|
|
||
|
// &Wires; @25
|
||
|
wire cont_16;
|
||
|
wire cont_8;
|
||
|
wire [1:0] ctrl_receive_data_length;
|
||
|
wire ctrl_receive_parity_bit;
|
||
|
wire ctrl_receive_parity_en;
|
||
|
wire ctrl_receive_stop_length;
|
||
|
wire ctrl_trans_parity_en;
|
||
|
wire data_over;
|
||
|
wire di_rx_in;
|
||
|
wire receive_clk_en;
|
||
|
wire receive_ctrl_busy;
|
||
|
wire receive_ctrl_fe;
|
||
|
wire receive_ctrl_pe;
|
||
|
wire [7:0] receive_ctrl_rdata;
|
||
|
wire receive_ctrl_redata_over;
|
||
|
wire rst_b;
|
||
|
wire rx_in;
|
||
|
wire s_in;
|
||
|
wire stop_over;
|
||
|
wire sys_clk;
|
||
|
|
||
|
|
||
|
parameter IDLE = 6'b000001,
|
||
|
START = 6'b000010,
|
||
|
DATA = 6'b000100,
|
||
|
PARITY = 6'b001000,
|
||
|
STOP = 6'b010000,
|
||
|
CLECT_SIG = 6'b100000;
|
||
|
|
||
|
always@(posedge sys_clk or negedge rst_b)
|
||
|
begin
|
||
|
if(!rst_b)
|
||
|
cur_state[5:0] <= IDLE;
|
||
|
else if(receive_clk_en)
|
||
|
cur_state[5:0] <= next_state[5:0];
|
||
|
end
|
||
|
|
||
|
//////////////////////////////////////////////////////////
|
||
|
////////////// midified by huawm, 2016-2-26 //////////////
|
||
|
//////////////////////////////////////////////////////////
|
||
|
always @(posedge sys_clk or negedge rst_b)
|
||
|
begin
|
||
|
if(rst_b == 1'b0)
|
||
|
begin
|
||
|
sync1 <= 1'b1;
|
||
|
sync2 <= 1'b1;
|
||
|
end
|
||
|
else
|
||
|
begin
|
||
|
sync1 <= s_in;
|
||
|
sync2 <= sync1;
|
||
|
end
|
||
|
end
|
||
|
assign rx_in = sync2;
|
||
|
|
||
|
//-------------------------------------------------------
|
||
|
// data integrity, the best two out of three samples will
|
||
|
// give the resulting serial input that will be passed to
|
||
|
// the RX FSM
|
||
|
// ------------------------------------------------------
|
||
|
always @(posedge sys_clk or negedge rst_b)
|
||
|
begin
|
||
|
if(rst_b == 1'b0)
|
||
|
begin
|
||
|
di_reg1 <= 1'b1;
|
||
|
di_reg2 <= 1'b1;
|
||
|
end
|
||
|
else if(receive_clk_en)
|
||
|
begin
|
||
|
di_reg1 <= rx_in;
|
||
|
di_reg2 <= di_reg1;
|
||
|
end
|
||
|
end
|
||
|
assign di_rx_in = (rx_in & di_reg1) | (rx_in & di_reg2) | (di_reg1 & di_reg2);
|
||
|
|
||
|
///////////////////////////////////////////////////////
|
||
|
|
||
|
// &CombBeg; @82
|
||
|
always @( di_rx_in
|
||
|
or stop_over
|
||
|
or cur_state[5:0]
|
||
|
or cont_8
|
||
|
or cont_16
|
||
|
or data_over
|
||
|
or ctrl_trans_parity_en)
|
||
|
begin
|
||
|
next_state[5:0] = IDLE;
|
||
|
case(cur_state[5:0])
|
||
|
IDLE:
|
||
|
begin
|
||
|
if(!di_rx_in)
|
||
|
next_state[5:0] = START;
|
||
|
end
|
||
|
START:
|
||
|
begin
|
||
|
if(cont_8)
|
||
|
begin
|
||
|
if(!di_rx_in)
|
||
|
next_state[5:0] = DATA;
|
||
|
end
|
||
|
else
|
||
|
next_state[5:0] = START;
|
||
|
end
|
||
|
DATA:
|
||
|
begin
|
||
|
if(cont_16 && data_over)
|
||
|
next_state[5:0] = ctrl_trans_parity_en ? PARITY : STOP;
|
||
|
else
|
||
|
next_state[5:0] = DATA;
|
||
|
end
|
||
|
PARITY:
|
||
|
begin
|
||
|
if(cont_16)
|
||
|
next_state[5:0] = STOP;
|
||
|
else
|
||
|
next_state[5:0] = PARITY;
|
||
|
end
|
||
|
STOP:
|
||
|
begin
|
||
|
if(cont_16 && stop_over)
|
||
|
begin
|
||
|
next_state[5:0] = CLECT_SIG;
|
||
|
end
|
||
|
else
|
||
|
next_state[5:0] = STOP;
|
||
|
end
|
||
|
CLECT_SIG:
|
||
|
next_state[5:0] = IDLE;
|
||
|
default: next_state[5:0] = IDLE;
|
||
|
endcase
|
||
|
// &CombEnd; @127
|
||
|
end
|
||
|
|
||
|
|
||
|
// the clock counter
|
||
|
always@(posedge sys_clk or negedge rst_b)
|
||
|
begin
|
||
|
if(!rst_b)
|
||
|
counter[3:0] <= 4'b0;
|
||
|
else if(receive_clk_en)
|
||
|
begin
|
||
|
if( (cur_state[0]) || ((cur_state[1]) && cont_8))
|
||
|
counter[3:0] <= 4'b0;
|
||
|
else
|
||
|
counter[3:0] <= counter[3:0] + 1;
|
||
|
end
|
||
|
end
|
||
|
|
||
|
assign cont_8 = (counter[3:0] == 4'b0111);
|
||
|
assign cont_16 = (counter[3:0] == 4'b1111);
|
||
|
|
||
|
|
||
|
//the data and the stop bit counter
|
||
|
always@(posedge sys_clk or negedge rst_b)
|
||
|
begin
|
||
|
if(!rst_b)
|
||
|
da_conter[2:0] <= 2'b0;
|
||
|
else if(receive_clk_en)
|
||
|
begin
|
||
|
if((data_over || stop_over)&& cont_16)
|
||
|
da_conter[2:0] <= 2'b0;
|
||
|
else if(((cur_state[2]) ||(cur_state[4])) && cont_16)
|
||
|
da_conter[2:0] <= da_conter[2:0] + 1'b1;
|
||
|
end
|
||
|
end
|
||
|
|
||
|
assign data_over = (da_conter[2:0] == {1'b1,ctrl_receive_data_length[1:0]});
|
||
|
assign stop_over = (cur_state[4]) && (da_conter[2:0] == {2'b0,ctrl_receive_stop_length});
|
||
|
|
||
|
//==============================================================
|
||
|
// generate the output s_out signal
|
||
|
//==============================================================
|
||
|
always@(posedge sys_clk or negedge rst_b)
|
||
|
begin
|
||
|
if( !rst_b )
|
||
|
receive_shift_reg[7:0] <= 8'b0;
|
||
|
else if(receive_clk_en)
|
||
|
begin
|
||
|
if((cur_state[2])&& cont_16)
|
||
|
receive_shift_reg[7:0] <= {di_rx_in,receive_shift_reg[7:1]};
|
||
|
else if((cur_state[0]))
|
||
|
receive_shift_reg[7:0] <= 8'b0;
|
||
|
end
|
||
|
end
|
||
|
|
||
|
assign receive_ctrl_rdata[7:0] = receive_shift_reg[7:0];
|
||
|
|
||
|
|
||
|
|
||
|
// generate the receive busy signal
|
||
|
assign receive_ctrl_busy = ~(cur_state[0]);
|
||
|
|
||
|
//receive the parity and check the parity
|
||
|
always@(posedge sys_clk or negedge rst_b)
|
||
|
begin
|
||
|
if( !rst_b )
|
||
|
parity_cout <= 1'b0;
|
||
|
else if(receive_clk_en)
|
||
|
begin
|
||
|
if((cur_state[2]) || (cur_state[3]))
|
||
|
begin
|
||
|
if(cont_16)
|
||
|
parity_cout <= parity_cout ^ di_rx_in;
|
||
|
else
|
||
|
parity_cout <= parity_cout;
|
||
|
end
|
||
|
else if(cur_state[4] || cur_state[5])
|
||
|
parity_cout <= parity_cout;
|
||
|
else
|
||
|
parity_cout <= 1'b0;
|
||
|
end
|
||
|
end
|
||
|
|
||
|
|
||
|
//generate the fram error signal
|
||
|
always@(posedge sys_clk or negedge rst_b)
|
||
|
begin
|
||
|
if( !rst_b )
|
||
|
fram_error <= 1'b0;
|
||
|
else if((cur_state[4]))
|
||
|
begin
|
||
|
if(fram_error == 1'b1)
|
||
|
fram_error <= fram_error;
|
||
|
else if(cont_16)
|
||
|
fram_error <= ~di_rx_in;
|
||
|
else
|
||
|
fram_error <= fram_error;
|
||
|
end
|
||
|
else if(cur_state[5])
|
||
|
fram_error <= fram_error;
|
||
|
else
|
||
|
fram_error <= 1'b0;
|
||
|
end
|
||
|
|
||
|
|
||
|
// the parity error bit
|
||
|
assign receive_ctrl_pe = (~(parity_cout ^ ctrl_receive_parity_bit)) && ctrl_receive_parity_en && (cur_state[5]);
|
||
|
//the frame error bit
|
||
|
assign receive_ctrl_fe = fram_error && (cur_state[5]);
|
||
|
//generate the data receive control signal
|
||
|
// &Force("output","receive_ctrl_pe"); @236
|
||
|
|
||
|
assign receive_ctrl_redata_over = cur_state[5] && !fram_error && !receive_ctrl_pe;
|
||
|
|
||
|
|
||
|
// &ModuleEnd; @241
|
||
|
endmodule
|
||
|
|
||
|
|