?? smc_model.v
字號:
module SMC_model(smc_clk,smc_data, smc_rstn);
input smc_clk ;
inout smc_data ;
input smc_rstn ;
//local signals
parameter IDLE = 0,
RESET = 1,
RESET_WAIT = 2,
RX_START = 3,
RX_PARITY = 4,
RX_WAIT = 5,
TX_START = 6,
TX_PARITY_CHECK = 7,
TX_REPEAT_WAIT = 8,
TX_WAIT = 9,
CLOCK_STOP = 10,
DEACTIVE = 11,
BLOCK_WAIT = 12;
reg [3:0]cur_state, next_state;
reg smc_data_out ;
reg smc_data_en ;
reg [7:0]tx_shifter ;
reg [7:0]rx_shifter ;
wire reset_resp_timeout ;
reg [23:0]bit_cnt ;
wire [3:0]D ;
wire [15:0]fi ;
reg [7:0]di ;
reg [2:0]bit_shift ;
reg [21:0]clk_num ;
reg [21:0]smc_clk_cnt ;
reg smc_bit_en ;
reg smc_half_bit_en ;
reg rx_start ;
reg tx_start ;
reg smc_data_in_d ;
reg data_parity ;
reg smc_rstn_d ;
assign smc_data = (!smc_data_en) ? smc_data_out : 'bZ;
assign smc_data_in = smc_data;
assign D = 4'd1;
assign fi = 'b1010;
always @(D)
begin
case(D)
4'b0001: begin di = 8'b00000001; bit_shift = 0; end
4'b0010: begin di = 8'b00000010; bit_shift = 1; end
4'b0011: begin di = 8'b00000100; bit_shift = 2; end
4'b0100: begin di = 8'b00001000; bit_shift = 3; end
4'b0101: begin di = 8'b00010000; bit_shift = 4; end
4'b0110: begin di = 8'b00100000; bit_shift = 5; end
4'b1010: begin di = 8'b10000010; bit_shift = 1; end
4'b1011: begin di = 8'b10000100; bit_shift = 2; end
4'b1100: begin di = 8'b10001000; bit_shift = 3; end
4'b1101: begin di = 8'b10010000; bit_shift = 4; end
4'b1110: begin di = 8'b10100000; bit_shift = 5; end
4'b1111: begin di = 8'b11000000; bit_shift = 6; end
default: begin di = 8'b00000001; bit_shift = 0; end
endcase
end
//generate F/D
always @(bit_shift or fi or di[7])
begin
if (di[7])
clk_num = (fi << bit_shift);
else
clk_num = (fi >> bit_shift);
end
always @(posedge smc_clk or negedge smc_rstn)
begin
if (!smc_rstn)
smc_clk_cnt <= 1;
else if (rx_start)
smc_clk_cnt <= 1;
else if (smc_clk_cnt == clk_num)
smc_clk_cnt <= 1;
else
smc_clk_cnt <= smc_clk_cnt + 1;
end
always @(posedge smc_clk or negedge smc_rstn)
begin
if (!smc_rstn)
smc_bit_en <= 1'b0;
else if (smc_clk_cnt == clk_num)
smc_bit_en <= 1'b1;
else
smc_bit_en <= 1'b0;
end
always @(posedge smc_clk or negedge smc_rstn)
begin
if (!smc_rstn)
smc_half_bit_en <= 1'b0;
else if (smc_clk_cnt == (clk_num >> 1))
smc_half_bit_en <= 1'b1;
else
smc_half_bit_en <= 1'b0;
end
always @(posedge smc_clk or negedge smc_rstn)
begin
if (!smc_rstn)
begin
rx_start <= 1'b0;
smc_data_in_d <= 1'b1;
end
else begin
smc_data_in_d <= smc_data_in;
if (~smc_data_in & smc_data_in_d & ((cur_state == RX_WAIT) || (cur_state == RESET_WAIT) || (cur_state == IDLE)))
rx_start <= 1'b1;
else
rx_start <= 1'b0;
end
end
reg [15:0]reset_timer;
always @(posedge smc_clk or negedge smc_rstn)
begin
if (!smc_rstn)
reset_timer <= 0;
else if (reset_timer !== 'hffff)
reset_timer <= reset_timer + 1;
end
assign reset_resp_timeout = (reset_timer == 'H20);
always @(posedge smc_clk or negedge smc_rstn)
begin
if (!smc_rstn)
bit_cnt <= 'h0;
else if (rx_start || tx_start)
bit_cnt <= 'h0;
else if (smc_bit_en)
bit_cnt <= bit_cnt + 1;
end
always @(posedge smc_clk or negedge smc_rstn)
begin
if (!smc_rstn)
tx_start <= 1'b0;
else if ((next_state == TX_START) && (cur_state != TX_START))
tx_start <= 1'b1;
else
tx_start <= 1'b0;
end
wire smc_rstn_tmp;
assign #10000 smc_rstn_tmp = smc_rstn;
always @(negedge smc_clk)
smc_rstn_d <= smc_rstn_tmp;
assign trig_reset = ~smc_rstn & smc_rstn_d;
//state machine
initial
cur_state = DEACTIVE;
always @(posedge smc_clk)
cur_state <= next_state;
always @(cur_state or rx_start or trig_reset or reset_resp_timeout or bit_cnt or smc_data_in)
begin
next_state = cur_state;
case(cur_state)
IDLE:
if (rx_start)
next_state = RX_START;
RESET:
if (smc_rstn)
next_state = RESET_WAIT;
RESET_WAIT:
if (reset_resp_timeout)
next_state = TX_START;
RX_START:
if (bit_cnt == 10)
next_state = RX_PARITY;
RX_PARITY:
if (bit_cnt == 12)
next_state = RX_WAIT;
RX_WAIT:
next_state = IDLE;
BLOCK_WAIT:
next_state = IDLE;
TX_START:
if (bit_cnt == 10)
next_state = TX_PARITY_CHECK;
TX_PARITY_CHECK:
if (bit_cnt == 12)
next_state = TX_WAIT;
TX_WAIT:
next_state = IDLE;
endcase
if (trig_reset)
next_state = RESET;
end
always @(posedge smc_clk or negedge smc_rstn)
begin
if (!smc_rstn)
tx_shifter <= 8'b0;
else if ((cur_state == TX_START) && smc_bit_en && (bit_cnt <= 8) && (bit_cnt != 0))
tx_shifter <= {tx_shifter[6:0],1'b0};
else if (cur_state != TX_START)
tx_shifter <= $random;
end
always @(posedge smc_clk or negedge smc_rstn)
begin
if (!smc_rstn)
begin
smc_data_out <= 'b1;
smc_data_en <= 'b1;
end
else if ((cur_state == IDLE) || (cur_state == RESET))
begin
smc_data_en <= 1'b1;
smc_data_en <= 1'b1;
end
else begin
if ((cur_state == RX_PARITY) && smc_half_bit_en)
begin
smc_data_en <= 1'b0; //parity signaling
smc_data_out <= ~data_parity;
if (!smc_data_en)
smc_data_en <= 1'b1;
end
else if ((cur_state == TX_START) && smc_bit_en)
begin
if (bit_cnt == 0)
begin
smc_data_out <= 'b0;
smc_data_en <= 'b0;
end
else if (bit_cnt == 9)
begin
smc_data_out <= data_parity;
smc_data_en <= 'b0;
end
else
begin
smc_data_out <= tx_shifter[7];
smc_data_en <= 'b0;
end
end
else if ((cur_state == TX_WAIT) && smc_bit_en)
begin
smc_data_out <= 'b1;
smc_data_en <= 'b0;
end
else if ((cur_state == TX_PARITY_CHECK) && smc_bit_en)
begin
smc_data_out <= 'b1;
smc_data_en <= 'b0;
end
end
end
always @(posedge smc_clk or negedge smc_rstn)
begin
if (!smc_rstn)
data_parity <= 'b0;
else if (rx_start | tx_start)
data_parity <= 1'b0;
else if (smc_half_bit_en)
begin
if ((cur_state == TX_START) && (bit_cnt != 0) && (bit_cnt <= 8))
data_parity <= data_parity ^ tx_shifter[7];
else if ((cur_state == RX_START) && (bit_cnt != 0) && (bit_cnt <= 8))
data_parity <= data_parity ^ smc_data_in;
end
end
always @(posedge smc_clk or negedge smc_rstn)
begin
if (!smc_rstn)
rx_shifter <= 8'b0;
else if ((cur_state == RX_START) && smc_half_bit_en && (bit_cnt != 0) && (bit_cnt != 9))
rx_shifter <= {rx_shifter[6:0], smc_data_in};
else if (cur_state != RX_START)
rx_shifter <= 'h0;
end
endmodule
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -