abstractaccelerator/opene906/smart_run/logical/uart/uart_receive.v

314 lines
7.8 KiB
Verilog

/*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