📄 ms_core.v
字号:
//if(arbitration_lost) //if arbitration lost then go to idle state releasing buses.remove this because its a //scl_main_state<=scl_main_idle; //software problem if even after arb_lost it is giving wr/rd then it has to go to respective state. if(detect_stop) begin //Go to idle state if there is stop command scl_main_state<=scl_main_idle; sm_stop_sig<=1'b0; end else if(detect_start) begin scl_main_state<=scl_address_shift; sm_stop_sig<=1'b0; end //else if(!sda_in) //If ack has been received then,check for slave/master else if(master_slave) begin //if master then set the direction for master to either transmit if(!master_rw) //or receive the data. scl_main_state<=scl_rx_data; else scl_main_state<=scl_tx_data; //Ravi: if no detect_stop then check if master send to state depending upon end //tx/rx bit of control register. else begin //If slave then check if received address has matched //if(addr_match) //begin //if address matches then set the direction of communication based if(add_reg[0]) //last bit of shift register of address cycle. scl_main_state<=scl_tx_data; else scl_main_state<=scl_rx_data; end //else //scl_main_state<=scl_main_idle; //end //else //begin // scl_main_state<=scl_main_idle; //If no ack received go to idle state. //if(master_slave) // sm_stop_sig<=1'b1; //end scl_rx_data: if(bit_cnt == 8'b0000_0111) scl_main_state<=scl_send_ack; else if(detect_stop) begin scl_main_state<=scl_main_idle; sm_stop_sig<=1'b0; end else if(detect_start) begin scl_main_state<=scl_address_shift; sm_stop_sig<=1'b0; end scl_tx_data: if(bit_cnt == 8'b0000_0111) scl_main_state<=scl_wait_ack; else if(detect_stop) begin scl_main_state<=scl_main_idle; sm_stop_sig<=1'b0; end else if(detect_start) begin scl_main_state<=scl_address_shift; sm_stop_sig<=1'b0; end scl_send_ack: if(detect_stop) begin scl_main_state<=scl_main_idle; sm_stop_sig<=1'b0; end else scl_main_state<=scl_rx_data; scl_wait_ack: //Ravi: Even in this state machine will goto Tx state,if no ack or arb_lost has occur //if(arbitration_lost) //This is software part to program the control register so that it will generate stop //scl_main_state<=scl_main_idle; //and will go in idle state.So removing all clauses except detect stop. if(detect_stop) begin scl_main_state<=scl_main_idle; sm_stop_sig<=1'b0; end else scl_main_state<=scl_tx_data; //else //begin //if(master_slave) //sm_stop_sig<=1'b1; //scl_main_state<=scl_main_idle; //end endcaseendend//Start and stop detect process//////////////////////////////always@(sda_in or scl_main_state)begin if(rst || h_rst) detect_start_sig<=1'b0; else if(!sda_in && scl_in) detect_start_sig<=1'b1; else if(scl_address_shift) detect_start_sig<=1'b0; else detect_start_sig<=1'b0;endalways@(posedge sda_in or posedge detect_start)begin if(rst || h_rst) detect_stop_sig<=1'b0; else if(detect_start) detect_stop_sig<=1'b0; else if(scl_in) detect_stop_sig<=1'b1; //else if(detect_start) //detect_stop_sig<=1'b0; else detect_stop_sig<=1'b0;end//generate a delay version of byte_trans signal//This will be used for detecting falling edge of byte_transalways@(posedge clk or posedge rst or posedge h_rst)begin if(rst || h_rst) byte_trans_delay_sig <= 1'b0; else begin byte_trans_delay_sig <= byte_trans; byte_trans_fall_sig <= byte_trans_delay && !byte_trans; endend //Processor status bits///////byte_trans bit//This indicate data is being transferred,This bit will be one only after all 8 bits has//been tranferred.i.e on rising pulse of SCL in ack cycle.always@(negedge scl_in or posedge rst or posedge halt_rst or posedge core_rst or posedge h_rst)begin if(rst || h_rst) byte_trans_sig<=1'b0; else if(halt_rst) byte_trans_sig <= 1'b0; else if(bit_cnt == 8'b0000_1000) byte_trans_sig<=1'b1; else if(halt_rst || core_rst) // after core_rst negate byte_trans bit byte_trans_sig<=1'b0;end//bus_busy//This indicates that communication is in progress and bus in not free.//This bit will be set on detection of start and will be cleared on STOPalways@(posedge clk or posedge rst or posedge h_rst)begin if(rst || h_rst) bb_sig<=1'b0; else begin if(detect_start) bb_sig<=1'b1; if(detect_stop || core_rst) bb_sig<=1'b0; endend//slave_addressed bit//This indicates that slave has been addressed,and after sending ack//core will switch to slave mode.//This bit will be set if adds matched in add ack state.always@(posedge clk or posedge rst or posedge h_rst)begin if(rst) //Removing h_rst slave_addressed_sig<=1'b0; //else if(scl_main_state == scl_ack_address) else if(byte_trans) slave_addressed_sig<=addr_match; else slave_addressed_sig<=slave_addressed; //slave_addressed_sig<= 1'b0;end//set address match bit if address reg matches with shift register output/*always@(negedge scl or posedge rst)begin if(rst) addr_match_sig<=1'b0; else if( slave_add[7:1] == add_reg[7:1]) addr_match_sig <=1'b1; else addr_match_sig<=1'b0;end*/assign addr_match = slave_add[7:1] == add_reg[7:1]? 1'b1:1'b0;assign add_reg_ld = 1'b0;//Slave read write//This bit indicates slave has been addressed,this indicates//read or write bit sent by processor.always@(posedge clk or posedge rst or posedge h_rst)begin if(rst || h_rst) slave_rw_sig<=1'b0; else if(scl_main_state == scl_ack_address) slave_rw_sig<=add_reg[0];end//interrupt pending//This will cause an interrupt to processor if interrupt enable is set//This bit will be set in following circumstances://1):Byte transfer has been completed.//2):Arbitration lost.//3):slave has been addressed and and bytes have been transferred.//4):Time out condition has been reached.//5):Repeated start condition.//Only processor can clear the interrupt.always@(posedge clk or posedge rst or posedge h_rst)begin if(rst || h_rst) inter_sig<=1'b0; else begin //if(interrupt_rst) //inter_sig<=1'b0; if(inter_rst) inter_sig<=1'b0; //in below else if condition anding byte_trans with master_slave also removing add_reg[] condition in next clause else if((byte_trans && master_slave) || arbitration_lost || (slave_addressed && !master_slave && byte_trans) || rep_start) inter_sig<=1'b1; //else //interrupt need to get cleared by processor,so do not reset in else condition //inter_sig<=1'b0; endend//generate delay version of detect_stopalways@(posedge clk or posedge rst or posedge h_rst)beginif(rst || h_rst)d_detect_stop_sig <= 1'b0;elsebegind1_detect_stop_sig <= detect_stop;d_detect_stop_sig <= d1_detect_stop_sig;endendalways@(posedge clk or posedge rst or posedge h_rst)begin if(rst || h_rst) halt_sig <= 1'b0; else begin if(halt_rst) halt_sig<=1'b0; else if(byte_trans && master_slave) halt_sig<=1'b1; endend//acknoweldege recieve//This bit indicates the data on SDA line during ack cycle.always@(posedge clk or posedge rst or posedge h_rst)begin if(rst || h_rst) ack_rec_sig<=1'b0; else if((scl_main_state == scl_wait_ack) || (scl_main_state == scl_ack_address) || (scl_main_state == scl_send_ack)) ack_rec_sig<=sda_in;end//Setting control bits of shift registers and counters////////////////////////////////////////////////////////Address shift register will just receive the data after start //condition detection.It wont be get loaded.While data shift register//will receive as well as transmit the data.//address shift register enable bitalways@(posedge clk or posedge rst or posedge h_rst)begin if(rst || h_rst) add_reg_enable_sig<=1'b0; else if(detect_start || scl_main_state == scl_address_shift) add_reg_enable_sig<=1'b1; else add_reg_enable_sig<=1'b0;end//Data shift register.//This register will be enabled every time when it is either transmitting or receiving the data. always @(posedge clk or posedge rst or posedge h_rst) begin if (rst || h_rst) begin data_reg_en_sig <= 1'b0; data_reg_ld_sig <= 1'b0; end else begin if (((master_slave && scl_main_state == scl_address_shift) || (scl_main_state == scl_rx_data) || (scl_main_state == scl_tx_data))) data_reg_en_sig <= 1'b1; else data_reg_en_sig <= 1'b0; /*if ((master_slave && scl_main_state == scl_idle) || (scl_main_state == scl_wait_ack) || (scl_main_state == scl_ack_address && !add_reg[0] && !master_slave) || (scl_main_state == scl_ack_address && master_rw && master_slave))*/ if(((scl_main_state == scl_main_idle) || byte_trans) && data_en) data_reg_ld_sig <= 1'b1; else data_reg_ld_sig <= 1'b0; end end//logic for generating control bits for bit counter////////////////////////////////////////////////////////////////////////////////////////////////assign bit_cnt_enable = ((scl_main_state == scl_address_shift) || (scl_main_state == scl_rx_data) || (scl_main_state == scl_tx_data));assign bit_cnt_rst = ((scl_main_state == scl_main_idle) || (scl_main_state == scl_send_ack) || (scl_main_state == scl_wait_ack) || (scl_main_state == scl_ack_address));///////////////////////////////////////////////////////////////////////////////////////////////implementation of timer counteralways@(posedge clk or posedge rst or posedge h_rst)begin if(rst || h_rst) time_cnt<=8'b0000_0000; else if(!scl_in) time_cnt<=time_cnt + 1'b1; else time_cnt<=8'b0000_0000;endalways@(posedge clk or posedge rst or posedge h_rst)begin if(rst || h_rst) begin core_rst_sig<=1'b0; time_out_sig<=1'b0; end else if((time_cnt == time_out_reg) & bb) begin core_rst_sig <= 1'b1; time_out_sig <= 1'b1; end /*else if((time_cnt == time_out_reg) && (scl_state == scl_idle)) begin core_rst_sig <= 1'b0; time_out_sig <= 1'b1; end*/ else begin core_rst_sig <= 1'b0; time_out_sig <= 1'b0; end end//Process for assigning Master and slave SDA.always@(posedge clk or posedge rst or posedge h_rst)begin if(rst || h_rst) master_sda_sig<=1'b1; else if((scl_main_state == scl_address_shift) || (scl_main_state == scl_tx_data)) master_sda_sig<=serial_out; else if(scl_main_state == scl_send_ack) master_sda_sig<=ack; else master_sda_sig<=1'b1;endalways@(posedge clk or posedge rst or posedge h_rst)begin if(rst || h_rst) slave_sda_sig<=1'b1; else if(scl_main_state == scl_tx_data) slave_sda_sig<=serial_out; else if((addr_match && (scl_main_state == scl_ack_address)) || (scl_main_state == scl_send_ack)) slave_sda_sig<=ack; else slave_sda_sig<=1'b1;end//assigning SCL and SDA lines in output conditions.assign scl_oe = master_slave ? scl_out : 1'b1;assign sda_sig = (((master_slave == 1'b1 && sda_out == 1'b0) || (master_slave == 1'b0 && slave_sda == 1'b0) || stop_scl) ? 1'b1 : 1'b0);assign sda_oe = (sda_sig ?1'b0 : 1'b1);//Presenting data on data_register which is for processoralways@(posedge clk or posedge rst or posedge h_rst)begin if(rst || h_rst) i2c_up<=8'b00000000; else if(scl_main_state == scl_send_ack) i2c_up<=shift_reg; else i2c_up<=i2c_up;end//This process will set arbitration lost signal////////////////////////////////////////////// // This process checks the master's outgoing SDA with the incoming SDA to determine // if control of the bus has been lost. SDA is checked only when SCL is high // and during the states IDLE, ADD_SHIFT, and TX_DATA to insure that START and STOP // conditions are not set when the bus is busy. Note that this is only done when Master. always @( posedge (clk) or posedge (rst) or posedge (h_rst) ) begin if (rst || h_rst) begin arbitration_lost_sig <= 1'b0; end else begin if (scl_main_state == scl_idle) begin arbitration_lost_sig <= 1'b0; end else if ((master_slave)) // only need to check arbitration in master mode // check for SCL high before comparing data if ((scl_in && scl_oe && (scl_main_state == scl_address_shift || scl_main_state == scl_tx_data || scl_main_state == scl_idle))) // when master, will check bus in all states except ACK_ADDR and WAIT_ACK // this will insure that arb_lost is set if a start or stop condition // is set at the wrong time //if(sda_in == 1'b0 && sda_oe == 1'b1) || (detect_stop if (sda_in == 1'b0 && sda_oe == 1'b1) begin arbitration_lost_sig <= 1'b1; end else begin arbitration_lost_sig <= 1'b0; end else begin arbitration_lost_sig <= arbitration_lost; end end end//setting the arbitration lost bit of status register//////////////////////////////////////////////////////this bit will be set when: //arbiration has lost. //core is in master mode and a generate strat condition has detected while bus is busy //or a stop conditioin has been detected when not requested //or a repeate start has been detected when in slave mode.always@(posedge clk or posedge rst or posedge core_rst or posedge h_rst)begin if(rst || h_rst) arb_lost_sig<=1'b0; else begin if(arb_rst) arb_lost_sig<=1'b0; else if(master_slave) begin if((arbitration_lost)||(bus_busy && gen_start)) arb_lost_sig<=1'b1; end else if(rep_start) arb_lost_sig<=1'b1; //else if(core_rst && master_slave) //arb_lost_sig<=1'b0; else arb_lost_sig<=1'b0; endendalways@(posedge clk or posedge rst or posedge h_rst)beginif(rst || h_rst) rep_start_sig<=1'b0;else if(scl_main_state == scl_address_shift || scl_main_state == scl_ack_address || scl_main_state == scl_send_ack || scl_main_state == scl_wait_ack) rep_start_sig<=1'b0;else rep_start_sig<=rep_start;end endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -