Subversion Repositories i2c_master_slave_core
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 5 to Rev 6
- ↔ Reverse comparison
Rev 5 → Rev 6
/i2c_master_slave_core/trunk/i2c_master_slave_core/doc/i2c_spec.pdf
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
i2c_master_slave_core/trunk/i2c_master_slave_core/doc/i2c_spec.pdf
Property changes :
Added: svn:mime-type
+ application/octet-stream
/i2c_master_slave_core/trunk/i2c_master_slave_core/doc/i2c_spec.doc
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
i2c_master_slave_core/trunk/i2c_master_slave_core/doc/i2c_spec.doc
Property changes :
Added: svn:mime-type
+ application/octet-stream
/i2c_master_slave_core/trunk/i2c_master_slave_core/verilog/rtl/shift.v
New file
0,0 → 1,52
////////////////////////////Shift.v///////////////////////////////////////////////////////////////////// |
// // |
//Design Engineer: Ravi Gupta // |
//Company Name : Toomuch Semiconductor |
//Email : ravi1.gupta@toomuchsemi.com // |
// // |
//Purpose : Used for shifting address and data in both transmit and recieve mode // |
//created : 22-11-07 // |
// // |
//////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
/*// synopsys translate_off |
`include "oc8051_timescale.v" |
// synopsys translate_on |
|
`include "oc8051_defines.v"*/ |
|
|
module shift(clk,asyn_rst,load,shift_en,serial_in,data_in,serial_out,data_out); |
|
input clk,asyn_rst,load,shift_en,serial_in; |
input [7:0]data_in; |
|
output serial_out; |
output [7:0]data_out; |
|
reg [7:0]data; |
|
always@(posedge clk or posedge asyn_rst or posedge load) |
begin |
if(asyn_rst) |
data<=8'h0; //clear the data register upon asynchronous reset. |
|
else if(load) |
data<=data_in; //Load the internal register upon insertion of load bit. |
|
else if(shift_en) |
data<={data[6:0],serial_in}; //Upon shift_en high every time a new serial data is coming to LSB bit and data will be shifted |
//to one bit. |
else |
data<=data; //Prevent formation of latches |
end |
|
|
assign data_out = data; //Output the data in a data_register |
assign serial_out = data[7]; //MSB is transmitted first in I2C protocol. |
|
|
endmodule |
|
//change loading into asynchronous mode |
|
/i2c_master_slave_core/trunk/i2c_master_slave_core/verilog/rtl/counter.v
New file
0,0 → 1,41
//////////////////////////counter.v/////////////////////////////////////////////////////////////////////////////// |
// |
//Designed Engineer: Ravi Gupta // |
//Company Name : Toomuch Semiconductor |
//Email : ravi1.gupta@toomuchsemi.com // |
// |
//Purpose : Used for counting clock pulses for prescale register and number of bytes transferred // |
//Created : 22-11-07 // |
// |
////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
/*// synopsys translate_off |
`include "oc8051_timescale.v" |
// synopsys translate_on |
|
`include "oc8051_defines.v"*/ |
|
|
module counter (clk,asyn_rst,enable,load,data_in,out); |
|
input clk,asyn_rst,enable,load; |
input [7:0] data_in; |
output [7:0] out; |
|
reg [7:0]data; |
|
always@(posedge clk or posedge asyn_rst) |
begin |
if(asyn_rst) |
data<=8'h0; //clear all bits upon asynchronous reset. |
else if(load) |
data<=data_in; //load the counter with incoming data if load signal is high |
else if(enable) |
data<=data + 1'b1; //Increment the counter if enable bit is high |
else |
data<=data; //else hold the data;else part is mention to avoid latch formation |
end |
|
assign out=data; |
|
endmodule |
/i2c_master_slave_core/trunk/i2c_master_slave_core/verilog/rtl/controller_interface.v
New file
0,0 → 1,546
////////////////////////////////////////////controller_interface.v//////////////////////////////////////// |
// // |
//Design Engineer: Ravi Gupta // |
//Company Name : Toomuch Semiconductor |
//Email : ravi1.gupta@toomuchsemi.com // |
// // |
//Purpose : This core will be used as an interface between I2C core and Processor // |
//Created : 6-12-2007 // |
// // |
// // |
// // |
// // |
// // |
// // |
// // |
// // |
//Modification : Change the control register,added halt reset and inter_rst in control register |
///////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
/*// synopsys translate_off |
`include "oc8051_timescale.v" |
// synopsys translate_on |
|
`include "oc8051_defines.v"*/ |
|
|
module processor_interface (clk,rst,add_bus,data_in,data_out,as,ds,rw,bus_busy,byte_trans,slave_addressed,arb_lost,slave_rw,inter,ack_rec, |
core_en,inter_en,mode,master_rw,ack,rep_start,data,i2c_data,slave_add,time_out_reg,prescale,irq,time_out,inter_rst,halt,data_en,time_rst); |
input clk; //System clock |
input rst; //system reset |
|
//signals connecting core to processor |
///////////////////////////////////// |
|
input [7:0]add_bus; //contains address of internal register |
input [7:0]data_in; //trnasport the data for i2c core |
input as; //asserted high indicates vallid address has been placed on the address bus |
input ds; //asserted high indicates valid data on data bus |
input rw; //"1" indicates that processor has to write else read |
output irq; //interrupt to processor |
output inter_rst; //this bit will be written by processor when it will clear the interrupt. |
output [7:0]data_out; |
output halt; |
output data_en; |
input time_rst; |
|
//signals from core to reflect te status of core and buses |
/////////////////////////////////////////////////////////// |
|
input bus_busy; //signal from core indicates bus is busy |
input byte_trans; //signal from core indicates byte transfer is in progress |
input slave_addressed; //signal from core indicares core has been identified as slave |
input arb_lost; //signal from core indicates bus error |
input slave_rw; //signal from core indicates operation of slave core |
input inter; //signal from core.this will interrupt the processor if this bit as well as interrupt enable is high |
input ack_rec; //signal from core to reflect the status of ack bit |
input time_out; |
|
//bits of control register |
////////////////////////// |
|
inout core_en; //this bit must be cleared before any other bit of control register have any effect on core |
inout inter_en; //To intrrupt the core this bit must be set when interrupt is pending |
inout mode; //Transaction from "0" to "1" directes core to act as master else slave |
inout master_rw; //set directiion for master either to transmit or receive |
inout ack; //value of acknowledgment bit to be transmitted on SDA line during ack cycle |
inout rep_start; //set this bit if processor wants a repeated start |
|
//data register |
//////////////// |
|
inout [7:0]prescale; //contains the value for generating SCL frequency |
inout [7:0]time_out_reg; //contains the value for maximum low period for scl |
inout [7:0]slave_add; //this is the programmble slave address |
inout [7:0]data; //data for i2c core |
input [7:0]i2c_data; //data from core for processor |
|
//defining registers addresses |
///////////////////////////// |
|
`define PRER 8'b0000_0010 |
`define CTR 8'b0000_0100 |
`define SR 8'b0000_1000 |
`define TO 8'b0000_1010 |
`define ADDR 8'b0000_1100 |
`define DR 8'b0000_1110 |
`define RR 8'b0000_0000 |
|
/*//defing the machine state |
////////////////////////// |
|
parameter processor_idle=2'b00; |
parameter processor_address=2'b01; |
parameter processor_data=2'b10; |
parameter processor_ack=2'b11;*/ |
|
//Definig internal registers and wires |
///////////////////////////////////// |
|
wire core_en,inter_en,mode,master_rw,ack,rep_start,inter_rst,halt; |
wire prescale_reg_en; |
wire ctr_reg_en; |
wire sr_reg_en; |
wire to_reg_en; |
wire addr_reg_en; |
wire dr_reg_en; |
reg [7:0]data_out,sr_reg,ctr_reg,dr_reg,rr_reg; |
wire [7:0]data_in; //if address on add_bus matches with register address then set this high. |
wire data_ie; //this is signal used for enaling the data line in read or write cycle. |
wire as_d; //delay version of address strobe signal for detection of rising and falling edge |
reg as_delay_sig; //same signal. |
wire ds_d; //delayed version of data strobe. |
wire decode; |
wire rr_reg_en; |
|
reg ds_delay_sig; |
|
reg prescale_reg_en_sig; |
assign prescale_reg_en = prescale_reg_en_sig; |
|
reg ctr_reg_en_sig; |
assign ctr_reg_en = ctr_reg_en_sig; |
|
reg sr_reg_en_sig; |
assign sr_reg_en = sr_reg_en_sig; |
|
reg to_reg_en_sig; |
assign to_reg_en = to_reg_en_sig; |
|
reg addr_reg_en_sig; |
assign addr_reg_en = addr_reg_en_sig; |
|
reg dr_reg_en_sig; |
assign dr_reg_en = dr_reg_en_sig; |
|
reg as_d_sig; |
assign as_d = as_d_sig; |
|
reg ds_d_sig; |
assign ds_d = ds_d_sig; |
|
reg data_ie_sig; |
assign data_ie = data_ie_sig; |
|
//reg core_en_sig; |
//assign core_en = core_en_sig; |
|
//reg inter_en_sig; |
//assign inter_en = inter_en_sig; |
|
//reg mode_sig; |
//assign mode = mode_sig; |
|
//reg master_rw_sig; |
//assign master_rw = master_rw_sig; |
|
//reg ack_sig; |
//assign ack = ack_sig; |
|
//reg rep_start_sig; |
//assign rep_start = rep_start_sig; |
|
reg [7:0]data_sig; |
assign data = dr_reg; |
|
reg [7:0]prescale_sig; |
assign prescale = prescale_sig; |
|
reg [7:0]time_out_sig; |
assign time_out_reg = time_out_sig; |
|
reg [7:0]slave_add_sig; |
assign slave_add = slave_add_sig; |
|
//reg [7:0]data_out_sig; |
//assign data_out = data_out_sig; |
|
reg decode_sig; |
assign decode = decode_sig; |
|
//reg inter_rst_sig; |
//assign inter_rst = inter_rst_sig; |
|
//reg halt_sig; |
//assign halt = halt_sig; |
assign data_en = dr_reg_en_sig; |
|
reg rr_reg_en_sig; |
assign rr_reg_en = rr_reg_en_sig; |
|
|
|
assign core_en = ctr_reg [7]; |
assign inter_en = ctr_reg [6]; |
assign mode = ctr_reg [5]; |
assign master_rw = ctr_reg [4]; |
assign ack = ctr_reg [3]; |
assign rep_start = ctr_reg [2]; |
assign inter_rst = ctr_reg [1]; |
assign halt = ctr_reg [0]; |
|
|
|
|
|
|
//generating delayed version of inputs for detection of rising and falling edge. |
////////////////////////////////////////////////////////////////////////////// |
|
always@(posedge clk or posedge rst) |
begin |
|
if(rst) |
begin |
as_delay_sig<=1'b0; |
as_d_sig<=1'b0; |
ds_delay_sig<=1'b0; |
ds_d_sig<=1'b0; |
end |
|
else |
begin |
as_delay_sig<=as; |
as_d_sig<=as_delay_sig; |
ds_delay_sig<=ds; |
ds_d_sig<=ds_delay_sig; |
end |
end |
|
always@(posedge clk or posedge rst) |
begin |
if(rst) |
decode_sig<=1'b0; |
else if(!as_d && as) |
decode_sig<=1'b1; |
//else |
//decode_sig<=1'b0; |
end |
|
//address decoding logic |
/////////////////////// |
|
//always@(posedge clk or posedge rst) |
always@(rst or as or add_bus or posedge time_rst) |
begin |
|
if(rst || time_rst) |
begin |
prescale_reg_en_sig<=1'b0; |
ctr_reg_en_sig<=1'b0; |
sr_reg_en_sig<=1'b0; |
to_reg_en_sig<=1'b0; |
addr_reg_en_sig<=1'b0; |
dr_reg_en_sig<=1'b0; |
rr_reg_en_sig <= 1'b0; |
|
//add_match_sig<=1'b0; |
end |
|
|
|
else if(as) |
begin |
if(add_bus == `PRER) |
begin |
rr_reg_en_sig <= 1'b0; |
prescale_reg_en_sig<=1'b1; |
ctr_reg_en_sig<=1'b0; |
sr_reg_en_sig<=1'b0; |
to_reg_en_sig<=1'b0; |
addr_reg_en_sig<=1'b0; |
dr_reg_en_sig<=1'b0; |
//add_match_sig<=1'b1; |
end |
|
else if(add_bus == `CTR) |
begin |
rr_reg_en_sig <= 1'b0; |
prescale_reg_en_sig<=1'b0; |
ctr_reg_en_sig<=1'b1; |
sr_reg_en_sig<=1'b0; |
to_reg_en_sig<=1'b0; |
addr_reg_en_sig<=1'b0; |
dr_reg_en_sig<=1'b0; |
//add_match_sig<=1'b1; |
end |
|
else if(add_bus == `SR) |
begin |
rr_reg_en_sig <= 1'b0; |
prescale_reg_en_sig<=1'b0; |
ctr_reg_en_sig<=1'b0; |
sr_reg_en_sig<=1'b1; |
to_reg_en_sig<=1'b0; |
addr_reg_en_sig<=1'b0; |
dr_reg_en_sig<=1'b0; |
//add_match_sig<=1'b1; |
end |
|
else if(add_bus == `TO) |
begin |
rr_reg_en_sig <= 1'b0; |
prescale_reg_en_sig<=1'b0; |
ctr_reg_en_sig<=1'b0; |
sr_reg_en_sig<=1'b0; |
to_reg_en_sig<=1'b1; |
addr_reg_en_sig<=1'b0; |
dr_reg_en_sig<=1'b0; |
//add_match_sig<=1'b1; |
end |
|
else if(add_bus == `ADDR) |
begin |
rr_reg_en_sig <= 1'b0; |
prescale_reg_en_sig<=1'b0; |
ctr_reg_en_sig<=1'b0; |
sr_reg_en_sig<=1'b0; |
to_reg_en_sig<=1'b0; |
addr_reg_en_sig<=1'b1; |
dr_reg_en_sig<=1'b0; |
//add_match_sig<=1'b1; |
end |
|
else if(add_bus == `DR) |
begin |
|
prescale_reg_en_sig<=1'b0; |
ctr_reg_en_sig<=1'b0; |
sr_reg_en_sig<=1'b0; |
to_reg_en_sig<=1'b0; |
addr_reg_en_sig<=1'b0; |
dr_reg_en_sig<=1'b1; |
rr_reg_en_sig <= 1'b0; |
//add_match_sig<=1'b1; |
end |
|
else if(add_bus == `RR) |
begin |
rr_reg_en_sig <= 1'b1; |
prescale_reg_en_sig<=1'b0; |
ctr_reg_en_sig<=1'b0; |
sr_reg_en_sig<=1'b0; |
to_reg_en_sig<=1'b0; |
addr_reg_en_sig<=1'b0; |
dr_reg_en_sig<=1'b0; |
//add_match_sig<=1'b1; |
end |
|
else |
begin |
rr_reg_en_sig <= 1'b0; |
prescale_reg_en_sig<=1'b0; |
ctr_reg_en_sig<=1'b0; |
sr_reg_en_sig<=1'b0; |
to_reg_en_sig<=1'b0; |
addr_reg_en_sig<=1'b0; |
dr_reg_en_sig<=1'b0; |
//add_match_sig<=1'b0; |
end |
|
|
end |
else |
begin |
prescale_reg_en_sig<=1'b0; |
ctr_reg_en_sig<=1'b0; |
sr_reg_en_sig<=1'b0; |
to_reg_en_sig<=1'b0; |
addr_reg_en_sig<=1'b0; |
dr_reg_en_sig<=1'b0; |
rr_reg_en_sig <= 1'b0; |
end |
|
end |
|
//assigning value of data_ie line |
////////////////////////////////// |
always@(posedge clk or posedge rst) |
begin |
if(rst) |
data_ie_sig<=1'b0; |
else if(!ds_d && ds) |
data_ie_sig<=1'b1; |
|
end |
|
|
//read data to/from the register specified by processor addrress. |
|
|
//always@(rst or addr_reg_en or ctr_reg_en or dr_reg_en or sr_reg_en or prescale_reg_en or to_reg_en or data_ie or rw or data_in ) |
|
always@(posedge clk or posedge rst) |
begin |
if(rst) |
begin |
sr_reg <= 8'b0; |
dr_reg <= 8'b0; |
rr_reg <= 8'b0; |
//ctr_reg <= 8'b0; |
end |
|
/*else if(ctr_reg_en) |
begin |
//sr_reg <= {byte_trans,slave_addressed,bus_busy,arb_lost,time_out,slave_rw,inter,ack_rec}; |
ctr_reg <= data_in; |
end*/ |
else |
begin |
sr_reg <= {byte_trans,slave_addressed,bus_busy,arb_lost,time_out,slave_rw,inter,ack_rec}; |
rr_reg <= i2c_data; |
end |
end |
|
always@(posedge clk or posedge rst or posedge time_rst) |
begin |
if(rst || time_rst) |
begin |
//initializing control register |
ctr_reg <= 8'b0; |
/*core_en_sig <= 1'b0; |
inter_en_sig <= 1'b0; |
mode_sig <= 1'b0; |
master_rw_sig <= 1'b0; |
ack_sig <= 1'b0; |
rep_start_sig <= 1'b0; |
inter_rst_sig<=1'b0;*/ |
//initializing data and timer register |
data_sig <= 8'b00000000; |
prescale_sig <= 8'b00000000; |
time_out_sig <= 8'b00000000; |
data_out <= 8'b00000000; |
end |
|
else if (data_ie) |
begin |
//address register |
if(addr_reg_en) //if address matches with slave address register |
begin |
if(rw) //processor write cycle |
slave_add_sig <= {data_in[7:1] , 1'b0}; |
else //processor read cycle |
data_out <= slave_add; |
end |
|
//control register |
if(ctr_reg_en) //if address matches with cntrol register |
begin |
if(rw) //processor write cycle |
//begin |
/*core_en_sig <= #2 ctr_reg [7]; |
inter_en_sig <= #2 ctr_reg [6]; |
mode_sig <= #2 ctr_reg [5]; |
master_rw_sig <= #2 ctr_reg [4]; |
ack_sig <= #2 ctr_reg [3]; |
rep_start_sig <= #2 ctr_reg [2]; |
inter_rst_sig <= #2 ctr_reg [1]; |
halt_sig <= #2 ctr_reg [0];*/ |
//end |
|
//else |
ctr_reg <= data_in; //processor read cycle |
else |
data_out <= ctr_reg; |
end |
|
else if(!byte_trans && bus_busy) |
ctr_reg[1:0] <= 2'b0; |
//data register |
|
if(dr_reg_en) |
begin |
if(rw) |
dr_reg <= data_in; |
else |
data_out <= dr_reg; |
end |
|
if(rr_reg_en) |
begin |
data_out <= rr_reg; |
end |
|
//staus register |
|
if(sr_reg_en) |
begin |
if(!rw) |
//begin |
//if(data_in[0]==1'b0) |
//inter_rst_sig <= 1'b0; |
//else |
//inter_rst_sig <= 1'b1; |
//end |
//else |
//begin |
data_out <= sr_reg; |
//inter_rst_sig<=1'b0; |
//end |
//else |
//inter_rst_sig<=1'b0; |
|
end |
|
|
//prescale register |
|
if(prescale_reg_en) |
begin |
if(rw) |
prescale_sig <= data_in; |
else |
data_out <= prescale; |
end |
|
//time_out register |
|
if(to_reg_en) |
begin |
if(rw) |
time_out_sig <= data_in; |
else |
data_out <= time_out_reg; |
end |
end |
end |
|
//assigning values to bidirectional bus |
////////////////////////////////////// |
|
//assign data_bus = (!rw && data_ie) ? data_out : 8'bzzzzzzzz; |
//assign data_in = (rw) ? data_bus : 8'bzzzzzzzz; |
|
//interuupt pin to processor |
assign irq = (inter && inter_en) ? 1'b1 : 1'b0; |
endmodule |
|
|
|
|
|
|
|
|
|
|
/i2c_master_slave_core/trunk/i2c_master_slave_core/verilog/rtl/i2c_blk.v
New file
0,0 → 1,172
////////////////////////////////////////////////////////////////////////////////////////// |
//Design Engineer: Ravi Gupta // |
//Company Name : Toomuch Semiconductor |
//Email : ravi1.gupta@toomuchsemi.com // |
// // |
// // |
//Purpose : This module will simply interconnect controller interface // // |
// controller_interface with ms_core. // |
// // |
// // |
//Date : 11-12-07 // |
// // |
// // |
// // |
// // |
// // |
// // |
// // |
////////////////////////////////////////////////////////////////////////////////////////// |
/*// synopsys translate_off |
`include "oc8051_timescale.v" |
// synopsys translate_on |
|
`include "oc8051_defines.v"*/ |
|
|
module block(scl_oe,scl_in,scl_o,sda_oe,sda_in,sda_o,wb_add_i,wb_data_i,wb_data_o,wb_we_i,wb_stb_i,wb_cyc_i,irq,trans_comp,wb_clk_i,wb_rst_i,wb_ack_o); |
|
//inout scl; //Bi-directional lines to follow i2c protocol for data transfer. |
input sda_in; //sda input |
output sda_oe; //control line for bidirectional buffer |
output sda_o; //input line for bi_firectional buffer |
input scl_in; |
output scl_o; |
output scl_oe; |
input [7:0]wb_data_i; //Bi-direction buses for transfering data to/from processor. |
input [7:0]wb_add_i; //Transfer the addresses of intenal registers. |
input wb_we_i; //signal from processor to indicate whether its a read or write cycle. |
input wb_stb_i; //when asserted indicates address is valid. |
input wb_cyc_i; //when asserted indicates data is valid. |
output irq; //interupt signal to processor. |
input wb_clk_i; //system clock. |
input wb_rst_i; //asynchrnous reset active high. |
inout trans_comp; //temprory signal for testing the core |
output [7:0]wb_data_o; |
output wb_ack_o; |
|
//declaratiion of internal signals |
////////////////////////////////// |
|
// control register |
wire [7:0] slave_add; // I2C address |
wire arb_lost; // indicates that arbitration for the i2c bus is lost |
wire bus_busy; // indicates the i2c bus is busy |
wire [7:0] i2c_up; // i2c data register |
wire [7:0] data; // uC data register |
wire core_en; // i2c enable - used as i2c reset |
wire inter_en; // interrupt enable |
wire inter; // interrupt pending |
wire mode; // i2c master/slave select |
wire master_rw; // master read/write |
wire rep_start; // generate a repeated start |
wire ack_rec; // value of received acknowledge |
wire slave_rw; // slave read/write |
wire ack; // value of acknowledge to be transmitted |
wire byte_trans; // indicates that one byte of data is being transferred |
wire slave_addressed; // address of core matches with address transferred |
wire time_out; // max low period for SCL has excedded |
wire [7:0]time_out_reg; // programmable max time for SCL low period |
wire [7:0]prescale; |
wire inter_rst; |
wire [7:0]wb_data_o; |
wire halt; |
wire data_en; |
wire time_rst; |
reg wb_ack_o; |
wire rst; |
|
assign trans_comp = byte_trans; |
|
always@(posedge wb_clk_i) |
begin |
wb_ack_o <= #1 wb_stb_i & wb_cyc_i & ~wb_ack_o; |
end |
|
//port map for i2c controller |
//////////////////////////// |
|
core i2c_core |
|
( |
.clk(wb_clk_i), |
.rst(core_en), |
.sda_oe(sda_oe), |
.sda_in(sda_in), |
.sda_o(sda_o), |
.scl_oe(scl_oe), |
.scl_o(scl_o), |
.scl_in(scl_in), |
.ack(ack), |
.mode(mode), |
.rep_start(rep_start), |
.master_rw(master_rw), |
.data_in(data[7:0]), |
.slave_add(slave_add[7:0]), |
.bus_busy(bus_busy), |
.byte_trans(byte_trans), |
.slave_addressed(slave_addressed), |
.arb_lost(arb_lost), |
.slave_rw(slave_rw), |
.time_out(time_out), |
.inter(inter), |
.ack_rec(ack_rec), |
.i2c_up(i2c_up[7:0]), |
.time_out_reg(time_out_reg[7:0]), |
.prescale_reg(prescale[7:0]), |
.inter_en(inter_en), |
.inter_rst(inter_rst), |
.data_en(data_en), |
.halt_rst(halt), |
.h_rst(wb_rst_i), |
.time_rst(time_rst)); |
|
|
//port map for controller interface |
/////////////////////////////////// |
|
processor_interface processor_interface |
|
( |
.clk(wb_clk_i), |
.rst(wb_rst_i), |
.add_bus(wb_add_i[7:0]), |
.data_in(wb_data_i[7:0]), |
.as(wb_stb_i), |
.ds(wb_cyc_i), |
.rw(wb_we_i), |
.bus_busy(bus_busy), |
.byte_trans(byte_trans), |
.slave_addressed(slave_addressed), |
.arb_lost(arb_lost), |
.slave_rw(slave_rw), |
.inter(inter), |
.ack_rec(ack_rec), |
.core_en(core_en), |
.inter_en(inter_en), |
.mode(mode), |
.master_rw(master_rw), |
.ack(ack), |
.rep_start(rep_start), |
.data(data[7:0]), |
.i2c_data(i2c_up[7:0]), |
.slave_add(slave_add), |
.time_out_reg(time_out_reg[7:0]), |
.prescale(prescale[7:0]), |
.irq(irq), |
.time_out(time_out), |
.inter_rst(inter_rst), |
.halt(halt), |
.data_en(data_en), |
.time_rst(time_rst), |
.data_out(wb_data_o)); |
|
//always@(scl or sda) |
//$display($time,"scl=%b\tsda=%b\t\n",scl,sda); |
|
|
endmodule |
|
|
|
|
/i2c_master_slave_core/trunk/i2c_master_slave_core/verilog/rtl/ms_core.v
New file
0,0 → 1,1157
///////////////////////////////////////ms_core.v//////////////////////////////////////////////////////////////////////// |
// // |
//Design engineer: Ravi Gupta // |
//Company Name : Toomuch Semiconductor |
//Email : ravi1.gupta@toomuchsemi.com // |
// // |
//Purpose : This is the core which will be used to interface I2C bus. // |
//Created : 23-11-07 // |
// |
//Modification : Changes made in data_reg_ld // |
// |
//Modification : Change byte_trans generation bit // |
// |
//Modification : Implemented a halt bit that will be generated at the completion of 9th scl pulse in master_mode only // |
// |
//Modification : After core reset(time out feature) core will go in idle escaping stop generation so need to clear // |
//all // |
//of status register. // |
// |
//Modification : Remove the sm_state clause,so that even if there is no acknowledegement it will not stop the // |
//generation of SCL and SDA // |
//untill it gets command to generate stop from processor. // |
// |
//Modification : Now also checking for detect_start in acknowledgement state for repeted start condition. // |
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
module core(clk,rst,sda_oe,sda_in,sda_o,scl_oe,scl_in,scl_o,ack,mode,rep_start,master_rw,data_in,slave_add,bus_busy,byte_trans,slave_addressed,arb_lost,slave_rw,time_out,inter,ack_rec,i2c_up,time_out_reg,prescale_reg,inter_rst,inter_en,halt_rst,data_en,time_rst,h_rst); |
|
////////////////////////////////////////////////signal defination//////////////////////////////////////////////////////////////// |
|
input clk; //System Clock |
input rst; //Main Reset |
output sda_oe; //I2C serial data line output to be connected to control line of bidirectional buffer on physical SDA line |
input sda_in; //I2C serial data line input |
output sda_o; //I2C sda line always asssign to zero this is to be connected to input of bidirectional buffer on physical SDA line |
output scl_oe; //I2C serial clock line output to be connected to control line of bidirectiional buffer on physical scl line |
input scl_in; //I2C serial clock line input |
output scl_o; //SCL output line to be connected to input of bidirectional line |
input ack; //Acknowledgement signal from control register |
input mode; //master/slave mode select |
input rep_start; //repeated start |
input master_rw; //command to core in master mode |
input [7:0]data_in; //data from processor to be outputed on I2C |
input [7:0]slave_add; //I2C slave address |
input data_en; |
output time_rst; |
input h_rst; |
|
//status signal: |
|
output bus_busy; //bus busy |
inout byte_trans; //transfer of byte is in progress_reg_en |
|
inout slave_addressed; //addressed as slave |
inout arb_lost; //arbitration has lost |
inout slave_rw; //indicates the operation by slave |
inout time_out; //indicates that SCL LOW time has been exceeded |
output inter; //interrupt pending,will be used for interrupting processor |
input inter_rst; //use to clear the interrupt |
input inter_en; //processor wants to take interrupt or not |
|
//signal for processor |
input halt_rst; |
output ack_rec; //indicates that ack has been recieved,will be used to inform if master reciever wants to terminate the transfer |
output [7:0]i2c_up; //I2C data for micro processor |
//timing control registers |
input [7:0]time_out_reg; //max SCL low period. |
input [7:0]prescale_reg; //clock divider for generating SCL frequency. |
|
/////////////////////////////////////////End of port defination////////////////////////////////////////////////////////////////// |
|
wire master_slave,arbitration_lost,bb,gen_start,rep_start,byte_trans_delay,byte_trans_fall; |
|
//wire scl_out,sda_out,clk_cnt_enable,clk_cnt_rst,bit_cnt_enable,bit_cnt_rst,timer_cnt_enable,timer_cnt_rst,scl_in,sda_in,sda_out_reg,stop_scl_reg,master_sda, gen_stop; |
wire master_sda,scl_in,gen_stop,sm_stop,detect_stop,detect_start,addr_match,core_rst,stop_scl,scl_out,neg_scl_sig,sda_sig; |
//reg [7:0]clk1_cnt,bit1_cnt,timer1_cnt; |
reg posedge_mode,negedge_mode; |
reg [2:0]scl_state; |
reg [1:0]state; |
reg [2:0]scl_main_state; |
wire [7:0] add_reg,shift_reg; |
wire [7:0]clk_cnt,bit_cnt; |
reg [7:0]time_cnt; |
reg [7:0]i2c_up; |
wire bit_cnt_enable,bit_cnt_rst,clk_cnt_enable,clk_cnt_rst,data_reg_ld,data_reg_en,sda_in,serial_out,i2c_serial_out,add_reg_ld,add_reg_en,posedge_mode_sig,negedge_mode_sig,interrupt; |
wire [7:0]zero; |
wire [7:0]reg_clr; |
|
wire slave_sda,sda_out,halt,arb_rst,interrupt_rst,d_detect_stop; |
|
shift shift_data(neg_scl,rst,data_reg_ld,data_reg_en,sda_in,data_in,serial_out,shift_reg); //shift register for transferring the data |
shift shift_add(neg_scl,rst,add_reg_ld,add_reg_en,sda_in,reg_clr,i2c_serial_out,add_reg); //shift register for transferring address |
counter clock_counter(clk,rst,clk_cnt_enable,clk_cnt_rst,zero,clk_cnt); //This will count number of clock pulses for prescale |
counter bit_counter(neg_scl,rst,bit_cnt_enable,bit_cnt_rst,zero,bit_cnt); //Implementation of bit counter |
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
reg clk_cnt_enable_sig; |
assign clk_cnt_enable = clk_cnt_enable_sig; |
|
reg clk_cnt_rst_sig; |
assign clk_cnt_rst = clk_cnt_rst_sig; |
|
|
//reg sda_in_sig; |
//assign sda_in = sda_in_sig; |
|
reg sm_stop_sig; |
assign sm_stop = sm_stop_sig; |
|
//reg scl_in_sig; |
//assign scl_in = scl_in_sig; |
|
reg gen_start_sig; |
assign gen_start = gen_start_sig; |
|
reg gen_stop_sig; |
assign gen_stop = gen_stop_sig; |
|
reg master_slave_sig; |
assign master_slave = master_slave_sig; |
|
reg detect_start_sig; |
assign detect_start=detect_start_sig; |
|
reg detect_stop_sig; |
assign detect_stop=detect_stop_sig; |
|
reg byte_trans_sig; |
assign byte_trans= byte_trans_sig; |
|
reg bb_sig; |
assign bb=bb_sig; |
|
reg slave_addressed_sig; |
assign slave_addressed=slave_addressed_sig; |
|
reg slave_rw_sig; |
assign slave_rw=slave_rw_sig; |
|
reg inter_sig; |
assign inter=inter_sig; |
assign interrupt=inter_sig; |
|
reg time_out_sig; |
assign time_out=time_out_sig; |
|
reg ack_rec_sig; |
assign ack_rec=ack_rec_sig; |
|
reg add_reg_enable_sig; |
assign add_reg_en=add_reg_enable_sig; |
|
reg data_reg_en_sig; |
assign data_reg_en=data_reg_en_sig; |
|
reg data_reg_ld_sig; |
assign data_reg_ld=data_reg_ld_sig; |
|
reg stop_scl_sig; |
assign stop_scl=stop_scl_sig; |
|
reg core_rst_sig; |
assign core_rst=core_rst_sig; |
|
reg sda_out_sig; |
assign sda_out=sda_out_sig; |
|
reg scl_out_sig; |
assign scl_out=scl_out_sig; |
|
reg master_sda_sig; |
assign master_sda=master_sda_sig; |
|
reg slave_sda_sig; |
assign slave_sda=slave_sda_sig; |
|
reg arbitration_lost_sig; |
assign arbitration_lost=arbitration_lost_sig; |
|
reg arb_lost_sig; |
assign arb_lost=arb_lost_sig; |
|
reg byte_trans_delay_sig; |
assign byte_trans_delay=byte_trans_delay_sig; |
|
reg byte_trans_fall_sig; |
assign byte_trans_fall=byte_trans_fall_sig; |
|
reg halt_sig; |
assign halt = halt_sig; |
|
reg arb_rst_sig; |
assign arb_rst=arb_rst_sig; |
|
reg interrupt_rst_sig; |
assign interrupt_rst=interrupt_rst_sig; |
|
reg rep_start_sig; |
assign time_rst = core_rst; |
|
reg d_detect_stop_sig; |
assign d_detect_stop = d_detect_stop_sig; |
|
reg d1_detect_stop_sig; |
|
|
assign bus_busy = bb; |
assign reg_clr=8'b00000000; |
assign neg_scl_sig=(~scl_in); |
assign neg_scl=neg_scl_sig; |
assign zero=8'b00000000; |
assign posedge_mode_sig=posedge_mode; |
assign negedge_mode_sig=negedge_mode; |
assign sda_o = 1'b0; //assign this to 0 always |
assign scl_o = 1'b0; |
|
|
|
parameter scl_idle=3'b000,scl_start=3'b001,scl_low_edge=3'b010,scl_low=3'b011,scl_high_edge=3'b100,scl_high=3'b101; |
parameter scl_address_shift=3'b001,scl_ack_address=3'b010,scl_rx_data=3'b011,scl_tx_data=3'b100,scl_send_ack=3'b101,scl_wait_ack=3'b110,scl_main_idle= 3'b000; |
|
parameter a=2'b00,b=2'b01,c=2'b10; |
|
////////////////////SCL Generator/////////////////////////////// |
//This machine will generate SCL and SDA when in master mode.It will |
//also generate START and STOP condition. |
|
//always@(scl_state or arbitration_lost or sm_stop or gen_stop or rep_start |
// or bb or gen_start or master_slave or clk_cnt or bit_cnt or |
// scl_in or sda_out or master_sda or core_rst) |
always@(posedge clk or posedge rst or posedge core_rst or posedge h_rst) |
begin |
|
//State machine initial conditions |
|
if(rst || h_rst) |
begin |
scl_state<=scl_idle; |
scl_out_sig<=1'b1; |
sda_out_sig<=1'b1; |
stop_scl_sig<=1'b0; |
clk_cnt_enable_sig<=1'b0; |
clk_cnt_rst_sig<=1'b1; |
//bit_cnt_rst_sig<=1'b0; |
//bit_cnt_enable_sig<=1'b0; |
end |
|
else if(core_rst) |
begin |
|
scl_state<=scl_idle; |
scl_main_state <= scl_main_idle; |
scl_out_sig<=1'b1; |
sda_out_sig<=1'b1; |
stop_scl_sig<=1'b0; |
clk_cnt_enable_sig<=1'b0; |
clk_cnt_rst_sig<=1'b1; |
slave_addressed_sig<=1'b0; |
end |
|
|
else |
begin |
|
case (scl_state) |
|
scl_idle: |
begin |
arb_rst_sig <= 1'b1; |
interrupt_rst_sig<=1'b1; |
sda_out_sig<=1'b1; |
stop_scl_sig<=1'b0; |
|
if(master_slave && !bb && gen_start) |
begin |
scl_state<=scl_start; |
|
end |
end |
|
|
scl_start: |
begin |
arb_rst_sig <= 1'b0; |
interrupt_rst_sig<=1'b0; |
clk_cnt_enable_sig<=1'b1; //enable the counter as soon as machine enters in this state. |
clk_cnt_rst_sig<=1'b0; |
//sda_out_sig<=1'b0; //generating start condition |
stop_scl_sig<=1'b0; |
if(clk_cnt == prescale_reg / 3) |
sda_out_sig<= 1'b0; |
|
if(clk_cnt == prescale_reg) //wait for prescale value to over |
scl_state<=scl_low_edge; |
else |
scl_state<=scl_start; |
end |
|
scl_low_edge: |
begin |
clk_cnt_rst_sig<=1'b1; //This state will generate only SCL negative edge,and reset all the counters |
//timer_cnt_enable_sig<=1'b1; //except timer counter which will be enabled at this state. |
//timer_cnt_rst_sig<=1'b0; //also reseting the timer counter in this state. |
scl_out_sig<=1'b0; |
scl_state<=scl_low; |
stop_scl_sig<=1'b0; |
end |
|
scl_low: |
begin |
clk_cnt_enable_sig<=1'b1; //enable the clock counter |
clk_cnt_rst_sig<=1'b0; |
scl_out_sig<=1'b0; |
|
if(arbitration_lost) |
stop_scl_sig<=1'b0; |
else if(rep_start_sig) |
begin |
sda_out_sig<=1'b1; |
stop_scl_sig<=1'b0; |
end |
|
|
else if((gen_stop) && ((scl_main_state != scl_ack_address) && (scl_main_state != scl_send_ack) |
&& (scl_main_state != scl_wait_ack))) //Ravi remove sm_stop from oring with gen_stop |
begin |
sda_out_sig<=1'b0; |
stop_scl_sig<=1'b1; |
|
end |
|
/*else if(rep_start) |
begin |
sda_out_sig<=1'b1; |
stop_scl_sig<=1'b0; |
end*/ |
else if(clk_cnt == prescale_reg / 3) |
begin |
sda_out_sig<=master_sda; |
stop_scl_sig<=1'b0; |
|
end |
|
else |
stop_scl_sig<=1'b0; |
|
|
//determine next state. |
|
if(clk_cnt == prescale_reg) |
begin |
if(bit_cnt == 8'b0000_0111 && arbitration_lost ) |
scl_state<=scl_idle; |
else if(interrupt && inter_en) //uncomenting out for cheking the core in interrupt mode |
scl_state<=scl_low; |
else if(halt) |
scl_state<=scl_low; |
else |
scl_state<=scl_high_edge; |
end |
|
else |
scl_state<=scl_low; |
end |
|
|
|
|
scl_high_edge: |
begin |
clk_cnt_rst_sig<=1'b1; |
scl_out_sig<=1'b1; |
if(gen_stop) //Ravi sm_stop from oring with gen_stop |
stop_scl_sig<=1'b1; |
|
else |
stop_scl_sig<=1'b0; |
if(!scl_in) |
scl_state<=scl_high_edge; |
else |
scl_state<=scl_high; |
end |
|
|
|
scl_high: |
begin |
clk_cnt_enable_sig<=1'b1; |
clk_cnt_rst_sig<=1'b0; |
scl_out_sig<=1'b1; |
if(clk_cnt == prescale_reg) |
begin |
if(rep_start_sig) |
scl_state<=scl_start; |
else if(stop_scl) |
scl_state<=scl_idle; |
|
else |
scl_state<=scl_low_edge; |
end |
|
else |
scl_state<=scl_high; |
end |
|
|
endcase |
end |
end |
|
|
//Sample the incoming SDA and SCL line with System clock |
|
/*always@(posedge clk or posedge rst) |
begin |
|
if(rst) |
begin |
//sda_in_sig <= 1'b1; |
scl_in_sig <=1'b1; |
end |
else |
begin |
if(!scl) |
scl_in_sig <= 1'b0; |
else |
scl_in_sig <= 1'b1; |
|
if(!sda) |
sda_in_sig <= 1'b0; |
else |
sda_in_sig <= 1'b1; |
|
//sda_out_sig <= sda; |
end |
end*/ |
|
//Generartion of control signal from the command based on processor. |
//This will control generation of start and stop signal. |
//This will also set the master_slave bit based on MODE signal |
//if bus is not busy i.e bb = 0 |
|
always@(posedge clk or posedge rst or posedge h_rst) |
begin |
if(rst || h_rst) |
begin |
gen_start_sig <= 1'b0; |
gen_stop_sig <= 1'b0; |
master_slave_sig <= 1'b0; |
|
end |
|
else |
begin |
if(posedge_mode_sig) |
gen_start_sig <= 1'b1; |
else if(detect_start) |
gen_start_sig <= 1'b0; |
|
if(!arbitration_lost && negedge_mode_sig) |
gen_stop_sig <= 1'b1; |
else if(detect_stop) |
gen_stop_sig <= 1'b0; |
|
if(!bb) |
master_slave_sig <= mode; |
else |
master_slave_sig <= master_slave; |
end |
end |
|
//State machine for detection of rising and falling edge of input mode for the generation of START and STOP. |
always@(posedge clk or posedge rst or posedge h_rst) |
begin |
if(rst || h_rst) |
begin |
posedge_mode<=1'b0; |
negedge_mode<=1'b0; |
state<=a; |
end |
|
else |
begin |
case(state) |
|
a: |
if(mode==1'b0) |
begin |
state<=b; |
posedge_mode<=1'b0; |
negedge_mode<=1'b0; |
end |
|
else |
begin |
state<=c; |
posedge_mode<=1'b1; |
negedge_mode<=1'b0; |
end |
|
b: |
if(mode==1'b0) |
begin |
state<=b; |
posedge_mode<=1'b0; |
negedge_mode<=1'b0; |
end |
|
else |
begin |
state<=a; |
posedge_mode<=1'b1; |
negedge_mode<=1'b0; |
end |
|
c: |
if(mode==1'b0) |
begin |
state<=a; |
posedge_mode<=1'b0; |
negedge_mode<=1'b1; |
end |
|
else |
begin |
state<=c; |
posedge_mode<=1'b0; |
negedge_mode<=1'b0; |
end |
|
endcase |
end |
end |
|
//This is the main state machine which will be used as both master as well as slave. |
//This gets triggered at falling edge of SCL. |
//If stop codition gets detected then it should work as asyn reset. |
|
always@(posedge rst or negedge scl_in or posedge detect_stop or posedge core_rst or posedge h_rst) |
begin |
|
if(rst || core_rst || h_rst) |
begin |
scl_main_state<=scl_main_idle; |
sm_stop_sig<=1'b0; |
end |
|
else |
begin |
case(scl_main_state) |
scl_main_idle: |
|
if(detect_start) |
scl_main_state<=scl_address_shift; |
else if(detect_stop) |
begin |
scl_main_state<=scl_main_idle; |
sm_stop_sig<=1'b0; |
end |
|
scl_address_shift: //machine will remain in this state,unless all the bits of address has been transferred. |
|
if(bit_cnt == 8'b0000_0111) |
scl_main_state<=scl_ack_address; |
else if(detect_stop) |
begin |
scl_main_state<=scl_main_idle; |
sm_stop_sig<=1'b0; |
end |
|
scl_ack_address: |
|
//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 |
endcase |
end |
end |
|
//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; |
end |
|
always@(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_trans |
|
always@(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; |
end |
end |
|
|
//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 STOP |
|
always@(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; |
end |
end |
|
//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; |
|
|
end |
end |
|
//generate delay version of detect_stop |
always@(posedge clk or posedge rst or posedge h_rst) |
begin |
if(rst || h_rst) |
d_detect_stop_sig <= 1'b0; |
else |
begin |
d1_detect_stop_sig <= detect_stop; |
d_detect_stop_sig <= d1_detect_stop_sig; |
end |
end |
|
|
always@(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; |
end |
end |
|
//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 bit |
always@(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 counter |
|
always@(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; |
end |
|
always@(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; |
end |
|
always@(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 processor |
always@(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; |
end |
end |
|
always@(posedge clk or posedge rst or posedge h_rst) |
begin |
if(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 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/doc/i2c_spec.pdf
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/doc/i2c_spec.pdf
Property changes :
Added: svn:mime-type
+ application/octet-stream
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/doc/i2c_core_verification_plan.pdf
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/doc/i2c_core_verification_plan.pdf
Property changes :
Added: svn:mime-type
+ application/octet-stream
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/doc/i2c_spec.doc
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/doc/i2c_spec.doc
Property changes :
Added: svn:mime-type
+ application/octet-stream
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/verilog/rtl/shift.v
New file
0,0 → 1,52
////////////////////////////Shift.v///////////////////////////////////////////////////////////////////// |
// // |
//Design Engineer: Ravi Gupta // |
//Company Name : Toomuch Semiconductor |
//Email : ravi1.gupta@toomuchsemi.com // |
// // |
//Purpose : Used for shifting address and data in both transmit and recieve mode // |
//created : 22-11-07 // |
// // |
//////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
/*// synopsys translate_off |
`include "oc8051_timescale.v" |
// synopsys translate_on |
|
`include "oc8051_defines.v"*/ |
|
|
module shift(clk,asyn_rst,load,shift_en,serial_in,data_in,serial_out,data_out); |
|
input clk,asyn_rst,load,shift_en,serial_in; |
input [7:0]data_in; |
|
output serial_out; |
output [7:0]data_out; |
|
reg [7:0]data; |
|
always@(posedge clk or posedge asyn_rst or posedge load) |
begin |
if(asyn_rst) |
data<=8'h0; //clear the data register upon asynchronous reset. |
|
else if(load) |
data<=data_in; //Load the internal register upon insertion of load bit. |
|
else if(shift_en) |
data<={data[6:0],serial_in}; //Upon shift_en high every time a new serial data is coming to LSB bit and data will be shifted |
//to one bit. |
else |
data<=data; //Prevent formation of latches |
end |
|
|
assign data_out = data; //Output the data in a data_register |
assign serial_out = data[7]; //MSB is transmitted first in I2C protocol. |
|
|
endmodule |
|
//change loading into asynchronous mode |
|
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/verilog/rtl/counter.v
New file
0,0 → 1,41
//////////////////////////counter.v/////////////////////////////////////////////////////////////////////////////// |
// |
//Designed Engineer: Ravi Gupta // |
//Company Name : Toomuch Semiconductor |
//Email : ravi1.gupta@toomuchsemi.com // |
// |
//Purpose : Used for counting clock pulses for prescale register and number of bytes transferred // |
//Created : 22-11-07 // |
// |
////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
/*// synopsys translate_off |
`include "oc8051_timescale.v" |
// synopsys translate_on |
|
`include "oc8051_defines.v"*/ |
|
|
module counter (clk,asyn_rst,enable,load,data_in,out); |
|
input clk,asyn_rst,enable,load; |
input [7:0] data_in; |
output [7:0] out; |
|
reg [7:0]data; |
|
always@(posedge clk or posedge asyn_rst) |
begin |
if(asyn_rst) |
data<=8'h0; //clear all bits upon asynchronous reset. |
else if(load) |
data<=data_in; //load the counter with incoming data if load signal is high |
else if(enable) |
data<=data + 1'b1; //Increment the counter if enable bit is high |
else |
data<=data; //else hold the data;else part is mention to avoid latch formation |
end |
|
assign out=data; |
|
endmodule |
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/verilog/rtl/controller_interface.v
New file
0,0 → 1,546
////////////////////////////////////////////controller_interface.v//////////////////////////////////////// |
// // |
//Design Engineer: Ravi Gupta // |
//Company Name : Toomuch Semiconductor |
//Email : ravi1.gupta@toomuchsemi.com // |
// // |
//Purpose : This core will be used as an interface between I2C core and Processor // |
//Created : 6-12-2007 // |
// // |
// // |
// // |
// // |
// // |
// // |
// // |
// // |
//Modification : Change the control register,added halt reset and inter_rst in control register |
///////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
/*// synopsys translate_off |
`include "oc8051_timescale.v" |
// synopsys translate_on |
|
`include "oc8051_defines.v"*/ |
|
|
module processor_interface (clk,rst,add_bus,data_in,data_out,as,ds,rw,bus_busy,byte_trans,slave_addressed,arb_lost,slave_rw,inter,ack_rec, |
core_en,inter_en,mode,master_rw,ack,rep_start,data,i2c_data,slave_add,time_out_reg,prescale,irq,time_out,inter_rst,halt,data_en,time_rst); |
input clk; //System clock |
input rst; //system reset |
|
//signals connecting core to processor |
///////////////////////////////////// |
|
input [7:0]add_bus; //contains address of internal register |
input [7:0]data_in; //trnasport the data for i2c core |
input as; //asserted high indicates vallid address has been placed on the address bus |
input ds; //asserted high indicates valid data on data bus |
input rw; //"1" indicates that processor has to write else read |
output irq; //interrupt to processor |
output inter_rst; //this bit will be written by processor when it will clear the interrupt. |
output [7:0]data_out; |
output halt; |
output data_en; |
input time_rst; |
|
//signals from core to reflect te status of core and buses |
/////////////////////////////////////////////////////////// |
|
input bus_busy; //signal from core indicates bus is busy |
input byte_trans; //signal from core indicates byte transfer is in progress |
input slave_addressed; //signal from core indicares core has been identified as slave |
input arb_lost; //signal from core indicates bus error |
input slave_rw; //signal from core indicates operation of slave core |
input inter; //signal from core.this will interrupt the processor if this bit as well as interrupt enable is high |
input ack_rec; //signal from core to reflect the status of ack bit |
input time_out; |
|
//bits of control register |
////////////////////////// |
|
inout core_en; //this bit must be cleared before any other bit of control register have any effect on core |
inout inter_en; //To intrrupt the core this bit must be set when interrupt is pending |
inout mode; //Transaction from "0" to "1" directes core to act as master else slave |
inout master_rw; //set directiion for master either to transmit or receive |
inout ack; //value of acknowledgment bit to be transmitted on SDA line during ack cycle |
inout rep_start; //set this bit if processor wants a repeated start |
|
//data register |
//////////////// |
|
inout [7:0]prescale; //contains the value for generating SCL frequency |
inout [7:0]time_out_reg; //contains the value for maximum low period for scl |
inout [7:0]slave_add; //this is the programmble slave address |
inout [7:0]data; //data for i2c core |
input [7:0]i2c_data; //data from core for processor |
|
//defining registers addresses |
///////////////////////////// |
|
`define PRER 8'b0000_0010 |
`define CTR 8'b0000_0100 |
`define SR 8'b0000_1000 |
`define TO 8'b0000_1010 |
`define ADDR 8'b0000_1100 |
`define DR 8'b0000_1110 |
`define RR 8'b0000_0000 |
|
/*//defing the machine state |
////////////////////////// |
|
parameter processor_idle=2'b00; |
parameter processor_address=2'b01; |
parameter processor_data=2'b10; |
parameter processor_ack=2'b11;*/ |
|
//Definig internal registers and wires |
///////////////////////////////////// |
|
wire core_en,inter_en,mode,master_rw,ack,rep_start,inter_rst,halt; |
wire prescale_reg_en; |
wire ctr_reg_en; |
wire sr_reg_en; |
wire to_reg_en; |
wire addr_reg_en; |
wire dr_reg_en; |
reg [7:0]data_out,sr_reg,ctr_reg,dr_reg,rr_reg; |
wire [7:0]data_in; //if address on add_bus matches with register address then set this high. |
wire data_ie; //this is signal used for enaling the data line in read or write cycle. |
wire as_d; //delay version of address strobe signal for detection of rising and falling edge |
reg as_delay_sig; //same signal. |
wire ds_d; //delayed version of data strobe. |
wire decode; |
wire rr_reg_en; |
|
reg ds_delay_sig; |
|
reg prescale_reg_en_sig; |
assign prescale_reg_en = prescale_reg_en_sig; |
|
reg ctr_reg_en_sig; |
assign ctr_reg_en = ctr_reg_en_sig; |
|
reg sr_reg_en_sig; |
assign sr_reg_en = sr_reg_en_sig; |
|
reg to_reg_en_sig; |
assign to_reg_en = to_reg_en_sig; |
|
reg addr_reg_en_sig; |
assign addr_reg_en = addr_reg_en_sig; |
|
reg dr_reg_en_sig; |
assign dr_reg_en = dr_reg_en_sig; |
|
reg as_d_sig; |
assign as_d = as_d_sig; |
|
reg ds_d_sig; |
assign ds_d = ds_d_sig; |
|
reg data_ie_sig; |
assign data_ie = data_ie_sig; |
|
//reg core_en_sig; |
//assign core_en = core_en_sig; |
|
//reg inter_en_sig; |
//assign inter_en = inter_en_sig; |
|
//reg mode_sig; |
//assign mode = mode_sig; |
|
//reg master_rw_sig; |
//assign master_rw = master_rw_sig; |
|
//reg ack_sig; |
//assign ack = ack_sig; |
|
//reg rep_start_sig; |
//assign rep_start = rep_start_sig; |
|
reg [7:0]data_sig; |
assign data = dr_reg; |
|
reg [7:0]prescale_sig; |
assign prescale = prescale_sig; |
|
reg [7:0]time_out_sig; |
assign time_out_reg = time_out_sig; |
|
reg [7:0]slave_add_sig; |
assign slave_add = slave_add_sig; |
|
//reg [7:0]data_out_sig; |
//assign data_out = data_out_sig; |
|
reg decode_sig; |
assign decode = decode_sig; |
|
//reg inter_rst_sig; |
//assign inter_rst = inter_rst_sig; |
|
//reg halt_sig; |
//assign halt = halt_sig; |
assign data_en = dr_reg_en_sig; |
|
reg rr_reg_en_sig; |
assign rr_reg_en = rr_reg_en_sig; |
|
|
|
assign core_en = ctr_reg [7]; |
assign inter_en = ctr_reg [6]; |
assign mode = ctr_reg [5]; |
assign master_rw = ctr_reg [4]; |
assign ack = ctr_reg [3]; |
assign rep_start = ctr_reg [2]; |
assign inter_rst = ctr_reg [1]; |
assign halt = ctr_reg [0]; |
|
|
|
|
|
|
//generating delayed version of inputs for detection of rising and falling edge. |
////////////////////////////////////////////////////////////////////////////// |
|
always@(posedge clk or posedge rst) |
begin |
|
if(rst) |
begin |
as_delay_sig<=1'b0; |
as_d_sig<=1'b0; |
ds_delay_sig<=1'b0; |
ds_d_sig<=1'b0; |
end |
|
else |
begin |
as_delay_sig<=as; |
as_d_sig<=as_delay_sig; |
ds_delay_sig<=ds; |
ds_d_sig<=ds_delay_sig; |
end |
end |
|
always@(posedge clk or posedge rst) |
begin |
if(rst) |
decode_sig<=1'b0; |
else if(!as_d && as) |
decode_sig<=1'b1; |
//else |
//decode_sig<=1'b0; |
end |
|
//address decoding logic |
/////////////////////// |
|
//always@(posedge clk or posedge rst) |
always@(rst or as or add_bus or posedge time_rst) |
begin |
|
if(rst || time_rst) |
begin |
prescale_reg_en_sig<=1'b0; |
ctr_reg_en_sig<=1'b0; |
sr_reg_en_sig<=1'b0; |
to_reg_en_sig<=1'b0; |
addr_reg_en_sig<=1'b0; |
dr_reg_en_sig<=1'b0; |
rr_reg_en_sig <= 1'b0; |
|
//add_match_sig<=1'b0; |
end |
|
|
|
else if(as) |
begin |
if(add_bus == `PRER) |
begin |
rr_reg_en_sig <= 1'b0; |
prescale_reg_en_sig<=1'b1; |
ctr_reg_en_sig<=1'b0; |
sr_reg_en_sig<=1'b0; |
to_reg_en_sig<=1'b0; |
addr_reg_en_sig<=1'b0; |
dr_reg_en_sig<=1'b0; |
//add_match_sig<=1'b1; |
end |
|
else if(add_bus == `CTR) |
begin |
rr_reg_en_sig <= 1'b0; |
prescale_reg_en_sig<=1'b0; |
ctr_reg_en_sig<=1'b1; |
sr_reg_en_sig<=1'b0; |
to_reg_en_sig<=1'b0; |
addr_reg_en_sig<=1'b0; |
dr_reg_en_sig<=1'b0; |
//add_match_sig<=1'b1; |
end |
|
else if(add_bus == `SR) |
begin |
rr_reg_en_sig <= 1'b0; |
prescale_reg_en_sig<=1'b0; |
ctr_reg_en_sig<=1'b0; |
sr_reg_en_sig<=1'b1; |
to_reg_en_sig<=1'b0; |
addr_reg_en_sig<=1'b0; |
dr_reg_en_sig<=1'b0; |
//add_match_sig<=1'b1; |
end |
|
else if(add_bus == `TO) |
begin |
rr_reg_en_sig <= 1'b0; |
prescale_reg_en_sig<=1'b0; |
ctr_reg_en_sig<=1'b0; |
sr_reg_en_sig<=1'b0; |
to_reg_en_sig<=1'b1; |
addr_reg_en_sig<=1'b0; |
dr_reg_en_sig<=1'b0; |
//add_match_sig<=1'b1; |
end |
|
else if(add_bus == `ADDR) |
begin |
rr_reg_en_sig <= 1'b0; |
prescale_reg_en_sig<=1'b0; |
ctr_reg_en_sig<=1'b0; |
sr_reg_en_sig<=1'b0; |
to_reg_en_sig<=1'b0; |
addr_reg_en_sig<=1'b1; |
dr_reg_en_sig<=1'b0; |
//add_match_sig<=1'b1; |
end |
|
else if(add_bus == `DR) |
begin |
|
prescale_reg_en_sig<=1'b0; |
ctr_reg_en_sig<=1'b0; |
sr_reg_en_sig<=1'b0; |
to_reg_en_sig<=1'b0; |
addr_reg_en_sig<=1'b0; |
dr_reg_en_sig<=1'b1; |
rr_reg_en_sig <= 1'b0; |
//add_match_sig<=1'b1; |
end |
|
else if(add_bus == `RR) |
begin |
rr_reg_en_sig <= 1'b1; |
prescale_reg_en_sig<=1'b0; |
ctr_reg_en_sig<=1'b0; |
sr_reg_en_sig<=1'b0; |
to_reg_en_sig<=1'b0; |
addr_reg_en_sig<=1'b0; |
dr_reg_en_sig<=1'b0; |
//add_match_sig<=1'b1; |
end |
|
else |
begin |
rr_reg_en_sig <= 1'b0; |
prescale_reg_en_sig<=1'b0; |
ctr_reg_en_sig<=1'b0; |
sr_reg_en_sig<=1'b0; |
to_reg_en_sig<=1'b0; |
addr_reg_en_sig<=1'b0; |
dr_reg_en_sig<=1'b0; |
//add_match_sig<=1'b0; |
end |
|
|
end |
else |
begin |
prescale_reg_en_sig<=1'b0; |
ctr_reg_en_sig<=1'b0; |
sr_reg_en_sig<=1'b0; |
to_reg_en_sig<=1'b0; |
addr_reg_en_sig<=1'b0; |
dr_reg_en_sig<=1'b0; |
rr_reg_en_sig <= 1'b0; |
end |
|
end |
|
//assigning value of data_ie line |
////////////////////////////////// |
always@(posedge clk or posedge rst) |
begin |
if(rst) |
data_ie_sig<=1'b0; |
else if(!ds_d && ds) |
data_ie_sig<=1'b1; |
|
end |
|
|
//read data to/from the register specified by processor addrress. |
|
|
//always@(rst or addr_reg_en or ctr_reg_en or dr_reg_en or sr_reg_en or prescale_reg_en or to_reg_en or data_ie or rw or data_in ) |
|
always@(posedge clk or posedge rst) |
begin |
if(rst) |
begin |
sr_reg <= 8'b0; |
dr_reg <= 8'b0; |
rr_reg <= 8'b0; |
//ctr_reg <= 8'b0; |
end |
|
/*else if(ctr_reg_en) |
begin |
//sr_reg <= {byte_trans,slave_addressed,bus_busy,arb_lost,time_out,slave_rw,inter,ack_rec}; |
ctr_reg <= data_in; |
end*/ |
else |
begin |
sr_reg <= {byte_trans,slave_addressed,bus_busy,arb_lost,time_out,slave_rw,inter,ack_rec}; |
rr_reg <= i2c_data; |
end |
end |
|
always@(posedge clk or posedge rst or posedge time_rst) |
begin |
if(rst || time_rst) |
begin |
//initializing control register |
ctr_reg <= 8'b0; |
/*core_en_sig <= 1'b0; |
inter_en_sig <= 1'b0; |
mode_sig <= 1'b0; |
master_rw_sig <= 1'b0; |
ack_sig <= 1'b0; |
rep_start_sig <= 1'b0; |
inter_rst_sig<=1'b0;*/ |
//initializing data and timer register |
data_sig <= 8'b00000000; |
prescale_sig <= 8'b00000000; |
time_out_sig <= 8'b00000000; |
data_out <= 8'b00000000; |
end |
|
else if (data_ie) |
begin |
//address register |
if(addr_reg_en) //if address matches with slave address register |
begin |
if(rw) //processor write cycle |
slave_add_sig <= {data_in[7:1] , 1'b0}; |
else //processor read cycle |
data_out <= slave_add; |
end |
|
//control register |
if(ctr_reg_en) //if address matches with cntrol register |
begin |
if(rw) //processor write cycle |
//begin |
/*core_en_sig <= #2 ctr_reg [7]; |
inter_en_sig <= #2 ctr_reg [6]; |
mode_sig <= #2 ctr_reg [5]; |
master_rw_sig <= #2 ctr_reg [4]; |
ack_sig <= #2 ctr_reg [3]; |
rep_start_sig <= #2 ctr_reg [2]; |
inter_rst_sig <= #2 ctr_reg [1]; |
halt_sig <= #2 ctr_reg [0];*/ |
//end |
|
//else |
ctr_reg <= data_in; //processor read cycle |
else |
data_out <= ctr_reg; |
end |
|
else if(!byte_trans && bus_busy) |
ctr_reg[1:0] <= 2'b0; |
//data register |
|
if(dr_reg_en) |
begin |
if(rw) |
dr_reg <= data_in; |
else |
data_out <= dr_reg; |
end |
|
if(rr_reg_en) |
begin |
data_out <= rr_reg; |
end |
|
//staus register |
|
if(sr_reg_en) |
begin |
if(!rw) |
//begin |
//if(data_in[0]==1'b0) |
//inter_rst_sig <= 1'b0; |
//else |
//inter_rst_sig <= 1'b1; |
//end |
//else |
//begin |
data_out <= sr_reg; |
//inter_rst_sig<=1'b0; |
//end |
//else |
//inter_rst_sig<=1'b0; |
|
end |
|
|
//prescale register |
|
if(prescale_reg_en) |
begin |
if(rw) |
prescale_sig <= data_in; |
else |
data_out <= prescale; |
end |
|
//time_out register |
|
if(to_reg_en) |
begin |
if(rw) |
time_out_sig <= data_in; |
else |
data_out <= time_out_reg; |
end |
end |
end |
|
//assigning values to bidirectional bus |
////////////////////////////////////// |
|
//assign data_bus = (!rw && data_ie) ? data_out : 8'bzzzzzzzz; |
//assign data_in = (rw) ? data_bus : 8'bzzzzzzzz; |
|
//interuupt pin to processor |
assign irq = (inter && inter_en) ? 1'b1 : 1'b0; |
endmodule |
|
|
|
|
|
|
|
|
|
|
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/verilog/rtl/i2c_blk.v
New file
0,0 → 1,172
////////////////////////////////////////////////////////////////////////////////////////// |
//Design Engineer: Ravi Gupta // |
//Company Name : Toomuch Semiconductor |
//Email : ravi1.gupta@toomuchsemi.com // |
// // |
// // |
//Purpose : This module will simply interconnect controller interface // // |
// controller_interface with ms_core. // |
// // |
// // |
//Date : 11-12-07 // |
// // |
// // |
// // |
// // |
// // |
// // |
// // |
////////////////////////////////////////////////////////////////////////////////////////// |
/*// synopsys translate_off |
`include "oc8051_timescale.v" |
// synopsys translate_on |
|
`include "oc8051_defines.v"*/ |
|
|
module block(scl_oe,scl_in,scl_o,sda_oe,sda_in,sda_o,wb_add_i,wb_data_i,wb_data_o,wb_we_i,wb_stb_i,wb_cyc_i,irq,trans_comp,wb_clk_i,wb_rst_i,wb_ack_o); |
|
//inout scl; //Bi-directional lines to follow i2c protocol for data transfer. |
input sda_in; //sda input |
output sda_oe; //control line for bidirectional buffer |
output sda_o; //input line for bi_firectional buffer |
input scl_in; |
output scl_o; |
output scl_oe; |
input [7:0]wb_data_i; //Bi-direction buses for transfering data to/from processor. |
input [7:0]wb_add_i; //Transfer the addresses of intenal registers. |
input wb_we_i; //signal from processor to indicate whether its a read or write cycle. |
input wb_stb_i; //when asserted indicates address is valid. |
input wb_cyc_i; //when asserted indicates data is valid. |
output irq; //interupt signal to processor. |
input wb_clk_i; //system clock. |
input wb_rst_i; //asynchrnous reset active high. |
inout trans_comp; //temprory signal for testing the core |
output [7:0]wb_data_o; |
output wb_ack_o; |
|
//declaratiion of internal signals |
////////////////////////////////// |
|
// control register |
wire [7:0] slave_add; // I2C address |
wire arb_lost; // indicates that arbitration for the i2c bus is lost |
wire bus_busy; // indicates the i2c bus is busy |
wire [7:0] i2c_up; // i2c data register |
wire [7:0] data; // uC data register |
wire core_en; // i2c enable - used as i2c reset |
wire inter_en; // interrupt enable |
wire inter; // interrupt pending |
wire mode; // i2c master/slave select |
wire master_rw; // master read/write |
wire rep_start; // generate a repeated start |
wire ack_rec; // value of received acknowledge |
wire slave_rw; // slave read/write |
wire ack; // value of acknowledge to be transmitted |
wire byte_trans; // indicates that one byte of data is being transferred |
wire slave_addressed; // address of core matches with address transferred |
wire time_out; // max low period for SCL has excedded |
wire [7:0]time_out_reg; // programmable max time for SCL low period |
wire [7:0]prescale; |
wire inter_rst; |
wire [7:0]wb_data_o; |
wire halt; |
wire data_en; |
wire time_rst; |
reg wb_ack_o; |
wire rst; |
|
assign trans_comp = byte_trans; |
|
always@(posedge wb_clk_i) |
begin |
wb_ack_o <= #1 wb_stb_i & wb_cyc_i & ~wb_ack_o; |
end |
|
//port map for i2c controller |
//////////////////////////// |
|
core i2c_core |
|
( |
.clk(wb_clk_i), |
.rst(core_en), |
.sda_oe(sda_oe), |
.sda_in(sda_in), |
.sda_o(sda_o), |
.scl_oe(scl_oe), |
.scl_o(scl_o), |
.scl_in(scl_in), |
.ack(ack), |
.mode(mode), |
.rep_start(rep_start), |
.master_rw(master_rw), |
.data_in(data[7:0]), |
.slave_add(slave_add[7:0]), |
.bus_busy(bus_busy), |
.byte_trans(byte_trans), |
.slave_addressed(slave_addressed), |
.arb_lost(arb_lost), |
.slave_rw(slave_rw), |
.time_out(time_out), |
.inter(inter), |
.ack_rec(ack_rec), |
.i2c_up(i2c_up[7:0]), |
.time_out_reg(time_out_reg[7:0]), |
.prescale_reg(prescale[7:0]), |
.inter_en(inter_en), |
.inter_rst(inter_rst), |
.data_en(data_en), |
.halt_rst(halt), |
.h_rst(wb_rst_i), |
.time_rst(time_rst)); |
|
|
//port map for controller interface |
/////////////////////////////////// |
|
processor_interface processor_interface |
|
( |
.clk(wb_clk_i), |
.rst(wb_rst_i), |
.add_bus(wb_add_i[7:0]), |
.data_in(wb_data_i[7:0]), |
.as(wb_stb_i), |
.ds(wb_cyc_i), |
.rw(wb_we_i), |
.bus_busy(bus_busy), |
.byte_trans(byte_trans), |
.slave_addressed(slave_addressed), |
.arb_lost(arb_lost), |
.slave_rw(slave_rw), |
.inter(inter), |
.ack_rec(ack_rec), |
.core_en(core_en), |
.inter_en(inter_en), |
.mode(mode), |
.master_rw(master_rw), |
.ack(ack), |
.rep_start(rep_start), |
.data(data[7:0]), |
.i2c_data(i2c_up[7:0]), |
.slave_add(slave_add), |
.time_out_reg(time_out_reg[7:0]), |
.prescale(prescale[7:0]), |
.irq(irq), |
.time_out(time_out), |
.inter_rst(inter_rst), |
.halt(halt), |
.data_en(data_en), |
.time_rst(time_rst), |
.data_out(wb_data_o)); |
|
//always@(scl or sda) |
//$display($time,"scl=%b\tsda=%b\t\n",scl,sda); |
|
|
endmodule |
|
|
|
|
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/verilog/rtl/ms_core.v
New file
0,0 → 1,1157
///////////////////////////////////////ms_core.v//////////////////////////////////////////////////////////////////////// |
// // |
//Design engineer: Ravi Gupta // |
//Company Name : Toomuch Semiconductor |
//Email : ravi1.gupta@toomuchsemi.com // |
// // |
//Purpose : This is the core which will be used to interface I2C bus. // |
//Created : 23-11-07 // |
// |
//Modification : Changes made in data_reg_ld // |
// |
//Modification : Change byte_trans generation bit // |
// |
//Modification : Implemented a halt bit that will be generated at the completion of 9th scl pulse in master_mode only // |
// |
//Modification : After core reset(time out feature) core will go in idle escaping stop generation so need to clear // |
//all // |
//of status register. // |
// |
//Modification : Remove the sm_state clause,so that even if there is no acknowledegement it will not stop the // |
//generation of SCL and SDA // |
//untill it gets command to generate stop from processor. // |
// |
//Modification : Now also checking for detect_start in acknowledgement state for repeted start condition. // |
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
module core(clk,rst,sda_oe,sda_in,sda_o,scl_oe,scl_in,scl_o,ack,mode,rep_start,master_rw,data_in,slave_add,bus_busy,byte_trans,slave_addressed,arb_lost,slave_rw,time_out,inter,ack_rec,i2c_up,time_out_reg,prescale_reg,inter_rst,inter_en,halt_rst,data_en,time_rst,h_rst); |
|
////////////////////////////////////////////////signal defination//////////////////////////////////////////////////////////////// |
|
input clk; //System Clock |
input rst; //Main Reset |
output sda_oe; //I2C serial data line output to be connected to control line of bidirectional buffer on physical SDA line |
input sda_in; //I2C serial data line input |
output sda_o; //I2C sda line always asssign to zero this is to be connected to input of bidirectional buffer on physical SDA line |
output scl_oe; //I2C serial clock line output to be connected to control line of bidirectiional buffer on physical scl line |
input scl_in; //I2C serial clock line input |
output scl_o; //SCL output line to be connected to input of bidirectional line |
input ack; //Acknowledgement signal from control register |
input mode; //master/slave mode select |
input rep_start; //repeated start |
input master_rw; //command to core in master mode |
input [7:0]data_in; //data from processor to be outputed on I2C |
input [7:0]slave_add; //I2C slave address |
input data_en; |
output time_rst; |
input h_rst; |
|
//status signal: |
|
output bus_busy; //bus busy |
inout byte_trans; //transfer of byte is in progress_reg_en |
|
inout slave_addressed; //addressed as slave |
inout arb_lost; //arbitration has lost |
inout slave_rw; //indicates the operation by slave |
inout time_out; //indicates that SCL LOW time has been exceeded |
output inter; //interrupt pending,will be used for interrupting processor |
input inter_rst; //use to clear the interrupt |
input inter_en; //processor wants to take interrupt or not |
|
//signal for processor |
input halt_rst; |
output ack_rec; //indicates that ack has been recieved,will be used to inform if master reciever wants to terminate the transfer |
output [7:0]i2c_up; //I2C data for micro processor |
//timing control registers |
input [7:0]time_out_reg; //max SCL low period. |
input [7:0]prescale_reg; //clock divider for generating SCL frequency. |
|
/////////////////////////////////////////End of port defination////////////////////////////////////////////////////////////////// |
|
wire master_slave,arbitration_lost,bb,gen_start,rep_start,byte_trans_delay,byte_trans_fall; |
|
//wire scl_out,sda_out,clk_cnt_enable,clk_cnt_rst,bit_cnt_enable,bit_cnt_rst,timer_cnt_enable,timer_cnt_rst,scl_in,sda_in,sda_out_reg,stop_scl_reg,master_sda, gen_stop; |
wire master_sda,scl_in,gen_stop,sm_stop,detect_stop,detect_start,addr_match,core_rst,stop_scl,scl_out,neg_scl_sig,sda_sig; |
//reg [7:0]clk1_cnt,bit1_cnt,timer1_cnt; |
reg posedge_mode,negedge_mode; |
reg [2:0]scl_state; |
reg [1:0]state; |
reg [2:0]scl_main_state; |
wire [7:0] add_reg,shift_reg; |
wire [7:0]clk_cnt,bit_cnt; |
reg [7:0]time_cnt; |
reg [7:0]i2c_up; |
wire bit_cnt_enable,bit_cnt_rst,clk_cnt_enable,clk_cnt_rst,data_reg_ld,data_reg_en,sda_in,serial_out,i2c_serial_out,add_reg_ld,add_reg_en,posedge_mode_sig,negedge_mode_sig,interrupt; |
wire [7:0]zero; |
wire [7:0]reg_clr; |
|
wire slave_sda,sda_out,halt,arb_rst,interrupt_rst,d_detect_stop; |
|
shift shift_data(neg_scl,rst,data_reg_ld,data_reg_en,sda_in,data_in,serial_out,shift_reg); //shift register for transferring the data |
shift shift_add(neg_scl,rst,add_reg_ld,add_reg_en,sda_in,reg_clr,i2c_serial_out,add_reg); //shift register for transferring address |
counter clock_counter(clk,rst,clk_cnt_enable,clk_cnt_rst,zero,clk_cnt); //This will count number of clock pulses for prescale |
counter bit_counter(neg_scl,rst,bit_cnt_enable,bit_cnt_rst,zero,bit_cnt); //Implementation of bit counter |
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
reg clk_cnt_enable_sig; |
assign clk_cnt_enable = clk_cnt_enable_sig; |
|
reg clk_cnt_rst_sig; |
assign clk_cnt_rst = clk_cnt_rst_sig; |
|
|
//reg sda_in_sig; |
//assign sda_in = sda_in_sig; |
|
reg sm_stop_sig; |
assign sm_stop = sm_stop_sig; |
|
//reg scl_in_sig; |
//assign scl_in = scl_in_sig; |
|
reg gen_start_sig; |
assign gen_start = gen_start_sig; |
|
reg gen_stop_sig; |
assign gen_stop = gen_stop_sig; |
|
reg master_slave_sig; |
assign master_slave = master_slave_sig; |
|
reg detect_start_sig; |
assign detect_start=detect_start_sig; |
|
reg detect_stop_sig; |
assign detect_stop=detect_stop_sig; |
|
reg byte_trans_sig; |
assign byte_trans= byte_trans_sig; |
|
reg bb_sig; |
assign bb=bb_sig; |
|
reg slave_addressed_sig; |
assign slave_addressed=slave_addressed_sig; |
|
reg slave_rw_sig; |
assign slave_rw=slave_rw_sig; |
|
reg inter_sig; |
assign inter=inter_sig; |
assign interrupt=inter_sig; |
|
reg time_out_sig; |
assign time_out=time_out_sig; |
|
reg ack_rec_sig; |
assign ack_rec=ack_rec_sig; |
|
reg add_reg_enable_sig; |
assign add_reg_en=add_reg_enable_sig; |
|
reg data_reg_en_sig; |
assign data_reg_en=data_reg_en_sig; |
|
reg data_reg_ld_sig; |
assign data_reg_ld=data_reg_ld_sig; |
|
reg stop_scl_sig; |
assign stop_scl=stop_scl_sig; |
|
reg core_rst_sig; |
assign core_rst=core_rst_sig; |
|
reg sda_out_sig; |
assign sda_out=sda_out_sig; |
|
reg scl_out_sig; |
assign scl_out=scl_out_sig; |
|
reg master_sda_sig; |
assign master_sda=master_sda_sig; |
|
reg slave_sda_sig; |
assign slave_sda=slave_sda_sig; |
|
reg arbitration_lost_sig; |
assign arbitration_lost=arbitration_lost_sig; |
|
reg arb_lost_sig; |
assign arb_lost=arb_lost_sig; |
|
reg byte_trans_delay_sig; |
assign byte_trans_delay=byte_trans_delay_sig; |
|
reg byte_trans_fall_sig; |
assign byte_trans_fall=byte_trans_fall_sig; |
|
reg halt_sig; |
assign halt = halt_sig; |
|
reg arb_rst_sig; |
assign arb_rst=arb_rst_sig; |
|
reg interrupt_rst_sig; |
assign interrupt_rst=interrupt_rst_sig; |
|
reg rep_start_sig; |
assign time_rst = core_rst; |
|
reg d_detect_stop_sig; |
assign d_detect_stop = d_detect_stop_sig; |
|
reg d1_detect_stop_sig; |
|
|
assign bus_busy = bb; |
assign reg_clr=8'b00000000; |
assign neg_scl_sig=(~scl_in); |
assign neg_scl=neg_scl_sig; |
assign zero=8'b00000000; |
assign posedge_mode_sig=posedge_mode; |
assign negedge_mode_sig=negedge_mode; |
assign sda_o = 1'b0; //assign this to 0 always |
assign scl_o = 1'b0; |
|
|
|
parameter scl_idle=3'b000,scl_start=3'b001,scl_low_edge=3'b010,scl_low=3'b011,scl_high_edge=3'b100,scl_high=3'b101; |
parameter scl_address_shift=3'b001,scl_ack_address=3'b010,scl_rx_data=3'b011,scl_tx_data=3'b100,scl_send_ack=3'b101,scl_wait_ack=3'b110,scl_main_idle= 3'b000; |
|
parameter a=2'b00,b=2'b01,c=2'b10; |
|
////////////////////SCL Generator/////////////////////////////// |
//This machine will generate SCL and SDA when in master mode.It will |
//also generate START and STOP condition. |
|
//always@(scl_state or arbitration_lost or sm_stop or gen_stop or rep_start |
// or bb or gen_start or master_slave or clk_cnt or bit_cnt or |
// scl_in or sda_out or master_sda or core_rst) |
always@(posedge clk or posedge rst or posedge core_rst or posedge h_rst) |
begin |
|
//State machine initial conditions |
|
if(rst || h_rst) |
begin |
scl_state<=scl_idle; |
scl_out_sig<=1'b1; |
sda_out_sig<=1'b1; |
stop_scl_sig<=1'b0; |
clk_cnt_enable_sig<=1'b0; |
clk_cnt_rst_sig<=1'b1; |
//bit_cnt_rst_sig<=1'b0; |
//bit_cnt_enable_sig<=1'b0; |
end |
|
else if(core_rst) |
begin |
|
scl_state<=scl_idle; |
scl_main_state <= scl_main_idle; |
scl_out_sig<=1'b1; |
sda_out_sig<=1'b1; |
stop_scl_sig<=1'b0; |
clk_cnt_enable_sig<=1'b0; |
clk_cnt_rst_sig<=1'b1; |
slave_addressed_sig<=1'b0; |
end |
|
|
else |
begin |
|
case (scl_state) |
|
scl_idle: |
begin |
arb_rst_sig <= 1'b1; |
interrupt_rst_sig<=1'b1; |
sda_out_sig<=1'b1; |
stop_scl_sig<=1'b0; |
|
if(master_slave && !bb && gen_start) |
begin |
scl_state<=scl_start; |
|
end |
end |
|
|
scl_start: |
begin |
arb_rst_sig <= 1'b0; |
interrupt_rst_sig<=1'b0; |
clk_cnt_enable_sig<=1'b1; //enable the counter as soon as machine enters in this state. |
clk_cnt_rst_sig<=1'b0; |
//sda_out_sig<=1'b0; //generating start condition |
stop_scl_sig<=1'b0; |
if(clk_cnt == prescale_reg / 3) |
sda_out_sig<= 1'b0; |
|
if(clk_cnt == prescale_reg) //wait for prescale value to over |
scl_state<=scl_low_edge; |
else |
scl_state<=scl_start; |
end |
|
scl_low_edge: |
begin |
clk_cnt_rst_sig<=1'b1; //This state will generate only SCL negative edge,and reset all the counters |
//timer_cnt_enable_sig<=1'b1; //except timer counter which will be enabled at this state. |
//timer_cnt_rst_sig<=1'b0; //also reseting the timer counter in this state. |
scl_out_sig<=1'b0; |
scl_state<=scl_low; |
stop_scl_sig<=1'b0; |
end |
|
scl_low: |
begin |
clk_cnt_enable_sig<=1'b1; //enable the clock counter |
clk_cnt_rst_sig<=1'b0; |
scl_out_sig<=1'b0; |
|
if(arbitration_lost) |
stop_scl_sig<=1'b0; |
else if(rep_start_sig) |
begin |
sda_out_sig<=1'b1; |
stop_scl_sig<=1'b0; |
end |
|
|
else if((gen_stop) && ((scl_main_state != scl_ack_address) && (scl_main_state != scl_send_ack) |
&& (scl_main_state != scl_wait_ack))) //Ravi remove sm_stop from oring with gen_stop |
begin |
sda_out_sig<=1'b0; |
stop_scl_sig<=1'b1; |
|
end |
|
/*else if(rep_start) |
begin |
sda_out_sig<=1'b1; |
stop_scl_sig<=1'b0; |
end*/ |
else if(clk_cnt == prescale_reg / 3) |
begin |
sda_out_sig<=master_sda; |
stop_scl_sig<=1'b0; |
|
end |
|
else |
stop_scl_sig<=1'b0; |
|
|
//determine next state. |
|
if(clk_cnt == prescale_reg) |
begin |
if(bit_cnt == 8'b0000_0111 && arbitration_lost ) |
scl_state<=scl_idle; |
else if(interrupt && inter_en) //uncomenting out for cheking the core in interrupt mode |
scl_state<=scl_low; |
else if(halt) |
scl_state<=scl_low; |
else |
scl_state<=scl_high_edge; |
end |
|
else |
scl_state<=scl_low; |
end |
|
|
|
|
scl_high_edge: |
begin |
clk_cnt_rst_sig<=1'b1; |
scl_out_sig<=1'b1; |
if(gen_stop) //Ravi sm_stop from oring with gen_stop |
stop_scl_sig<=1'b1; |
|
else |
stop_scl_sig<=1'b0; |
if(!scl_in) |
scl_state<=scl_high_edge; |
else |
scl_state<=scl_high; |
end |
|
|
|
scl_high: |
begin |
clk_cnt_enable_sig<=1'b1; |
clk_cnt_rst_sig<=1'b0; |
scl_out_sig<=1'b1; |
if(clk_cnt == prescale_reg) |
begin |
if(rep_start_sig) |
scl_state<=scl_start; |
else if(stop_scl) |
scl_state<=scl_idle; |
|
else |
scl_state<=scl_low_edge; |
end |
|
else |
scl_state<=scl_high; |
end |
|
|
endcase |
end |
end |
|
|
//Sample the incoming SDA and SCL line with System clock |
|
/*always@(posedge clk or posedge rst) |
begin |
|
if(rst) |
begin |
//sda_in_sig <= 1'b1; |
scl_in_sig <=1'b1; |
end |
else |
begin |
if(!scl) |
scl_in_sig <= 1'b0; |
else |
scl_in_sig <= 1'b1; |
|
if(!sda) |
sda_in_sig <= 1'b0; |
else |
sda_in_sig <= 1'b1; |
|
//sda_out_sig <= sda; |
end |
end*/ |
|
//Generartion of control signal from the command based on processor. |
//This will control generation of start and stop signal. |
//This will also set the master_slave bit based on MODE signal |
//if bus is not busy i.e bb = 0 |
|
always@(posedge clk or posedge rst or posedge h_rst) |
begin |
if(rst || h_rst) |
begin |
gen_start_sig <= 1'b0; |
gen_stop_sig <= 1'b0; |
master_slave_sig <= 1'b0; |
|
end |
|
else |
begin |
if(posedge_mode_sig) |
gen_start_sig <= 1'b1; |
else if(detect_start) |
gen_start_sig <= 1'b0; |
|
if(!arbitration_lost && negedge_mode_sig) |
gen_stop_sig <= 1'b1; |
else if(detect_stop) |
gen_stop_sig <= 1'b0; |
|
if(!bb) |
master_slave_sig <= mode; |
else |
master_slave_sig <= master_slave; |
end |
end |
|
//State machine for detection of rising and falling edge of input mode for the generation of START and STOP. |
always@(posedge clk or posedge rst or posedge h_rst) |
begin |
if(rst || h_rst) |
begin |
posedge_mode<=1'b0; |
negedge_mode<=1'b0; |
state<=a; |
end |
|
else |
begin |
case(state) |
|
a: |
if(mode==1'b0) |
begin |
state<=b; |
posedge_mode<=1'b0; |
negedge_mode<=1'b0; |
end |
|
else |
begin |
state<=c; |
posedge_mode<=1'b1; |
negedge_mode<=1'b0; |
end |
|
b: |
if(mode==1'b0) |
begin |
state<=b; |
posedge_mode<=1'b0; |
negedge_mode<=1'b0; |
end |
|
else |
begin |
state<=a; |
posedge_mode<=1'b1; |
negedge_mode<=1'b0; |
end |
|
c: |
if(mode==1'b0) |
begin |
state<=a; |
posedge_mode<=1'b0; |
negedge_mode<=1'b1; |
end |
|
else |
begin |
state<=c; |
posedge_mode<=1'b0; |
negedge_mode<=1'b0; |
end |
|
endcase |
end |
end |
|
//This is the main state machine which will be used as both master as well as slave. |
//This gets triggered at falling edge of SCL. |
//If stop codition gets detected then it should work as asyn reset. |
|
always@(posedge rst or negedge scl_in or posedge detect_stop or posedge core_rst or posedge h_rst) |
begin |
|
if(rst || core_rst || h_rst) |
begin |
scl_main_state<=scl_main_idle; |
sm_stop_sig<=1'b0; |
end |
|
else |
begin |
case(scl_main_state) |
scl_main_idle: |
|
if(detect_start) |
scl_main_state<=scl_address_shift; |
else if(detect_stop) |
begin |
scl_main_state<=scl_main_idle; |
sm_stop_sig<=1'b0; |
end |
|
scl_address_shift: //machine will remain in this state,unless all the bits of address has been transferred. |
|
if(bit_cnt == 8'b0000_0111) |
scl_main_state<=scl_ack_address; |
else if(detect_stop) |
begin |
scl_main_state<=scl_main_idle; |
sm_stop_sig<=1'b0; |
end |
|
scl_ack_address: |
|
//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 |
endcase |
end |
end |
|
//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; |
end |
|
always@(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_trans |
|
always@(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; |
end |
end |
|
|
//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 STOP |
|
always@(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; |
end |
end |
|
//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; |
|
|
end |
end |
|
//generate delay version of detect_stop |
always@(posedge clk or posedge rst or posedge h_rst) |
begin |
if(rst || h_rst) |
d_detect_stop_sig <= 1'b0; |
else |
begin |
d1_detect_stop_sig <= detect_stop; |
d_detect_stop_sig <= d1_detect_stop_sig; |
end |
end |
|
|
always@(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; |
end |
end |
|
//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 bit |
always@(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 counter |
|
always@(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; |
end |
|
always@(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; |
end |
|
always@(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 processor |
always@(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; |
end |
end |
|
always@(posedge clk or posedge rst or posedge h_rst) |
begin |
if(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 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/svtb/Readme
New file
0,0 → 1,18
|
This Directory contains all files which are required to run this VMM testbench. |
Scripts are not given as it vary from compiler to compiler. |
|
The Basic structure of file system is given below. |
|
vmm_i2c_top.sv |
| |
|--- vmm_clkgen.sv |
|--- vmm_program_test.sv |
| |
|--- vmm_i2c_env.sv (This is the environment file and all transactors and packet files |
are included in this file) |
|
Please note that for transition coverage in register testcase (write-write-read), another file is |
availabe which is vmm_program1_test.sv. In this file Scenario_generator_class is extended and |
program and top level module is also available. |
|
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_stimulus_packet.sv
New file
0,0 → 1,69
////////////////////////////////////////////////////////////////////////////////////////// |
// // |
// Verification Engineer: Atish Jaiswal // |
// Company Name : TooMuch Semiconductor Solutions Pvt Ltd. // |
// // |
// Description of the Source File: // |
// This file defines Stimulus packet class for Scenario Generator. // |
// The Packet Randomizes intr_en to enable/disable interrupt, byte_count to transfer // |
// Random no. of data_bytes, register_address and data for register testcase. It also // |
// randomize slave address. Other fields get assigned in Scenario generator class. // |
// Constraint block called reg_add is used to contrain randomized fields. // |
// // |
// // |
////////////////////////////////////////////////////////////////////////////////////////// |
|
`include "vmm.sv" |
|
class stimulus_packet extends vmm_data; |
|
vmm_log log; |
|
rand bit intr_en ; // 1 for Interrupt enable and 0 for disable |
rand int byte_count; // no. of bytes to be transfered |
rand bit [7:0] register_data; // to check register read/write |
rand bit [7:0] register_addr; // to select the address of internal register |
rand bit [6:0] slave_address; // slave address to be checked |
bit [7:0] data_packet[]; // data packets to be transfered |
bit master_slave; // 1 for master and 0 for slave |
bit tr; // 1 for trasmit and 0 for receive |
bit register_check; // 1 to check registers writing and 0 for not. |
bit reset_check; // 1 to check reset test and 0 for not. |
int temp_count; |
|
constraint reg_add { |
register_addr inside {8'h02, 8'h04, 8'h0A, 8'h0C, 8'h0E}; |
byte_count inside {[2:10]}; |
slave_address < 7'b111_1111; |
intr_en dist {0 := 1, 1 :=1}; |
} |
|
|
function new(); |
super.new(this.log); |
this.log = new("Stimulus Data", "class"); |
endfunction |
|
function void display(); |
this.log.start_msg(vmm_log::NOTE_TYP); |
void'(this.log.text($psprintf("Master/Slave mode is = %b\n", master_slave))); |
void'(this.log.text($psprintf("tr = %d\n", tr))); |
void'(this.log.text($psprintf("register_check = %b\n", register_check))); |
void'(this.log.text($psprintf("reset_check = %b\n", reset_check))); |
void'(this.log.text($psprintf("Interrupt Enable is = %b\n", intr_en))); |
void'(this.log.text($psprintf("byte_count = %d\n", byte_count))); |
void'(this.log.text($psprintf("register_addr = %b\n", register_addr))); |
void'(this.log.text($psprintf("register_data = %b\n", register_data))); |
void'(this.log.text($psprintf("slave_address = %b\n", slave_address))); |
this.log.end_msg(); |
temp_count = byte_count; |
endfunction |
|
|
function vmm_data copy(vmm_data to = null); |
copy = new this; |
endfunction |
|
endclass |
`vmm_channel(stimulus_packet) // This macro defined in VMM Methodology creates channel named stimulus_packet_channel |
|
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_sb_pkt.sv
New file
0,0 → 1,43
////////////////////////////////////////////////////////////////////////////////////////// |
// // |
// Verification Engineer: Atish Jaiswal // |
// Company Name : TooMuch Semiconductor Solutions Pvt Ltd. // |
// // |
// Description of the Source File: // |
// This source code defines Scoreboard Packet. This packet will be sent to Scoreboard // |
// and Coverage Module from Both W/B Driver and I2C M/S Driver through vmm_callback. // |
// // |
// // |
////////////////////////////////////////////////////////////////////////////////////////// |
|
`include "vmm.sv" |
|
class scoreboard_pkt extends vmm_data; |
|
vmm_log log; |
bit master_slave; // 1 for Master; 0 for Slave; |
bit tx_rx; // 1 for Tx; 0 for Rx |
bit [6:0] slave_address; // 7-bit Slave Address |
bit [7:0] data_byte; // 8-bit Data Byte |
|
function new(); |
super.new(this.log); |
this.log = new("Sb Data", "class"); |
endfunction |
|
function vmm_data copy(vmm_data to = null); |
copy = new this; |
endfunction |
|
|
function void display(); |
this.log.start_msg(vmm_log::NOTE_TYP); |
void'(this.log.text($psprintf("master_slave is %0b", this.master_slave))); |
void'(this.log.text($psprintf("tx_rx is %0b", this.tx_rx))); |
void'(this.log.text($psprintf("slave_address is %b", this.slave_address))); |
void'(this.log.text($psprintf("data_byte is %b", this.data_byte))); |
this.log.end_msg(); |
endfunction |
|
endclass |
|
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_scoreboard.sv
New file
0,0 → 1,146
////////////////////////////////////////////////////////////////////////////////////////// |
// // |
// Verification Engineer: Atish Jaiswal // |
// Company Name : TooMuch Semiconductor Solutions Pvt Ltd. // |
// // |
// Description of the Source File: // |
// This source code implements Scoreboard. // |
// Scoreboard contains queues for data_bytes comparision and Associative Array for // |
// Register values comparision for read/write test-cases. // |
// Whenever any transaction starts, through pre_txn callback it gets oject and // |
// save that object into queue. Once transaction is done, it get another objects // |
// through post_txn call backs from dirvers. In Scoreboard it compares both object's // |
// data_byte and reports MATCH or MISMATCH of data. // |
// For Register testcases it saves register value whenever any data gets written // |
// to DUT register into associative array with register address as an index. Now, // |
// When Register-read test occurs, it compares the data read from internal register // |
// with Assocative Array's dat of same index. If register was not written previously // |
// it compread read data with initial value of that register. // |
// // |
////////////////////////////////////////////////////////////////////////////////////////// |
|
`include "vmm.sv" |
|
class i2c_scoreboard extends vmm_xactor; |
|
scoreboard_pkt sb_pre_txn_q[$]; // Queue of scoreboard_pkt for pre_transaction |
scoreboard_pkt sb_post_txn_q[$]; // Queue of scoreboard_pkt for post_transaction |
vmm_log log; |
scoreboard_pkt sb_pre_obj; // Scoreoard_pkt's instance for pre_transaction |
scoreboard_pkt sb_pre_obj1; // Scoreoard_pkt's instance for pre_transaction |
scoreboard_pkt sb_post_obj; // Scoreoard_pkt's instance for post_transaction |
scoreboard_pkt sb_post_obj1; // Scoreoard_pkt's instance for post_transaction |
|
register_pkt reg_pkt; // registet_pkt's instance |
register_pkt reg_pkt1; // register_pkt's instance |
|
typedef bit [7:0] reg_addr; |
bit [7:0] initial_reg [*]; // 8-bit wide Associative Array of to store initial_register's value |
bit [7:0] wr_reg [*]; // 8-bit wide Associative Array of to store data which were written in DUT reigsters |
bit [7:0] ref_reg_value; // 8-bit wide register for storing reference data to be compared. |
|
// Constructor Class |
function new (string name, string instance); |
super.new("I2C_Scoreboard", "SCOREBOARD"); |
this.log = new("Scoreboard", "SCOREBOARD"); |
endfunction |
|
|
// Write_reg Task. It saves the data written to internal register of DUT into Associative Array wr_reg |
task write_reg(register_pkt reg_pkt); |
// $display("Scoreboard: inside write_reg at %t", $time); |
// if(reg_pkt.reset_bit) |
// begin |
// wr_reg.delete; |
// for (int i = 0; i < sb_pre_txn_q.size ; i++) |
// sb_pre_txn_q.delete(i); |
// for (int j = 0; j < sb_post_txn_q.size ; j++) |
// sb_post_txn_q.delete(j); |
// end |
// else |
// begin |
$cast(reg_pkt1,reg_pkt.copy()); |
wr_reg[reg_pkt1.reg_address] = reg_pkt1.data_byte; |
// end |
endtask |
|
|
// Read_reg task. It Check whether data is previously written to internal register (Checks Whether data already exists for the given index, |
// which is internal register's address in this case). If data already exists, it compare this data with the read data. If data with same index |
// doesn't exists, it will compare this read data with initial data of that index. |
task read_reg(register_pkt reg_pkt); |
$cast(reg_pkt1,reg_pkt.copy()); |
if(wr_reg.exists(reg_pkt1.reg_address)) // Data Already written into internal register of given index(address) |
begin |
ref_reg_value = wr_reg[reg_pkt1.reg_address]; |
if(reg_pkt1.reg_address == 8'h0C) |
if(ref_reg_value[7:1] == reg_pkt1.data_byte[7:1]) |
`vmm_note(log, "Scoreboard: Date written into Register MATCH with Date read from Register"); |
else |
`vmm_error(log, "Scoreboard: Date written into Register DO NOT MATCH with Date read from Register"); |
else if (reg_pkt1.reg_address == 8'h04) |
if(ref_reg_value[7:2] == reg_pkt1.data_byte[7:2]) |
`vmm_note(log, "Scoreboard: Date written into Register MATCH with Date read from Register"); |
else |
`vmm_error(log, "Scoreboard: Date written into Register DO NOT MATCH with Date read from Register"); |
else |
if(ref_reg_value == reg_pkt1.data_byte) |
`vmm_note(log, "Scoreboard: Date written into Register MATCH with Date read from Register"); |
else |
`vmm_error(log, "Scoreboard: Date written into Register DO NOT MATCH with Date read from Register"); |
end |
else |
begin // Data was not written before |
if(reg_pkt1.data_byte == 8'h00) |
`vmm_note(log, "Scoreboard: Date written into Register MATCH with Initial Valre of Register"); |
else |
`vmm_error(log, "Scoreboard: Date written into Register DO NOT MATCH with Initial Value of Register"); |
end |
endtask |
|
// Pre_txn_push task. This task will push back the data packet(object) been received by callback. |
task pre_txn_push(scoreboard_pkt sb_pre_obj); |
$cast(sb_pre_obj1,sb_pre_obj.copy()); |
this.sb_pre_obj1.display(); |
this.sb_pre_txn_q.push_back(sb_pre_obj1); |
endtask |
|
// Post_txn_push Task. This task is used to compare both data_byte, the one to be transmitter before starting transmission and |
// the one which was received after completion of transation. This task will check whether any object is already available |
// in the queue(If size > 0). If object is alread there, It will pop_out that object and check the data_byte of both objects. |
task post_txn_push(scoreboard_pkt sb_post_obj); |
if(sb_pre_txn_q.size > 0) |
begin |
sb_post_obj1 = this.sb_pre_txn_q.pop_front(); |
if(sb_post_obj1.data_byte == sb_post_obj.data_byte) |
`vmm_note(log, $psprintf("DATA TRANSMITED AND RECEIVED MATCH WITH EACH OTHER AT TIME %t", $time)); |
else |
`vmm_error(log, $psprintf("DATA TRANSMITED AND RECEIVED DO NOT MATCH WITH EACH OTHER AT TIME %t", $time)); |
end |
endtask |
|
|
// This task it used to display all contents of queue. |
task sb_display(); |
this.log.start_msg(vmm_log::NOTE_TYP); |
void'(this.log.text($psprintf("****************************"))); |
void'(this.log.text($psprintf("*****SCOREBOARD REPORT*****"))); |
void'(this.log.text($psprintf("****************************"))); |
|
void'(this.log.text($psprintf("\n*****PACKETS TRANSMITTED*****"))); |
for (int i = 0; i < this.sb_pre_txn_q.size ; i++) |
begin |
void'(this.log.text($psprintf("Master/Slave = %0b Data_Transmitted = %b", sb_pre_txn_q[i].master_slave, sb_pre_txn_q[i].data_byte))); |
end |
|
void'(this.log.text($psprintf("\n*****PACKETS RECEIVED*****"))); |
for (int i = 0; i < this.sb_post_txn_q.size ; i++) |
begin |
void'(this.log.text($psprintf("Master/Slave = %0b Data_Received = %b", sb_post_txn_q[i].master_slave, sb_post_txn_q[i].data_byte))); |
end |
this.log.end_msg(); |
endtask |
|
endclass |
|
|
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_slave_driver.sv
New file
0,0 → 1,717
////////////////////////////////////////////////////////////////////////////////////////// |
// // |
// Verification Engineer: Atish Jaiswal // |
// Company Name : TooMuch Semiconductor Solutions Pvt Ltd. // |
// // |
// Description of the Source File: // |
// This source code implements I2C M/S Driver. // |
// Driver will be receiving Scenario packets from Stimulus gen and accordingly it // |
// will keep on monitoring/driving interface signals. // |
// // |
// // |
////////////////////////////////////////////////////////////////////////////////////////// |
|
|
`include "vmm.sv" |
|
class i2c_slave_driver extends vmm_xactor; |
|
vmm_log log = new("lOG", "SLAVE_DRIVER"); |
|
virtual i2c_pin_if pif; // Virtual Interface |
stimulus_packet_channel s_stim_req_chan; // Scenario_gen to Driver Channel |
stimulus_packet s_stim_packet; // Stimulus Packet's Instance |
stimulus_packet s_temp_stim_packet; // Stimulus Packet's Temprary Instance |
stimulus_packet s_response_packet; |
scoreboard_pkt s_sb_pkt; // Scoreboard Packet's Instance |
|
|
// Class Constructor |
function new(string name, string instance, virtual i2c_pin_if pif, stimulus_packet_channel s_stim_req_chan = null); |
super.new("slave_driver","i2c_slave_driver"); |
if(s_stim_req_chan == null) s_stim_req_chan = new("slave_stimulus_packet_channel", "s_stim_req_chan"); |
this.s_stim_req_chan = s_stim_req_chan; |
s_stim_packet = new; |
s_temp_stim_packet = new; |
s_response_packet = new; |
s_sb_pkt = new; |
this.pif = pif; |
endfunction |
|
|
reg [6:0] slave_address; // Stores slave addess |
reg [7:0] mem_in ; // memory reg which receives data |
reg [7:0] mem_out; // memory data output |
reg [2:0] bit_cnt; // 3-bit down counter |
reg [2:0] state; // State when this core is in slave mode |
reg [7:0] sr; // 8bit shift register |
reg sta, d_sta; // Local Start and delayed Start Signal |
reg sto, d_sto; // Local Stop and delayed Stop Signal |
reg rw; // read/write direction |
reg ld; // load downcounter |
reg sda_o; // sda-drive level |
reg scl_o; // sca-drive level |
|
reg my_adr, my_adr_flag ; // address match flags |
reg i2c_reset; // i2c-state machine reset |
reg acc_done; // Checks whethere 8-bits transmission done |
reg sda_dly; // delayed version of sda |
int byte_count; // Byte count |
reg core_master_slave; // Selects Master/Slave configuration of this driver |
reg tr; // Selects Transmit/Receive Operation of this driver |
reg [7:0] data_out; // memory data output |
bit [7:0] slave_data_out[]; // memory data output |
bit load_data; // Load new data into mem_out |
int sent_data_count; // Count no. of bytes already been sent |
int received_data_count; // Count no. of bytes already been received |
int slave_bit_count; // Control Slave bit count while sending address to DUT |
bit slave_start_sig; // Local Start signal for generating Start |
bit slave_stop_sig; // Local Stop Signal for generating Stop |
bit slave_ack; // Checks Acknowledgment from DUT |
reg [2:0] slave_state; // Slave State when this core is in master mode |
int i =0; |
reg temp; // Temp signal to be assigned on sda_oe |
reg shift_data_out; // Control Shifting of data |
reg load_first_data_flag; |
|
// Initialize the local variables of driver |
task i2c_slave_driver_initialize; |
sda_o = 1'b1; |
scl_o = 1'b1; |
pif.scl_oe = 1'b1; |
state = 3'b000; |
slave_state = 3'b000; |
slave_start_sig = 1'b1; |
sta = 1'b0; |
sto = 1'b0; |
endtask |
|
// This task will invoke parallel threads which will be running continuously throughout the simulation. // |
task set_always; |
fork |
shift_reg; |
set_sda; |
set_scl; |
bit_count; |
detect_start; |
detect_stop; |
set_mem_out; |
delayed_start; |
acc_done_check; |
address_check; |
generate_scl; |
generate_start; |
set_data_out; |
set_load_first_data_flag; |
join |
endtask |
|
// This Task will be shifting sr register. On every scl clock it will get the data from sda line and // |
// that data will be copied to lsb of sr register and data will be shifted left bit by bit. // |
task shift_reg; |
forever @(posedge pif.scl) |
begin |
if (sta) sr = #1 {sr[6:0],pif.sda}; |
end |
endtask |
|
// This task will be counting no. of scl clock events. When ld (load Count) is one, it will initialize // |
// the counter, otherwise it will decrement the count by one on every posedge of scl // |
task bit_count; |
forever @(posedge pif.scl) |
begin |
if(ld) |
bit_cnt = #1 3'b111; |
else |
bit_cnt = #1 bit_cnt - 3'b001; |
end |
endtask |
|
// This task will be comparing the slave address being received on sda line and the address assigned to // |
// this transactor. It sets the flag when addresses match. // |
task address_check; |
forever @(posedge pif.clk) |
begin |
my_adr_flag = (sr[7:1] == slave_address); |
if (my_adr_flag && !(my_adr)) |
my_adr = #1 1'b1; |
end |
endtask |
|
// This task will set the flag load_first_data_flag |
task set_load_first_data_flag; |
forever @(posedge pif.scl) |
begin |
load_first_data_flag = my_adr; |
end |
endtask |
|
// This task will check whether 8 bits have been transmitted or received. In other words it checks the // |
// bit-Count. Sets the flag when 8 bits transaction is done. // |
task acc_done_check; |
forever @(posedge pif.clk) |
begin |
acc_done = !(|bit_cnt); |
end |
endtask |
|
// This task will detect start signal on sda line. It sets flags when start signal is detected. // |
task detect_start; |
forever @(negedge pif.sda) |
if(pif.scl) |
begin |
sta = #1 1'b1; |
d_sta = #1 1'b0; |
sto = #1 1'b0; |
my_adr = 1'b0; |
end |
else sta = #1 sta; |
endtask |
|
// This task will detect stop signal on sda line. It sets flags when stop signal is detected. // |
task detect_stop; |
forever @(posedge pif.sda); |
if(pif.scl) |
begin |
sta = #1 1'b0; |
sto = #1 1'b1; |
end |
else sto = #1 1'b0; |
endtask |
|
// This task assign start signal to delayed version of start. // |
task delayed_start; |
forever @(posedge pif.scl) |
d_sta = #1 sta; |
endtask |
|
// This task shifts bitwise data of mem_out. MSB of this register is transmitted when I2C M/S works as // |
// a Trasnmitter. // |
task set_mem_out; |
forever @(posedge pif.scl) |
begin |
if(!acc_done && rw) |
mem_out = #1 {mem_out[6:0],1'b1}; |
end |
endtask |
|
// This task assign sda_o (local sda_o data) to interface sda_oe. // |
task set_sda; |
begin |
forever |
begin |
#5; |
temp = slave_start_sig & sda_o; |
if(slave_stop_sig) |
begin |
if(!pif.scl) |
pif.sda_oe = 1'b0; |
else |
#100 pif.sda_oe = 1'b1; |
end |
else |
pif.sda_oe = temp; |
end |
end |
endtask |
|
// This task assigns value of local scl_o to interface port scl_o // |
task set_scl; |
forever begin |
#10; pif.scl_oe = scl_o; |
end |
endtask |
|
|
// This task will generate SCL clk when I2C Master/Slave Driver (this one) is working in Master mode. |
task generate_scl; |
int s_clk_gen_count = 0; |
forever @(posedge pif.clk) |
begin |
if(core_master_slave == 1'b0) |
begin |
if(s_clk_gen_count == 49) |
begin |
scl_o = ~scl_o; |
s_clk_gen_count = 0; |
end |
else |
s_clk_gen_count++; |
end |
end |
endtask |
|
// This task will generate Start Signal on sda line when This Driver is working in Master Mode. |
task generate_start; |
if(core_master_slave == 1'b0) |
begin |
#100; |
forever |
begin |
if(sta != 1'b1 && !(core_master_slave) && !(s_temp_stim_packet.reset_check) && !(s_temp_stim_packet.reset_check)) |
begin |
@(posedge pif.scl) |
begin |
if(sta != 1'b1 && !(core_master_slave)) |
begin |
#100 slave_start_sig = 1'b0; |
end |
end |
@(negedge pif.scl) slave_start_sig = 1'b1; |
end |
#100; |
end |
end |
endtask |
|
// This task will set data out on posedge of scl // |
task set_data_out; |
forever @(posedge pif.scl) |
begin |
if(!acc_done || shift_data_out) |
begin |
data_out = #1 {data_out[6:0],1'b1}; |
#2; |
end |
end |
endtask |
|
|
// process task |
task process; |
forever |
begin |
s_stim_packet = new; |
s_stim_req_chan.peek(s_stim_packet); |
$cast(s_temp_stim_packet,s_stim_packet.copy()); |
`vmm_note(log, "***********Packet Received inside I2C_SLAVE_DRIVER from GENERATOR************"); |
s_temp_stim_packet.display(); |
slave_address = s_temp_stim_packet.slave_address; |
byte_count = s_temp_stim_packet.byte_count; |
slave_data_out = new[byte_count]; |
slave_data_out = s_temp_stim_packet.data_packet; |
core_master_slave = s_temp_stim_packet.master_slave; |
tr = s_temp_stim_packet.tr; |
#1; |
// $display("begining of task process mem_out is %b and byte_count is %d and slave_address is %b", mem_out, byte_count, slave_address); |
i = 0; |
|
if(my_adr_flag && !(load_first_data_flag)) |
begin |
mem_out = slave_data_out[0]; |
end |
|
// If load_data is set, it will copy a new data byte from slave_data_out array to mem_out register. |
// This mem_out register's data will be outputed on sda line. |
if(load_data) |
begin |
mem_out = slave_data_out[byte_count - sent_data_count]; |
// `vmm_callback |
if(core_master_slave == 1) |
begin |
s_sb_pkt.master_slave = 1'b1; |
s_sb_pkt.tx_rx = 1'b0; |
end |
else |
begin |
s_sb_pkt.master_slave = 1'b0; |
s_sb_pkt.tx_rx = 1'b1; |
end |
s_sb_pkt.slave_address = s_temp_stim_packet.slave_address; |
s_sb_pkt.data_byte = mem_out; |
// $display("Callback for pre_transaction in slave driver at %t", $time); |
`vmm_callback(i2c_callback,pre_transaction(s_sb_pkt)); |
// vmm_callback |
load_data = 1'b0; |
end |
|
// When reset_check test case is begin run on W/B driver side (DUT) this driver will not do any operation. |
if(s_temp_stim_packet.reset_check) |
begin |
`vmm_note(log, $psprintf("SLave_Driver: Checking reset operation of DUT at %t", $time)); |
repeat (10) @(posedge pif.clk); |
i2c_slave_driver_initialize; |
s_stim_req_chan.get(s_stim_packet); |
end |
|
// When register_check test case is begin run on W/B driver side (DUT) this driver will not do any operation. |
else if(s_temp_stim_packet.register_check) |
begin |
`vmm_note(log, $psprintf("SLave_Driver: Checking register test operation of DUT at %t", $time)); |
repeat (10) @(posedge pif.clk); |
i2c_slave_driver_initialize; |
s_stim_req_chan.get(s_stim_packet); |
end |
|
// Data-Transmisstion test-case is being run now. This Core (I2C M/S) is working as a Slave Device |
else if(core_master_slave) //In slave mode |
begin |
@(negedge pif.scl or posedge sto) |
begin |
if(sto || (sta && !d_sta)) |
begin |
sda_o = #1 1'b1; |
//scl_o = #1 1'b1; |
ld = #1 1'b1; |
state = #1 3'b000; |
end |
else |
begin |
sda_o = #1 1'b1; |
ld = #1 1'b0; |
end |
|
// Case 000 will be checking whether 8 bits of transaction is done, Address matches and rd/wr bit. // |
// It will assign next state to state 001, which is Address Acknowledgment State. // |
case (state) |
3'b000: |
begin |
if(acc_done && my_adr) |
begin |
rw = #1 sr[0]; |
sda_o = #5 1'b0; |
#2; |
if(rw) |
begin |
sent_data_count = byte_count; |
// if(sent_data_count != 0) |
//s_rsp_port.put(1); |
// #1; |
end |
else if (!rw) |
begin |
received_data_count = byte_count; |
end |
state = #1 3'b001; |
end |
end |
|
// Case 001 is Acknowledgment state for address. It checks rd/wr bit received with slave address // |
// Then for I2C M/S Core(this dirver) as a Transmitter, next state will be assigned to 010 and send // |
// slave address acknowledgment signal. For I2C M/S Core (This driver) as a Receiver, next state // |
// will be assigned to 011. Then it sets load_count bit. // |
3'b001: |
begin |
if(rw) |
begin |
state = #1 3'b010; // read state |
// `vmm_callback |
s_sb_pkt.master_slave = 1'b1; |
s_sb_pkt.tx_rx = 1'b0; |
s_sb_pkt.slave_address = s_temp_stim_packet.slave_address; |
s_sb_pkt.data_byte = mem_out; |
// $display("Callback for pre_transaction in slave driver at %t", $time); |
`vmm_callback(i2c_callback,pre_transaction(s_sb_pkt)); |
sda_o = #1 mem_out[7]; |
end |
else |
state = #1 3'b011; // write state |
ld = #2 1'b1; |
end |
|
// When I2C M/S DUT is acting as a Master trasnmitter and access is done, it will send msb of // |
// mem_out to sda_o which will get assigned to sda_oe line on interface. When Access is done, // |
// next State will be assigned to 100, which is Data Acknowledgment state. It also checks // |
// whether byte_count is 0. If it is not 0, load_data will be set to 1 for next byte. // |
3'b010: |
begin |
if(rw) |
#1 sda_o = mem_out[7]; |
|
if(acc_done) |
begin |
sda_o = #1 rw; |
state = #1 3'b100; // Data Acknoledgment |
if(rw) |
begin |
sent_data_count --; |
if(sent_data_count != 0) |
load_data = 1'b1; |
end |
end |
end |
|
// When I2C M/S core (this core) is acting as a receiver and access is done, it will get data_byte // |
// from shift register sr and send acknowledgement signal to interface through sda_o signal. Next // |
// State will be assigned to 100, which is Data Acknowledgment state. // |
3'b011: |
begin |
if(acc_done) |
begin |
mem_in = #1 sr; |
sda_o = #1 1'b0; |
// `vmm_callback |
s_sb_pkt.master_slave = 1'b1; |
s_sb_pkt.tx_rx = 1'b0; |
s_sb_pkt.slave_address = s_temp_stim_packet.slave_address; |
s_sb_pkt.data_byte = mem_in; |
// $display("Callback for post_transaction in slave driver when DUT is in master at %t", $time); |
`vmm_callback(i2c_callback,post_transaction(s_sb_pkt)); |
// vmm_callback |
state = #1 3'b100; // Data Acknoledgment |
end |
// #1; |
end |
|
// This is Data Acknowledgment State. When I2C M/S Core (this driver) is acting as a trasmitter and when after // |
// sending data byte it doesn't get acknowledgment from Master DUT, next state will assigned to 000. // |
// If it gets the acknoeledgment, next state will be assigned to 010. Similerly when I2C M/S core (this core) // |
// as a receiver, next state will be assigned to 011. // |
3'b100: |
begin |
ld = #1 1'b1; |
if(rw) |
begin |
if(sr[0]) // read and master send NACK |
begin |
sda_o = #1 1'b1; |
state = 3'b000; |
end |
else |
begin |
sda_o = mem_out[7]; |
//if(byte_count == 0) |
if(sent_data_count == 0) |
begin |
state = 3'b000; |
ld = 1'b0; |
#5000 s_stim_req_chan.get(s_stim_packet); |
i2c_slave_driver_initialize; |
end |
else |
state = 3'b010; |
end |
end |
else |
begin |
received_data_count--; |
if(received_data_count != 0) |
begin |
state = #1 3'b011; |
sda_o = #1 1'b1; |
end |
else |
begin |
#5000 s_stim_req_chan.get(s_stim_packet); |
i2c_slave_driver_initialize; |
end |
end |
end |
default : $display("default case"); |
endcase |
end // @(negedge pif.scl or posedge sto) |
end // (s_stim_packet.master_slave)) |
|
// Data Transmission test-case and this core (I2C M/S Core) is working as a Master Device. |
else if(core_master_slave == 1'b0) // This core works as in master mode (DUT core in slave mode) |
begin |
#100; |
rw = tr; |
shift_data_out = 1'b1; |
@(negedge pif.scl) |
begin |
if(sto || (sta && !d_sta)) |
begin |
data_out = {slave_address,!tr}; |
ld = 1'b1; |
slave_state = #1 3'b000; |
end |
else |
begin |
ld = 1'b0; |
end |
|
case(slave_state) |
|
// State 000 will be generating SCL and then check Ack bit and accordingly set next state. // |
// For I2C M/S Core(this driver) as a Transmitter it will be setting next state to 001 and // |
// for I2C M/S Core(this dirver) to be a Receiver this will be setting next state to 010. // |
3'b000: |
begin |
if(acc_done && slave_bit_count > 7) |
begin |
sent_data_count = byte_count; |
received_data_count = byte_count; |
ld = #2 1'b1; |
slave_state = 3'b001; |
sda_o = 1'b1; |
@(posedge pif.scl) |
begin |
slave_ack = pif.sda; |
if(!slave_ack && tr) // This slave will be sending data to DUT core |
begin |
mem_out = slave_data_out[0]; |
end |
else if (!slave_ack && !tr) // This slave will be receiving data from DUT core |
begin |
// $display("slave ack is 0 and tr is 1 at %t", $time); |
end |
end |
end |
else |
begin |
if(sta) |
begin |
sda_o = data_out[7]; |
slave_bit_count++; |
end |
end |
end |
|
// Case 001 is Acknowledgment state for address. It checks rd/wr bit received with slave address // |
// Then for I2C M/S Core(this dirver) as a Transmitter, next state will be assigned to 010 and send // |
// slave address acknowledgment signal. For I2C M/S Core (This driver) as a Receiver, next state // |
// will be assigned to 011. Then it sets load_count bit. // |
3'b001: |
begin |
if(rw) |
begin |
slave_state = #1 3'b010; // I2C M/S Core (this dirver) transmit state |
// `vmm_callback |
s_sb_pkt.master_slave = 1'b0; |
s_sb_pkt.tx_rx = 1'b1; |
s_sb_pkt.slave_address = s_temp_stim_packet.slave_address; |
s_sb_pkt.data_byte = mem_out; |
// $display("Callback for pre_transaction in slave driver when DUT is in slave mode at %t", $time); |
`vmm_callback(i2c_callback,pre_transaction(s_sb_pkt)); |
// vmm_callback |
sda_o = #1 mem_out[7]; |
end |
else |
slave_state = #1 3'b011; // I2C M/S Core (this dirver) receive state |
|
ld = #2 1'b1; |
end |
|
// State 010 will be transmitting serial data from mem_out to sda_o. // |
// If 8 bits are transmitted (acc_done set) it will decrese the sent_data_count. // |
// If sent_data_count is not 0, it will set load_data to load new data into mem_out. // |
3'b010: |
begin |
#1 sda_o = mem_out[7]; |
if(acc_done) |
begin |
slave_state = 3'b100; |
sent_data_count--; |
if(sent_data_count != 0) |
load_data = 1'b1; |
end |
end |
|
// State 011 will be receiving data from sda_in. // |
// If 8 bits are received (acc_done set) it will copy sr into mem_in and // |
// decrese the received_data_count. // |
3'b011: |
begin |
if(acc_done) |
begin |
mem_in = #1 sr; |
sda_o = #1 1'b0; |
// `vmm_callback |
s_sb_pkt.master_slave = 1'b0; |
s_sb_pkt.tx_rx = 1'b0; |
s_sb_pkt.slave_address = s_temp_stim_packet.slave_address; |
s_sb_pkt.data_byte = mem_in; |
// $display("Callback for post_transaction in driver when DUT is in slave mode at %t", $time); |
`vmm_callback(i2c_callback,post_transaction(s_sb_pkt)); |
// vmm_callback |
slave_state = #1 3'b100; // Data Acknoledgment |
end |
// #1; |
end |
|
|
// State 100 is for acknowledgment of data byte tx/rx // |
// In transmit mode it will check ack from DUT and then if sent_data_count is not zero, // |
// It will set the next state to 010. If sent_data_count is 0, it will set next state // |
// to 000 and set all local variable to their initial values. // |
// Similerly, In Receive mode when received_data_count is not 0, it will set next state // |
// to 011. If its 0, next state will be set to 000 and set all local variable to their // |
// initial values. // |
3'b100: |
begin |
if(rw) |
begin |
sda_o = mem_out[7]; |
if(sent_data_count == 0) |
begin |
slave_state = 3'b000; |
ld = 1'b0; |
if(sto != 1'b1) |
#10 slave_stop_sig = 1'b1; |
else |
begin |
@(posedge pif.scl); |
begin |
#1000 slave_stop_sig = 1'b0; |
end |
end |
#1000 slave_stop_sig = 1'b0; |
slave_bit_count = 0; |
sda_o =1'b1; |
scl_o = 1'b1; |
sta = 1'b0; |
s_stim_req_chan.get(s_stim_packet); |
end |
else |
begin |
ld = #1 1'b1; |
slave_state = 3'b010; |
end |
end |
else |
begin |
received_data_count--; |
if(received_data_count != 0) |
begin |
slave_state = #1 3'b011; |
sda_o = #1 1'b1; |
ld = 1'b1; |
end |
else |
begin |
slave_state = 3'b000; |
ld = 1'b0; |
if(sto != 1'b1) |
#10 slave_stop_sig = 1'b1; |
else |
begin |
@(posedge pif.scl); |
begin |
#1000 slave_stop_sig = 1'b0; |
end |
end |
#1000 slave_stop_sig = 1'b0; |
slave_bit_count = 0; |
sda_o = 1'b1; |
scl_o = 1'b1; // to check scl generation when this core's mode got changed from m to s ... |
sta = 1'b0; |
s_stim_req_chan.get(s_stim_packet); |
end |
end |
end |
endcase |
end |
end |
else |
begin |
#10; |
// $display("Slave Driver: no condition matches"); |
end |
end |
endtask |
|
virtual protected task main(); |
super.main(); |
begin |
fork |
i2c_slave_driver_initialize; |
set_always; |
process; |
join |
end |
endtask |
|
|
endclass |
|
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_monitor.sv
New file
0,0 → 1,205
////////////////////////////////////////////////////////////////////////////////////////// |
// // |
// Verification Engineer: Atish Jaiswal // |
// Company Name : TooMuch Semiconductor Solutions Pvt Ltd. // |
// // |
// Description of the Source File: // |
// This source code implements I2C Master-Slave Monitor. // |
// Monitor does protocol validations. It checks generation of Start, Stop, interrupt // |
// request, slave and data acknowledgment for every trnasaction. It will create // |
// monitor packet on every transaction and send that packet to Coverage Module. // |
// // |
////////////////////////////////////////////////////////////////////////////////////////// |
|
`include "vmm.sv" |
|
class i2c_monitor extends vmm_xactor; |
|
vmm_log log = new("lOG", "MONITOR"); |
virtual i2c_pin_if pif; // Virtual Interface |
stimulus_packet mon_stim_packet; // Stimulus Packet |
stimulus_packet temp_mon_stim_packet; // Stimulus Packet |
monitor_pkt mon_pkt; // Monitor Packet |
|
// Class Constructor |
function new(string name, string instance, virtual i2c_pin_if pif); |
super.new("Monitor","I2C_MONITOR"); |
mon_stim_packet = new; |
temp_mon_stim_packet = new; |
mon_pkt = new; |
this.pif = pif; |
endfunction |
|
reg sta, d_sta; // Local Variable of start and delayed start |
reg sto, d_sto; // Local variable of stop and delayed stop |
reg slave_ack; // Local Variable for Slave Acknowledgment |
reg data_ack; // Local variable for Data Acknowledgment |
reg intr_ack; // Local variable for Genaration of Interrupt |
reg first_stop_flag; // Local variable for First Stop bit |
integer local_byte_count; // Track byte_count |
integer ack_count; // Track Acknowledgment pulse count |
integer intr_count; // Track Interrupt Count |
reg [3:0] bit_count; // 3-bit Counter |
reg load_counter; // load_counter flag |
|
|
// This task gets packet from driver. Though this call monitor will be aware of what kind of test-case is being run. |
task get_packet_from_driver(stimulus_packet mon_stim_packet); |
`vmm_note(log, $psprintf("Received Packet IN MONITOR at time %t", $time)); |
$cast(temp_mon_stim_packet, mon_stim_packet.copy()); |
temp_mon_stim_packet.display(); |
endtask |
|
// Initialize the local variables of Monitor |
task initialize; |
sta = 1'b0; |
d_sta = 1'b0; |
sto = 1'b0; |
d_sto = 1'b0; |
slave_ack = 1'b0; |
data_ack = 1'b0; |
intr_ack = 1'b0; |
bit_count = 4'h0; |
load_counter = 1'b0; |
ack_count = 0; |
intr_count = 0; |
endtask |
|
|
// This task will be counting no. of scl clock events. When load_counter is one, it will initialize // |
// the counter, otherwise it will decrement the count by one on every posedge of scl // |
task bit_counter; |
forever @(posedge pif.scl) |
begin |
if(load_counter) |
bit_count = 4'h8; |
else |
bit_count = bit_count - 4'h1; |
end |
endtask |
|
// This task will detect start signal on sda line. It sets flags when start signal is detected. // |
task detect_start; |
forever @(negedge pif.sda) |
if(pif.scl) |
begin |
sta = #1 1'b1; |
d_sta = #1 1'b0; |
sto = #1 1'b0; |
load_counter = 1'b1; |
end |
else sta = #1 sta; |
endtask |
|
// This task will detect stop signal on sda line. It sets flags when stop signal is detected. // |
task detect_stop; |
forever @(posedge pif.sda) |
if(pif.scl) |
begin |
sto = #1 1'b1; |
end |
else sto = #1 1'b0; |
endtask |
|
// This task assign start signal to delayed version of start. // |
task delayed_start; |
forever @(posedge pif.scl) |
d_sta = #1 sta; |
endtask |
|
// This task assign stop signal to delayed version of start. // |
task delayed_stop; |
forever @(posedge pif.clk) |
d_sto = #1 sto; |
endtask |
|
// This task will detect interrupt signal on sda line. If bit_count is 0, it will increment intr_count. // |
task detect_intr; |
forever @(posedge pif.irq) |
begin |
if(bit_count == 0) |
intr_count++; |
else if(bit_count != 0 && temp_mon_stim_packet.intr_en && !(temp_mon_stim_packet.register_check) && !(temp_mon_stim_packet.reset_check)) |
`vmm_error(log, "INTERRUPT SIGNAL NOT GENERATED ON RIGHT TIME"); |
end |
endtask |
|
// Process Task |
task process; |
forever @(posedge pif.scl or posedge sto) |
begin |
if(sta && !(d_sta) && !(sto)) // First SCL posedge after Start pulse |
begin |
load_counter = 1'b0; |
`vmm_note(log, $psprintf("START DETECTED IN MONITOR AT %t", $time)); |
end |
else if (sta && d_sta && !(sto)) |
begin |
load_counter = 1'b0; |
// It checks the value of sda line when bit_count is 0 for acknowledgment. First Acknowledgment pulse is Slave Acknowledgment |
// and from then it will be Data acknowldgment. |
if(bit_count == 4'h0 && !pif.sda) |
begin |
if(ack_count == 0) |
`vmm_note(log,$psprintf("SLAVE ADDRESS ACKNOWLEDGMENT DETECTED AT %t", $time)); |
else |
`vmm_note(log,$psprintf("DATA ACKNOWLEDGMENT DETECTED AT %t", $time)); |
ack_count++; |
load_counter = 1'b1; |
end |
end |
else if (sto && !(d_sto)) |
begin |
if(!first_stop_flag) |
first_stop_flag = 1'b1; |
else |
begin |
// Checks whether the testcase being run is not of register_check or reset_check type. |
if(!(temp_mon_stim_packet.register_check) && !(temp_mon_stim_packet.reset_check)) |
begin |
`vmm_note(log, $psprintf("STOP DETECTED IN MONITOR AT %t", $time)); |
if(!(sta || d_sta)) |
`vmm_error(log, "START PULSE NOT DETECTED"); |
if(temp_mon_stim_packet.byte_count != (ack_count-1)) |
`vmm_error(log, "ACKNOWLEDGMENT NOT DETECTED"); |
if(temp_mon_stim_packet.intr_en && temp_mon_stim_packet.byte_count != (intr_count-1)) |
`vmm_error(log, "INTERRUPT BIT NOT CLEARED FOR ALL INTERRUPT MODE TRANSACTIONS"); |
if (sta) |
begin |
// Create a monitor pkt and sent it to and coverage module through callback |
mon_pkt.start_bit = 1'b1; |
mon_pkt.stop_bit = 1'b1; |
mon_pkt.slave_ack = 1'b1; |
mon_pkt.data_ack = 1'b1; |
mon_pkt.intr_ack = 1'b1; |
`vmm_callback(i2c_callback,protocol_checks_coverage(mon_pkt)); |
@(posedge pif.clk) initialize; |
end |
end |
end |
end |
end |
endtask |
|
// Main Task |
virtual protected task main(); |
super.main(); |
begin |
first_stop_flag = 1'b0; |
fork |
initialize; |
bit_counter; |
delayed_start; |
delayed_stop; |
detect_start; |
detect_stop; |
detect_intr; |
process; |
join |
end |
endtask |
|
endclass |
|
|
|
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_env.sv
New file
0,0 → 1,187
////////////////////////////////////////////////////////////////////////////////////////// |
// // |
// Verification Engineer: Atish Jaiswal // |
// Company Name : TooMuch Semiconductor Solutions Pvt Ltd. // |
// // |
// Description of the Source File: // |
// This source code Creates VMM Environment of the I2C M/S Core. // |
// // |
// // |
// // |
////////////////////////////////////////////////////////////////////////////////////////// |
|
`include "vmm.sv" |
`include "config.sv" |
`include "vmm_i2c_interface.sv" |
//`include "debug_if.sv" |
`include "vmm_i2c_sb_pkt.sv" |
`include "vmm_i2c_mon_pkt.sv" |
`include "vmm_i2c_reg_pkt.sv" |
`include "vmm_i2c_scenario_packet.sv" |
`include "vmm_i2c_stimulus_packet.sv" |
`include "vmm_i2c_data_packet.sv" |
`include "vmm_i2c_scenario_generator.sv" |
`include "sb_callback.sv" |
`include "vmm_i2c_driver.sv" |
`include "vmm_i2c_slave_driver.sv" |
|
class i2c_env extends vmm_env; |
|
vmm_log log = new("log", "ENV"); |
virtual i2c_pin_if pif; // Virtual Interface |
i2c_scenario_generator sc_gen; // Scenario Generator |
configuration cfg; // Configuration Class |
stimulus_packet_channel m_stim_req_chan; // Scenarion_gen to W/B Driver Channel |
stimulus_packet_channel s_stim_req_chan; // Scenarion_gen to I2C M/S Driver Channel |
i2c_master_driver m_driver_xactor; // W/B Driver Xactor |
i2c_slave_driver s_driver_xactor; // I2C Driver Xactor |
i2c_scoreboard i2c_sb; // Scoreboard |
sb_callback sb_c; // Sb_Callback |
i2c_coverage i2c_cov; // Coverage_Module |
i2c_monitor i2c_mon; // Monitor |
|
bit rand_tran = 1'b0; // Rand_mode |
integer transaction_count; // No. of Transaction |
|
// Class Constructor |
function new(virtual i2c_pin_if pif); |
super.new("MY_ENV"); |
this.pif = pif; |
// this.d_if = d_if; |
$value$plusargs("transaction_count=%d",transaction_count); |
$value$plusargs("rand_trans=%b",rand_tran); |
cfg = new(); |
endfunction |
|
|
//Gen Config Function. If rand_trans is 1 then this will randomize trasaction_count in config class |
virtual function void gen_cfg(); |
super.gen_cfg(); |
`vmm_note(log, "inside gen_cfg"); |
if(rand_tran) |
begin |
if(!cfg.randomize()) |
`vmm_error(log,"Configuration Randomization Failed"); |
transaction_count = cfg.transaction_count; |
end |
endfunction |
|
// Build function to all Connections Initializaion |
virtual function void build(); |
super.build(); |
m_stim_req_chan = new("master_stimulus_packet_channel", "m_stim_req_chan"); |
s_stim_req_chan = new("slave_stimulus_packet_channel", "s_stim_req_chan"); |
sc_gen = new("scenario_generator", "generator", m_stim_req_chan, s_stim_req_chan); |
m_driver_xactor = new("i2c_master_driver", "m_driver_xactor", this.pif, m_stim_req_chan); |
s_driver_xactor = new("i2c_slave_driver", "s_driver_xactor", this.pif, s_stim_req_chan); |
sc_gen.transaction_count = transaction_count; |
i2c_sb = new("I2C_Scoreboard", "SCOREBOARD"); |
i2c_cov = new("I2C_Coverage", "COVERAGE"); |
i2c_mon = new("I2C_Monitor", "MONITOR",this.pif); |
sb_c = new(i2c_sb, i2c_cov, i2c_mon); |
m_driver_xactor.append_callback(sb_c); |
s_driver_xactor.append_callback(sb_c); |
i2c_mon.append_callback(sb_c); |
endfunction |
|
// Reset DUT task. It will reset dut for 5 system clk cycle |
virtual task reset_dut(); |
super.reset_dut(); |
m_driver_xactor.set_enable_signals; |
pif.rst = 1; |
repeat(5) |
begin |
@(posedge pif.clk); |
pif.rst = 0; |
end |
`vmm_note(log, "inside reset_dut"); |
endtask |
|
// cfg dut task for configuration of DUT. |
virtual task cfg_dut(); |
super.cfg_dut(); |
`vmm_note(log, "inside cfg_dut"); |
endtask |
|
// Start Transactor task. This will start all transactor in the Environment. |
virtual task start(); |
super.start(); |
sc_gen.start_xactor(); |
m_driver_xactor.start_xactor(); |
s_driver_xactor.start_xactor(); |
i2c_mon.start_xactor(); |
`vmm_note(log, "inside start"); |
endtask |
|
// Wait for end task. It will wait for Done signal from Scenario Generartor. |
virtual task wait_for_end(); |
super.wait_for_end(); |
`vmm_note(log, "inside wait_for_end"); |
`vmm_note(log, "inside wait_for_end: before wait for done"); |
this.sc_gen.notify.wait_for(this.sc_gen.DONE); |
`vmm_note(log, "inside wait_for_end: Affter wait for done"); |
endtask |
|
// Report Task |
virtual task report(); |
super.report(); |
// i2c_sb.sb_display(); |
`vmm_note(log, "inside report"); |
endtask |
|
// Clean-up task |
virtual task cleanup(); |
super.cleanup(); |
`vmm_note(log, "inside cleanup"); |
endtask |
|
endclass |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/config.sv
New file
0,0 → 1,27
////////////////////////////////////////////////////////////////////////////////////////// |
// // |
// Verification Engineer: Atish Jaiswal // |
// Company Name : TooMuch Semiconductor Solutions Pvt Ltd. // |
// // |
// Description of the Source File: // |
// This source code is used to configure the test-case. // |
// This class randmomize the no. of transactions. // |
// // |
// // |
////////////////////////////////////////////////////////////////////////////////////////// |
|
`include "vmm.sv" |
|
class configuration; |
|
rand int transaction_count; // No. of transaction to be done |
|
function new(); |
endfunction |
|
constraint valid { |
transaction_count inside {[0:44]}; |
} |
|
endclass |
|
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_program1_test.sv
New file
0,0 → 1,134
////////////////////////////////////////////////////////////////////////////////////////// |
// // |
// Verification Engineer: Atish Jaiswal // |
// Company Name : TooMuch Semiconductor Solutions Pvt Ltd. // |
// // |
// Description of the Source File: // |
// This source code is written to apply directed test-case to I2C M/S core. // |
// This test-case will be written to apply write-write-read operation on register // |
// test-case. // |
// // |
////////////////////////////////////////////////////////////////////////////////////////// |
|
`include "vmm.sv" |
`include "vmm_i2c_env.sv" |
`include "vmm_clkgen.sv" |
|
class i2c_scenario_generator1 extends i2c_scenario_generator; |
int transaction_count; |
byte reg_addr[5] = {8'h02, 8'h04, 8'h0A, 8'h0C, 8'h0E}; |
|
function new( string name, string instance_name, stimulus_packet_channel m_req_chan = null, stimulus_packet_channel s_req_chan = null); |
super.new("scenario_generator ", "scenario_generator"); |
if(m_req_chan == null) m_req_chan = new("master_stimulus_packet_channel", "m_req_chan"); |
this.m_req_chan = m_req_chan; |
if(s_req_chan == null) s_req_chan = new("slave_stimulus_packet_channel", "s_req_chan"); |
this.s_req_chan = s_req_chan; |
this.DONE = this.notify.configure(1,vmm_notify::ON_OFF); |
sc_packet = new; |
stim_packet = new; |
d_pkt = new; |
$value$plusargs("transaction_count=%d",transaction_count); |
$value$plusargs("rand_gen=%b",rand_gen); |
$value$plusargs("master_slave=%b",master_slave); |
$value$plusargs("register_check=%b",register_check); |
$value$plusargs("reset_check=%b",reset_check); |
$value$plusargs("tx_rx=%b",tx_rx); |
endfunction |
|
|
// Main task |
virtual protected task main(); |
begin |
stim_packet.master_slave = 1'b1; |
stim_packet.tr = 1'b1; |
stim_packet.register_check = 1'b1; |
stim_packet.reset_check = 1'b0; |
// For all internal register |
foreach (reg_addr[i]) |
begin |
stim_packet.register_addr = reg_addr[i]; |
// Writing into registers twice |
for (int j = 1; j <=2 ; j++) |
begin |
stim_packet.register_data = {reg_addr[i]+j}; |
stim_packet.intr_en = 1'b1; |
this.m_req_chan.put(stim_packet); // sending packet to master driver |
this.s_req_chan.put(stim_packet); // sending packet to slave driver |
end |
// Reading Registers |
stim_packet.intr_en = 1'b0; |
this.m_req_chan.put(stim_packet); // sending packet to master driver |
this.s_req_chan.put(stim_packet); // sending packet to slave driver |
end |
notify.indicate(DONE); |
end |
endtask |
|
endclass |
|
|
//-------------------- Program Block -------------------------- |
program program_test(i2c_pin_if pif); |
|
i2c_scenario_generator1 i2c_sc_gen1; |
initial begin |
i2c_env env; |
env = new(pif); |
env.build(); |
i2c_sc_gen1 = new("new_scenario_generator", "generator", env.m_stim_req_chan, env.s_stim_req_chan); |
env.sc_gen = i2c_sc_gen1; // Assigning a new Scenario Generator to handle of Old Scenarion Gen in env. |
env.run(); |
end |
endprogram |
//------------------------------------------------------------- |
|
|
|
//---------------------- Module Top -------------------- |
module top; |
|
i2c_pin_if pif(); |
clkgen c_gen(pif); |
program_test p_test(pif); |
|
wire dut_sda_o; |
wire dut_sda_oe; |
wire dut_sda_in; |
wire dut_scl_o; |
wire dut_scl_oe; |
wire dut_scl_in; |
wire temp; |
wire temp_scl; |
assign dut_sda_o = 1'b0; |
|
assign temp = pif.sda_oe & dut_sda_oe; |
assign temp_scl = pif.scl_oe & dut_scl_oe; |
assign pif.sda = temp ? 1'bz : 1'b0; |
assign pif.scl = temp_scl ? 1'bz : 1'b0; |
pullup p1_if(pif.sda); |
pullup p2_if(pif.scl); |
|
|
block i2c_core( .scl_in(pif.scl), |
.scl_o(dut_scl_o), |
.scl_oe(dut_scl_oe), |
.sda_in(pif.sda), |
.sda_o(dut_sda_o), |
.sda_oe(dut_sda_oe), |
.wb_add_i(pif.addr_in), |
.wb_data_i(pif.data_in), |
.wb_data_o(pif.data_out), |
.wb_stb_i(pif.wb_stb_i), |
.wb_cyc_i(pif.wb_cyc_i), |
.wb_we_i(pif.we), |
.wb_ack_o(pif.ack_o), |
.irq(pif.irq), |
.trans_comp(pif.trans_comp), |
.wb_clk_i(pif.clk), |
.wb_rst_i(pif.rst) |
); |
|
endmodule |
|
|
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_scenario_packet.sv
New file
0,0 → 1,57
////////////////////////////////////////////////////////////////////////////////////////// |
// // |
// Verification Engineer: Atish Jaiswal // |
// Company Name : TooMuch Semiconductor Solutions Pvt Ltd. // |
// // |
// Description of the Source File: // |
// This file is the packet class for Scenario Generator. // |
// The Packet Randomizes Master/Slave bit,(1 for configuring DUT as a Master and 0 for // |
// Slave), tx_rx bit, which determines the direction of data to be transfered. // |
// It also randomize reset_check and register_check to enable/disable reset or register// |
// testcases. Transacation_count will be assigned from environment itself. // |
// // |
// // |
////////////////////////////////////////////////////////////////////////////////////////// |
|
|
`include "vmm.sv" |
|
class scenario_packet extends vmm_data; |
|
vmm_log log; |
|
randc bit master_slave ; // 1 for master and and 0 for slave |
int transaction_count; // No. of transaction to be done |
rand bit register_check; // to check register read/write |
rand bit reset_check; // to check reset |
rand bit tx_rx ; // 1 for transmit and and 0 for receive |
|
|
function new(); |
super.new(this.log); |
this.log = new("Scenario data", "class"); |
endfunction |
|
function void display(); |
this.log.start_msg(vmm_log::NOTE_TYP); |
void'(this.log.text($psprintf("Master/Slave mode is = %b\n", master_slave))); |
void'(this.log.text($psprintf("transaction_count = %d\n", transaction_count))); |
void'(this.log.text($psprintf("register_check = %b\n", register_check))); |
void'(this.log.text($psprintf("reset_check = %b\n", reset_check))); |
void'(this.log.text($psprintf("tx_rx = %b\n", tx_rx))); |
this.log.end_msg(); |
endfunction |
|
|
function vmm_data copy(vmm_data to = null); |
copy = new this; |
endfunction |
|
constraint valid_scenario { |
reset_check dist {1 := 1 , 0 := 20}; |
register_check dist { 1 := 1 , 0 := 20}; |
} |
|
endclass: scenario_packet |
|
|
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_coverage.sv
New file
0,0 → 1,181
////////////////////////////////////////////////////////////////////////////////////////// |
// // |
// Verification Engineer: Atish Jaiswal // |
// Company Name : TooMuch Semiconductor Solutions Pvt Ltd. // |
// // |
// Description of the Source File: // |
// This Source Code Implements Coverage Collector. // |
// This Coverage Module contains 3 Covergroups. CG1 for data transaction and modes of // |
// of operation, CG2 for Register read-write testcases and CG3 for Protocol validation.// |
// All Covergroups are sampled on events which are triggered in different tasks. // |
// // |
////////////////////////////////////////////////////////////////////////////////////////// |
|
`include "vmm.sv" |
|
class i2c_coverage extends vmm_xactor; |
|
scoreboard_pkt cov_pkt; // Scoreboard_pkt's instance |
register_pkt reg_pkt; // register_pkt's instance |
monitor_pkt mon_pkt; // Monitor_pkt's instance |
event start_cov; // Event data_tye to sample cg1 |
event start_cov_reg; // Event data type to sample cg2 |
event start_protocol_checks_cov; // Event data type to sample cg3 |
|
// local variables which gets assigned object's data members in tasks |
bit [7:0] data_byte; |
bit master_slave; |
bit tx_rx; |
bit [6:0] slave_address; |
bit start_bit; |
bit stop_bit; |
bit slave_ack; |
bit data_ack; |
bit intr_ack; |
bit [7:0] reg_address; |
bit wr_rd; |
bit reset_bit; |
bit [8:0] reg_addr_txn; |
|
|
// Covergroup CG1. This Covergroup Generate Coverage for modes of operation. their cross coverpoint is defined as well. |
// This covergroup will be sampled on every event of start_cov variable. This event will be triggered in task pre_txn_start_cov. |
covergroup cg1 @start_cov; |
data_in : coverpoint data_byte { |
bins low = {[8'h00 : 8'h40]}; |
bins mid = {[8'h41 : 8'h80]}; |
bins high = {[8'h81: 8'hff]}; |
} |
m_s : coverpoint master_slave; |
tx_rx : coverpoint tx_rx; |
slave_addr: coverpoint slave_address { |
bins low = {[7'h00 : 7'h20]}; |
bins mid = {[7'h21 : 7'h40]}; |
bins high = {[7'h41: 7'h7f]}; |
} |
data_mode_cross : cross data_in, m_s, tx_rx; |
endgroup : cg1 |
|
// Covergroup CG2. This covergroup generate fucntion coverage for all register read-write operations. Cross Coverage is written |
// to check both read and write operation of all reigsters. Transaction Coverage is wrritten for write-write-read operations. |
// This covergroup is sampled on every event of start_cov_reg. |
covergroup cg2 @start_cov_reg; |
register_addr : coverpoint reg_address { |
bins prescale = {8'h02}; |
bins control = {8'h04}; |
bins timeout = {8'h0A}; |
bins address = {8'h0C}; |
bins data_tx = {8'h0E}; |
} |
write_read : coverpoint wr_rd { |
bins write = {1'b1}; |
bins read = {1'b0}; |
} |
cross_reg_addr_wr : cross register_addr, write_read; |
reset_test: coverpoint reset_bit { |
bins reset = {1'b1}; |
} |
prescale_txn : coverpoint wr_rd iff(reg_address == 8'h02) { |
bins wr_wr_rd = ( 1 => 1 => 0); |
} |
control_txn : coverpoint wr_rd iff(reg_address == 8'h04) { |
bins wr_wr_rd = ( 1'b1 => 1'b1 => 1'b0); |
} |
timeout_txn : coverpoint wr_rd iff(reg_address == 8'h0A) { |
bins wr_wr_rd = ( 1'b1 => 1'b1 => 1'b0); |
} |
address_txn : coverpoint wr_rd iff(reg_address == 8'h0C) { |
bins wr_wr_rd = ( 1'b1 => 1'b1 => 1'b0); |
} |
data_tx_txn : coverpoint wr_rd iff(reg_address == 8'h0E) { |
bins wr_wr_rd = ( 1'b1 => 1'b1 => 1'b0); |
} |
txn: coverpoint reg_addr_txn { |
bins pre = (9'h102 => 9'h102 => 9'h002); |
bins con = (9'h104 => 9'h104 => 9'h004); |
bins tim = (9'h10A => 9'h10A => 9'h00A); |
bins add = (9'h10C => 9'h10C => 9'h00C); |
bins dat = (9'h10E=> 9'h10E => 9'h00E); |
} |
endgroup |
|
|
// Covergroup CG3. This Covergroup is used to check fucntion coverage of all protocol validation. Cross Coverage is written to check |
// all protocol checks in every possible mode of operation. This Cover Group is sampled on every even of start_protocol_checks_cov. |
|
covergroup cg3 @start_protocol_checks_cov; |
start_bit : coverpoint start_bit { |
bins sta = {1'b1}; |
} |
stop_bit : coverpoint stop_bit { |
bins sto = {1'b1}; |
} |
slave_ack : coverpoint slave_ack { |
bins sl_ac = {1'b1}; |
} |
data_ack : coverpoint data_ack { |
bins da_ac = {1'b1}; |
} |
intr_ack : coverpoint intr_ack { |
bins int_ac = {1'b1}; |
} |
start_mode_cross : cross start_bit, master_slave, tx_rx; |
stop_mode_corss : cross stop_bit, master_slave, tx_rx; |
sack_mode_cross : cross slave_ack, master_slave, tx_rx; |
dack_mode_cross : cross data_ack, master_slave, tx_rx; |
inack_mode_cross : cross intr_ack, master_slave, tx_rx; |
endgroup |
|
|
// Class Constructor |
function new(string name, string instance); |
super.new("fifo_coverage_gen","COVERAGE_GEN"); |
cg1 = new; |
cg2 = new; |
cg3 = new; |
endfunction |
|
|
// This task will assign values of object's(cov_pkt) fields to local variables and then trigger the event start_cov to sample Covergroup CG1. |
task pre_txn_start_cov (scoreboard_pkt cov_pkt); |
this.cov_pkt = cov_pkt; |
data_byte = cov_pkt.data_byte; |
slave_address = cov_pkt.slave_address; |
master_slave = cov_pkt.master_slave; |
tx_rx = cov_pkt.tx_rx; |
-> start_cov; |
endtask |
|
// This task will assign values of object's(reg_pkt) fields to local variables and then trigger the event start_cov_reg to sample Covergroup CG2. |
task write_reg_cov (register_pkt reg_pkt); |
this.reg_pkt = reg_pkt; |
reg_address = reg_pkt.reg_address; |
wr_rd = reg_pkt.wr_rd; |
reset_bit = reg_pkt.reset_bit; |
reg_addr_txn = {wr_rd,reg_address}; |
-> start_cov_reg; |
endtask |
|
// This task will assign values of object's(reg_pkt) fields to local variables and then trigger the event start_cov_reg to sample Covergroup CG2. |
task read_reg_cov (register_pkt reg_pkt); |
this.reg_pkt = reg_pkt; |
reg_address = reg_pkt.reg_address; |
wr_rd = reg_pkt.wr_rd; |
reg_addr_txn = {wr_rd,reg_address}; |
-> start_cov_reg; |
endtask |
|
// This task will assign values of object's(mon_pkt) fields to local variables and then trigger the event start_protocol_checks_cov to |
// sample Covergroup CG2. |
task protocol_checks_cov (monitor_pkt mon_pkt); |
this.mon_pkt = mon_pkt; |
start_bit = mon_pkt.start_bit; |
stop_bit = mon_pkt.stop_bit; |
slave_ack = mon_pkt.slave_ack; |
data_ack = mon_pkt.data_ack; |
intr_ack = mon_pkt.intr_ack; |
-> start_protocol_checks_cov; |
endtask |
|
|
endclass |
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_driver.sv
New file
0,0 → 1,734
////////////////////////////////////////////////////////////////////////////////////////// |
// // |
// Verification Engineer: Atish Jaiswal // |
// Company Name : TooMuch Semiconductor Solutions Pvt Ltd. // |
// // |
// Description of the Source File: // |
// This source code implements W/B M/S Driver. // |
// Driver will be receiving Scenario packets from Stimulus gen and accordingly it // |
// will drive W/B ports of interface to configure DUT in different modes. // |
// In every mode of operation whenever DUT is configured in interupt mode, this driver // |
// waits for posedge of interrupt and then write commands/data to internal reigster of // |
// DUT. In normal mode where interrupt will not be generated, it keeps on checking // |
// Status register of DUT and act accordingly. // |
// // |
// // |
////////////////////////////////////////////////////////////////////////////////////////// |
|
`include "vmm.sv" |
|
class i2c_master_driver extends vmm_xactor; |
|
vmm_log log = new("lOG", "MASTER_DRIVER"); |
virtual i2c_pin_if pif; // Virtual Interface |
stimulus_packet_channel m_stim_req_chan; // Scenario Generator to Diver Channel |
stimulus_packet stim_packet; // Stimulus Packet's Instance |
stimulus_packet temp_stim_packet; // Stimulus Packet's Instance |
stimulus_packet response_packet; |
scoreboard_pkt sb_pkt; // Scoreboard Packet's instance for callback |
register_pkt reg_pkt; // Register Packet's instance for callback |
|
|
// Class Constructor |
function new(string name, string instance, virtual i2c_pin_if pif, stimulus_packet_channel m_stim_req_chan = null); |
super.new("driver","i2c_master_driver"); |
if(m_stim_req_chan == null) m_stim_req_chan = new("master_stimulus_packet_channel", "m_stim_req_chan"); |
this.m_stim_req_chan = m_stim_req_chan; |
stim_packet = new; |
temp_stim_packet = new; |
response_packet = new; |
sb_pkt = new; |
reg_pkt = new; |
this.pif = pif; |
endfunction |
|
|
|
/* task for initial setting */ |
task set_enable_signals; |
pif.rst = 1'b1; |
pif.clk = 1'b0; |
pif.wb_stb_i = 1'b0; |
pif.ack_o = 1'b0; |
pif.wb_cyc_i = 1'b0; |
#10 pif.rst = 1'b0; |
#20 write_inf(1,8'h04, 8'hD0); |
#40 write_inf(1,8'h04, 8'h00); |
endtask |
/* task for initial setting */ |
|
// Task to Enable core |
task enable_core; |
#20 write_inf(1,8'h04, 8'h80); |
reg_pkt.reg_address = 8'h04; |
reg_pkt.data_byte = 8'hD0; |
reg_pkt.wr_rd = 1'b1; |
reg_pkt.reset_bit = 1'b0; |
`vmm_callback(i2c_callback,write_reg(reg_pkt)); |
#40 write_inf(1,8'h04, 8'h00); |
reg_pkt.reg_address = 8'h04; |
reg_pkt.data_byte = 8'h00; |
reg_pkt.wr_rd = 1'b1; |
reg_pkt.reset_bit = 1'b0; |
`vmm_callback(i2c_callback,write_reg(reg_pkt)); |
endtask |
|
// Task to reset Core. This task is called from ENV. |
task set_reset; |
pif.rst = 1'b1; |
pif.clk = 1'b0; |
pif.wb_stb_i = 1'b0; |
pif.ack_o = 1'b0; |
pif.wb_cyc_i = 1'b0; |
repeat(2) @(posedge pif.clk); |
pif.rst = 1'b0; |
endtask |
|
// Task to set TimeOut Register's Value |
task set_timeout_reg; |
#40 write_inf(1,8'h0A, 8'hff); |
reg_pkt.reg_address = 8'h0A; |
reg_pkt.data_byte = 8'hff; |
reg_pkt.wr_rd = 1'b1; |
reg_pkt.reset_bit = 1'b0; |
`vmm_callback(i2c_callback,write_reg(reg_pkt)); |
endtask |
|
|
/* Write Task to write data and address on interface */ |
task write_inf; |
input delay; |
input [7:0] reg_addr; |
input [7:0] reg_value; |
integer delay; |
begin |
repeat(delay) @(posedge pif.clk) |
#1; |
pif.addr_in = reg_addr; |
pif.data_in = reg_value; |
pif.we = 1'b1; |
pif.wb_stb_i = 1'b1; |
pif.wb_cyc_i = 1'b1; |
@(posedge pif.clk) |
while (~pif.ack_o) @(posedge pif.clk) |
#1; |
pif.addr_in = {3{1'bx}}; |
pif.data_in = {8{1'bx}}; |
pif.we = 1'bx; |
pif.wb_stb_i = 1'bx; |
pif.wb_cyc_i = 1'b0; |
end |
endtask |
|
// Task to Set Prescale Register's Value |
task set_prescale_register; |
#40 write_inf(1,8'h02, 8'h64); |
reg_pkt.reg_address = 8'h02; |
reg_pkt.data_byte = 8'h64; |
reg_pkt.wr_rd = 1'b1; |
reg_pkt.reset_bit = 1'b0; |
`vmm_callback(i2c_callback,write_reg(reg_pkt)); |
endtask |
|
/* Read Task to read data from the design core through interface */ |
task read_inf; |
input delay; |
input [7:0] reg_addr; |
output [7:0] reg_value; |
integer delay; |
repeat(delay) @(posedge pif.clk) |
#1; |
pif.addr_in = reg_addr; |
pif.we = 1'b0; |
pif.wb_stb_i = 1'b1; |
pif.wb_cyc_i = 1'b1; |
pif.data_in = {8{1'bx}}; |
|
@(posedge pif.clk) |
while (~pif.ack_o) @(posedge pif.clk) |
#1; |
pif.wb_cyc_i = 1'b0; |
pif.we = 1'bx; |
pif.wb_stb_i = 1'bx; |
pif.addr_in = {3{1'bx}}; |
pif.data_in = {8{1'bx}}; |
reg_value = pif.data_out; |
endtask |
|
|
// task process; |
|
virtual protected task main(); |
super.main(); |
begin |
stimulus_packet stim_packet; |
int byte_count; |
reg intr_check; |
reg register_check; |
reg register_write; |
string s; |
reg [7:0] status_reg; |
reg [7:0] reg_data_register; |
forever |
begin |
m_stim_req_chan.peek(stim_packet); |
$cast(temp_stim_packet,stim_packet.copy()); |
`vmm_note(log, "***********Packet Received inside I2C_DRIVER from GENERATOR************"); |
temp_stim_packet.display(); |
byte_count = temp_stim_packet.byte_count; |
register_write = temp_stim_packet.intr_en; |
`vmm_callback(i2c_callback,send_pkt_to_monitor(temp_stim_packet)); // Sending packet to monitor |
|
// Reset test-case. Driver will driver high on pif.rst to Reset DUT |
// This will set reset_bit of reg_pkt and then invoke callback for scoreboad. |
if(temp_stim_packet.reset_check) // reset check |
begin |
repeat (10) |
begin |
@(posedge pif.clk) |
pif.rst = 1'b1; |
end |
@(posedge pif.clk) |
pif.rst = 1'b0; |
reg_pkt.reg_address = 8'h00; |
reg_pkt.data_byte = 8'h00; |
reg_pkt.wr_rd = 1'b1; |
reg_pkt.reset_bit = 1'b1; |
`vmm_callback(i2c_callback,write_reg(reg_pkt)); |
m_stim_req_chan.get(stim_packet); // get(remove) the packet from channel |
end // reset check |
|
// Register Test-case. If register_write is 1, it will write internal register, set fields of reg_pkt and invoke callback. |
// If register_write is 0, it will read value of internal register, set fields of reg_pkt and invoke callback for |
// comparision of register datas in Scoreboard. |
else if(temp_stim_packet.register_check) //Internal register read and write check |
begin |
if(register_write) // write |
begin |
write_inf(1,temp_stim_packet.register_addr,temp_stim_packet.register_data); |
reg_pkt.reg_address = temp_stim_packet.register_addr; |
reg_pkt.data_byte = temp_stim_packet.register_data; |
reg_pkt.wr_rd = 1'b1; |
reg_pkt.reset_bit = 1'b0; |
`vmm_callback(i2c_callback,write_reg(reg_pkt)); |
end |
else //read |
begin |
read_inf(1,temp_stim_packet.register_addr,reg_data_register); |
reg_pkt.reg_address = temp_stim_packet.register_addr; |
reg_pkt.data_byte = reg_data_register; |
reg_pkt.wr_rd = 1'b0; |
`vmm_callback(i2c_callback,read_reg(reg_pkt)); |
|
end |
m_stim_req_chan.get(stim_packet); // get (remove) packet from channel |
end //Internal register read and write check |
|
// Data Transfer test-case starts |
else //Data Transfer check |
begin |
m_stim_req_chan.get(stim_packet); // get (remove) packet from channel |
enable_core; |
set_prescale_register; |
set_timeout_reg; |
|
// DUT (W/B Driver) is in Master Mode. |
if(temp_stim_packet.master_slave) //Core in Master Mode |
begin |
// DUT (W/B Driver) in Master Mode and Transmitting data. |
if(temp_stim_packet.tr == 1) // Writing data packets to slave device |
begin |
|
// DUT (W/B Driver) in Master/Transmiter and in Interrupt mode. |
// Driver will configure DUT in given mode and then write data to Tx reg of DUT on each posedge of irq after slave acknowledgment. |
// After transmission of last byte it will configure DUT to generate Stop Signal |
if(temp_stim_packet.intr_en) // Interrupt Mode |
begin |
write_inf(1,8'h0E, {{temp_stim_packet.slave_address},{1'b0}}); // Slave Address + rd/wr bit |
reg_pkt.reg_address = 8'h0E; |
reg_pkt.data_byte = {{temp_stim_packet.slave_address},{1'b0}}; |
reg_pkt.wr_rd = 1'b1; |
reg_pkt.reset_bit = 1'b0; |
`vmm_callback(i2c_callback,write_reg(reg_pkt)); |
write_inf(1,8'h04, 8'h70); //Enable the core,set mode into interrupt and tx and generate Start |
reg_pkt.reg_address = 8'h04; |
reg_pkt.data_byte = 8'h70; |
reg_pkt.wr_rd = 1'b1; |
reg_pkt.reset_bit = 1'b0; |
`vmm_callback(i2c_callback,write_reg(reg_pkt)); |
while(byte_count != 0) |
begin |
@(posedge pif.irq) |
begin |
write_inf(1,8'h0E, temp_stim_packet.data_packet[byte_count-1]); |
reg_pkt.reg_address = 8'h0E; |
reg_pkt.data_byte = temp_stim_packet.data_packet[byte_count-1]; |
reg_pkt.wr_rd = 1'b1; |
reg_pkt.reset_bit = 1'b0; |
`vmm_callback(i2c_callback,write_reg(reg_pkt)); |
// vmm_callback |
sb_pkt.master_slave = 1'b1; |
sb_pkt.tx_rx = 1'b1; |
sb_pkt.slave_address = temp_stim_packet.slave_address; |
sb_pkt.data_byte = temp_stim_packet.data_packet[byte_count-1]; |
`vmm_callback(i2c_callback,pre_transaction(sb_pkt)); |
// vmm_callback |
write_inf(1,8'h04, 8'h73); |
reg_pkt.reg_address = 8'h04; |
reg_pkt.data_byte = 8'h73; |
reg_pkt.wr_rd = 1'b1; |
reg_pkt.reset_bit = 1'b0; |
`vmm_callback(i2c_callback,write_reg(reg_pkt)); |
end |
byte_count-- ; |
end |
read_inf(1,8'h08,status_reg); |
while (!status_reg[7] && !status_reg[0]) |
begin |
read_inf(1,8'h08,status_reg); |
end |
if(byte_count == 0 && status_reg[7]) |
write_inf(1,8'h04, 8'h01); // Generate Stop Command |
reg_pkt.reg_address = 8'h04; |
reg_pkt.data_byte = 8'h01; |
reg_pkt.wr_rd = 1'b1; |
reg_pkt.reset_bit = 1'b0; |
`vmm_callback(i2c_callback,write_reg(reg_pkt)); |
#1200; response_packet.tr = 1'b1; |
end // Interrupt Mode |
|
// DUT (W/B Driver) in Master/Transmiter and in Non-Interrupt mode. |
//Driver will configure DUT in given mode,then it will keep on checking status register and wait for bit 7 of Status Register (TIP) to be set, |
// After Slave Acknowledgment detection, it will write data to Transmit Register of DUT. |
// After transmission of last byte it will configure DUT to generate Stop Signal |
else // Non-Interrupt Mode |
begin |
write_inf(1,8'h0E, {{temp_stim_packet.slave_address},{1'b0}}); |
reg_pkt.reg_address = 8'h0E; |
reg_pkt.data_byte = {{temp_stim_packet.slave_address},{1'b0}}; |
reg_pkt.wr_rd = 1'b1; |
reg_pkt.reset_bit = 1'b0; |
`vmm_callback(i2c_callback,write_reg(reg_pkt)); |
write_inf(1,8'h04, 8'h30); //Enable the core,set mode into non-interrupt and tx and generate Start |
reg_pkt.reg_address = 8'h04; |
reg_pkt.data_byte = 8'h30; |
reg_pkt.wr_rd = 1'b1; |
reg_pkt.reset_bit = 1'b0; |
`vmm_callback(i2c_callback,write_reg(reg_pkt)); |
while(byte_count != 0) |
begin |
read_inf(1,8'h08,status_reg); |
while(!status_reg[7]) |
begin |
read_inf(1,8'h08,status_reg); |
end |
write_inf(1,8'h0E, temp_stim_packet.data_packet[byte_count-1]); |
reg_pkt.reg_address = 8'h0E; |
reg_pkt.data_byte = temp_stim_packet.data_packet[byte_count-1]; |
reg_pkt.wr_rd = 1'b1; |
reg_pkt.reset_bit = 1'b0; |
`vmm_callback(i2c_callback,write_reg(reg_pkt)); |
read_inf(1,8'h08,status_reg); |
while (!status_reg[7] && !status_reg[0]) |
begin |
read_inf(1,8'h08,status_reg); |
end |
// vmm_callback |
sb_pkt.master_slave = 1'b1; |
sb_pkt.tx_rx = 1'b1; |
sb_pkt.slave_address = temp_stim_packet.slave_address; |
sb_pkt.data_byte = temp_stim_packet.data_packet[byte_count-1]; |
`vmm_callback(i2c_callback,pre_transaction(sb_pkt)); |
// vmm_callback |
write_inf(1,8'h04, 8'h31); |
reg_pkt.reg_address = 8'h04; |
reg_pkt.data_byte = 8'h31; |
reg_pkt.wr_rd = 1'b1; |
reg_pkt.reset_bit = 1'b0; |
`vmm_callback(i2c_callback,write_reg(reg_pkt)); |
byte_count-- ; |
read_inf(1,8'h08,status_reg); |
while (!status_reg[7] && !status_reg[0]) |
begin |
read_inf(1,8'h08,status_reg); |
end |
if(byte_count == 0 && status_reg[7]) |
write_inf(1,8'h04, 8'h01); // Generate Stop Signal |
reg_pkt.reg_address = 8'h04; |
reg_pkt.data_byte = 8'h01; |
reg_pkt.wr_rd = 1'b1; |
reg_pkt.reset_bit = 1'b0; |
`vmm_callback(i2c_callback,write_reg(reg_pkt)); |
end |
#1200; response_packet.tr = 1'b1; |
end // Non-Interrupt Mode |
end |
|
// DUT (W/B Driver) in Master/Receiver and in Interrupt mode. |
// Driver will configure DUT in given mode and then After Slave Acknowledgment detection, it will read data from Receive Register on |
// on every posedge of irq. After Reception of last byte it will configure DUT to generate Stop Signal |
else // Reading Data Packets from Slave Address |
begin |
if(stim_packet.intr_en) // Interrupt Mode |
begin |
write_inf(1,8'h0E, {{temp_stim_packet.slave_address},{1'b1}}); |
reg_pkt.reg_address = 8'h0E; |
reg_pkt.data_byte = {{temp_stim_packet.slave_address},{1'b1}}; |
reg_pkt.wr_rd = 1'b1; |
reg_pkt.reset_bit = 1'b0; |
`vmm_callback(i2c_callback,write_reg(reg_pkt)); |
write_inf(1,8'h04, 8'h63); //Enable the core,set mode into interrupt and tx and generate Start |
reg_pkt.reg_address = 8'h04; |
reg_pkt.data_byte = 8'h63; |
reg_pkt.wr_rd = 1'b1; |
reg_pkt.reset_bit = 1'b0; |
`vmm_callback(i2c_callback,write_reg(reg_pkt)); |
@(posedge pif.irq) |
while(byte_count != 0) |
begin |
write_inf(1,8'h04, 8'h63); |
reg_pkt.reg_address = 8'h04; |
reg_pkt.data_byte = 8'h63; |
reg_pkt.wr_rd = 1'b1; |
reg_pkt.reset_bit = 1'b0; |
`vmm_callback(i2c_callback,write_reg(reg_pkt)); |
@(posedge pif.irq) |
begin |
read_inf(1,8'h00,status_reg); |
// $display("In Driver - Received Data in interrupt mode is %b",status_reg); |
// vmm_callback |
sb_pkt.master_slave = 1'b1; |
sb_pkt.tx_rx = 1'b1; |
sb_pkt.slave_address = temp_stim_packet.slave_address; |
sb_pkt.data_byte = status_reg; |
`vmm_callback(i2c_callback,post_transaction(sb_pkt)); |
// vmm_callback |
end |
byte_count--; |
end |
read_inf(1,8'h08,status_reg); |
while (!status_reg[7]) |
read_inf(1,8'h08,status_reg); |
if(byte_count == 0) |
write_inf(1,8'h04, 8'h43); //Generate Stop Signal |
reg_pkt.reg_address = 8'h04; |
reg_pkt.data_byte = 8'h43; |
reg_pkt.wr_rd = 1'b1; |
reg_pkt.reset_bit = 1'b0; |
`vmm_callback(i2c_callback,write_reg(reg_pkt)); |
#1200; response_packet.tr = 1'b1; |
end |
|
// DUT (W/B Driver) in Master/Receiver and in Non-Interrupt mode. |
// Driver will configure DUT in given mode,then it will keep on checking status register and wait for bit 7 of Status Register (TIP) to be set, |
// After Slave Acknowledgment detection, it will read data from Receive Register everytime TIP bit is set. |
// After Reception of last byte it will configure DUT to generate Stop Signal |
else // non-interrupt mode |
begin |
write_inf(1,8'h0E, {{temp_stim_packet.slave_address},{1'b1}}); |
reg_pkt.reg_address = 8'h0E; |
reg_pkt.data_byte = {{temp_stim_packet.slave_address},{1'b1}}; |
reg_pkt.wr_rd = 1'b1; |
reg_pkt.reset_bit = 1'b0; |
`vmm_callback(i2c_callback,write_reg(reg_pkt)); |
write_inf(1,8'h04, 8'h20); //Enable the core,set mode into interrupt and tx and generate Start |
reg_pkt.reg_address = 8'h04; |
reg_pkt.data_byte = 8'h20; |
reg_pkt.wr_rd = 1'b1; |
reg_pkt.reset_bit = 1'b0; |
`vmm_callback(i2c_callback,write_reg(reg_pkt)); |
read_inf(1,8'h08,status_reg); |
while(!status_reg[7]) |
read_inf(1,8'h08,status_reg); |
|
while(byte_count != 0) |
begin |
write_inf(1,8'h04, 8'h21); |
reg_pkt.reg_address = 8'h04; |
reg_pkt.data_byte = 8'h21; |
reg_pkt.wr_rd = 1'b1; |
reg_pkt.reset_bit = 1'b0; |
`vmm_callback(i2c_callback,write_reg(reg_pkt)); |
read_inf(1,8'h08,status_reg); |
while(!status_reg[7]) |
read_inf(1,8'h08,status_reg); |
read_inf(1,8'h08,status_reg); |
while (!status_reg[7] && !status_reg[0]) |
begin |
read_inf(1,8'h08,status_reg); |
end |
read_inf(1,8'h00,status_reg); |
// $display("In Driver - Received Data in non-interrupt mode is %b",status_reg); |
// vmm_callback |
sb_pkt.master_slave = 1'b1; |
sb_pkt.tx_rx = 1'b1; |
sb_pkt.slave_address = temp_stim_packet.slave_address; |
sb_pkt.data_byte = status_reg; |
`vmm_callback(i2c_callback,post_transaction(sb_pkt)); |
// vmm_callback |
byte_count--; |
read_inf(1,8'h08,status_reg); |
while (!status_reg[7]) |
read_inf(1,8'h08,status_reg); |
if(byte_count == 0 && status_reg[7] ) |
write_inf(1,8'h04, 8'h01); // Generate Stop signal |
reg_pkt.reg_address = 8'h04; |
reg_pkt.data_byte = 8'h01; |
reg_pkt.wr_rd = 1'b1; |
reg_pkt.reset_bit = 1'b0; |
`vmm_callback(i2c_callback,write_reg(reg_pkt)); |
end |
#1200; response_packet.tr = 1'b1; |
end |
end |
|
end |
|
// DUT (W/B Driver) in Slave mode. |
else // core in slave mode |
begin |
// DUT (W/B Driver) in Slave Mode and Transmitting data. |
if(temp_stim_packet.tr == 1) // Core in Slave mode: Receiving |
begin |
|
// DUT (W/B Driver) in Slave/Receiver and in Interrupt mode. |
// Driver will configure DUT in given mode, on posedge on irq it will again configure core to receive data and |
// then it will read data from Receive Register on every posedge of irq. |
if (temp_stim_packet.intr_en) // Interrupt Mode |
begin |
write_inf(1,8'h0C, {{temp_stim_packet.slave_address},{1'b1}}); // Slave Address + 1'b1 bit |
reg_pkt.reg_address = 8'h0C; |
reg_pkt.data_byte = {{temp_stim_packet.slave_address},{1'b1}}; |
reg_pkt.wr_rd = 1'b1; |
reg_pkt.reset_bit = 1'b0; |
`vmm_callback(i2c_callback,write_reg(reg_pkt)); |
write_inf(1,8'h04, 8'h40); //Enable the core,keep it in slave mode |
reg_pkt.reg_address = 8'h04; |
reg_pkt.data_byte = 8'h40; |
reg_pkt.wr_rd = 1'b1; |
reg_pkt.reset_bit = 1'b0; |
`vmm_callback(i2c_callback,write_reg(reg_pkt)); |
@(posedge pif.irq) |
while(byte_count != 0) |
begin |
write_inf(1,8'h04, 8'h43); |
reg_pkt.reg_address = 8'h04; |
reg_pkt.data_byte = 8'h43; |
reg_pkt.wr_rd = 1'b1; |
reg_pkt.reset_bit = 1'b0; |
`vmm_callback(i2c_callback,write_reg(reg_pkt)); |
@(posedge pif.irq) |
begin |
read_inf(1,8'h00,status_reg); |
// $display("In Driver - When core is in slave mode: Received Data in interrupt mode is %b",status_reg); |
// vmm_callback |
sb_pkt.master_slave = 1'b0; |
sb_pkt.tx_rx = 1'b1; |
sb_pkt.slave_address = temp_stim_packet.slave_address; |
sb_pkt.data_byte = status_reg; |
`vmm_callback(i2c_callback,post_transaction(sb_pkt)); |
// vmm_callback |
end |
byte_count--; |
end |
end |
|
// DUT (W/B Driver) in Slave/Receiver and in Non-Interrupt mode. |
// Driver will configure DUT in given mode, it will keep on waiting for tip bit (bit 7) of Status Register to be set. |
// After first occurance of tip to be set it will again configure DUT core to receive data and then it will read data |
// from Receive Register every time tip bit of Status Register is set. |
else // Non-interrupt mode |
begin |
write_inf(1,8'h0C, {{temp_stim_packet.slave_address},{1'b1}}); // Slave Address + 1'b1 bit |
reg_pkt.reg_address = 8'h0C; |
reg_pkt.data_byte = {{temp_stim_packet.slave_address},{1'b1}}; |
reg_pkt.wr_rd = 1'b1; |
reg_pkt.reset_bit = 1'b0; |
`vmm_callback(i2c_callback,write_reg(reg_pkt)); |
write_inf(1,8'h04, 8'h00); //Enable the core,keep it in slave mode , non-interrupt mode |
reg_pkt.reg_address = 8'h04; |
reg_pkt.data_byte = 8'h00; |
reg_pkt.wr_rd = 1'b1; |
reg_pkt.reset_bit = 1'b0; |
`vmm_callback(i2c_callback,write_reg(reg_pkt)); |
read_inf(1,8'h08,status_reg); |
while(!status_reg[7]) |
read_inf(1,8'h08,status_reg); |
while(byte_count != 0) |
begin |
write_inf(1,8'h04, 8'h01); |
reg_pkt.reg_address = 8'h04; |
reg_pkt.data_byte = 8'h01; |
reg_pkt.wr_rd = 1'b1; |
reg_pkt.reset_bit = 1'b0; |
`vmm_callback(i2c_callback,write_reg(reg_pkt)); |
read_inf(1,8'h08,status_reg); |
while(!status_reg[7]) |
read_inf(1,8'h08,status_reg); |
read_inf(1,8'h08,status_reg); |
while (!status_reg[7] && !status_reg[0]) |
begin |
read_inf(1,8'h08,status_reg); |
end |
read_inf(1,8'h00,status_reg); |
// $display("In Driver - When core is in slave mode: Received Data in non-interrupt mode is %b",status_reg); |
// vmm_callback |
sb_pkt.master_slave = 1'b0; |
sb_pkt.tx_rx = 1'b1; |
sb_pkt.slave_address = temp_stim_packet.slave_address; |
sb_pkt.data_byte = status_reg; |
`vmm_callback(i2c_callback,post_transaction(sb_pkt)); |
// vmm_callback |
byte_count--; |
read_inf(1,8'h08,status_reg); |
while (!status_reg[7]) |
read_inf(1,8'h08,status_reg); |
if(byte_count == 0 && status_reg[7] ) |
write_inf(1,8'h04, 8'h01); |
reg_pkt.reg_address = 8'h04; |
reg_pkt.data_byte = 8'h01; |
reg_pkt.wr_rd = 1'b1; |
reg_pkt.reset_bit = 1'b0; |
`vmm_callback(i2c_callback,write_reg(reg_pkt)); |
end |
end |
end |
|
// DUT (W/B Driver) in Slave/Transmiter Mode. |
else // Core in Slave Mode: Transmitting |
begin |
|
// DUT (W/B Driver) in Slave/Transmiter and in Interrupt mode. |
// Driver will configure DUT in given mode and then it will write data to Transmit Register of DUT on every posedge of irq. |
if (temp_stim_packet.intr_en) // Interrupt Mode |
begin |
write_inf(1,8'h0C, {{temp_stim_packet.slave_address},{1'b1}}); // Slave Address + 1'b1 bit |
reg_pkt.reg_address = 8'h0C; |
reg_pkt.data_byte = {{temp_stim_packet.slave_address},{1'b1}}; |
reg_pkt.wr_rd = 1'b1; |
reg_pkt.reset_bit = 1'b0; |
`vmm_callback(i2c_callback,write_reg(reg_pkt)); |
write_inf(1,8'h04, 8'h40); //Enable the core,keep it in slave mode , non-interrupt mode |
reg_pkt.reg_address = 8'h04; |
reg_pkt.data_byte = 8'h40; |
reg_pkt.wr_rd = 1'b1; |
reg_pkt.reset_bit = 1'b0; |
`vmm_callback(i2c_callback,write_reg(reg_pkt)); |
while(byte_count != 0) |
begin |
@(posedge pif.irq) |
begin |
write_inf(1,8'h0E, temp_stim_packet.data_packet[byte_count-1]); |
reg_pkt.reg_address = 8'h0E; |
reg_pkt.data_byte = temp_stim_packet.data_packet[byte_count-1]; |
reg_pkt.wr_rd = 1'b1; |
reg_pkt.reset_bit = 1'b0; |
`vmm_callback(i2c_callback,write_reg(reg_pkt)); |
write_inf(1,8'h04, 8'h43); |
reg_pkt.reg_address = 8'h04; |
reg_pkt.data_byte = 8'h43; |
reg_pkt.wr_rd = 1'b1; |
reg_pkt.reset_bit = 1'b0; |
`vmm_callback(i2c_callback,write_reg(reg_pkt)); |
// vmm_callback |
sb_pkt.master_slave = 1'b0; |
sb_pkt.tx_rx = 1'b0; |
sb_pkt.slave_address = temp_stim_packet.slave_address; |
sb_pkt.data_byte = temp_stim_packet.data_packet[byte_count-1]; |
`vmm_callback(i2c_callback,pre_transaction(sb_pkt)); |
// vmm_callback |
end |
byte_count-- ; |
end |
read_inf(1,8'h08,status_reg); |
while (!status_reg[7]) |
read_inf(1,8'h08,status_reg); |
if(byte_count == 0 && status_reg[7] ) |
begin |
write_inf(1,8'h0E, 8'hFF); |
reg_pkt.reg_address = 8'h0E; |
reg_pkt.data_byte = 8'hFF; |
reg_pkt.wr_rd = 1'b1; |
reg_pkt.reset_bit = 1'b0; |
`vmm_callback(i2c_callback,write_reg(reg_pkt)); |
end |
end |
|
// DUT (W/B Driver) in Slave/Transmiter and in Non-Interrupt mode. |
// Driver will configure DUT in given mode it will keep on waiting for tip bit (bit 7) of Status Register to be set |
// and then it will write data to transmit register of DUT. |
else // Non-Interrupt Mode |
begin |
write_inf(1,8'h0C, {{temp_stim_packet.slave_address},{1'b1}}); // Slave Address + 1'b1 bit |
reg_pkt.reg_address = 8'h0C; |
reg_pkt.data_byte = {{temp_stim_packet.slave_address},{1'b1}}; |
reg_pkt.wr_rd = 1'b1; |
reg_pkt.reset_bit = 1'b0; |
`vmm_callback(i2c_callback,write_reg(reg_pkt)); |
write_inf(1,8'h04, 8'h00); //Enable the core,keep it in slave mode , non-interrupt mode |
reg_pkt.reg_address = 8'h04; |
reg_pkt.data_byte = 8'h00; |
reg_pkt.wr_rd = 1'b1; |
reg_pkt.reset_bit = 1'b0; |
`vmm_callback(i2c_callback,write_reg(reg_pkt)); |
|
while(byte_count != 0) |
begin |
read_inf(1,8'h08,status_reg); |
while(!status_reg[7]) |
begin |
read_inf(1,8'h08,status_reg); |
end |
write_inf(1,8'h0E, temp_stim_packet.data_packet[byte_count-1]); |
reg_pkt.reg_address = 8'h0E; |
reg_pkt.data_byte = temp_stim_packet.data_packet[byte_count-1]; |
reg_pkt.wr_rd = 1'b1; |
reg_pkt.reset_bit = 1'b0; |
`vmm_callback(i2c_callback,write_reg(reg_pkt)); |
write_inf(1,8'h04, 8'h01); |
reg_pkt.reg_address = 8'h04; |
reg_pkt.data_byte = 8'h01; |
reg_pkt.wr_rd = 1'b1; |
reg_pkt.reset_bit = 1'b0; |
`vmm_callback(i2c_callback,write_reg(reg_pkt)); |
// vmm_callback |
sb_pkt.master_slave = 1'b0; |
sb_pkt.tx_rx = 1'b0; |
sb_pkt.slave_address = temp_stim_packet.slave_address; |
sb_pkt.data_byte = temp_stim_packet.data_packet[byte_count-1]; |
`vmm_callback(i2c_callback,pre_transaction(sb_pkt)); |
// vmm_callback |
read_inf(1,8'h08,status_reg); |
while (!status_reg[7] && !status_reg[0]) |
begin |
read_inf(1,8'h08,status_reg); |
end |
//write_inf(1,8'h04, 8'h01); |
byte_count-- ; |
end |
read_inf(1,8'h08,status_reg); |
while (!status_reg[7] && !status_reg[0]) |
begin |
read_inf(1,8'h08,status_reg); |
end |
if(byte_count == 0 && status_reg[7]) |
write_inf(1,8'h0E, 8'hFF); |
reg_pkt.reg_address = 8'h0E; |
reg_pkt.data_byte = 8'hFF; |
reg_pkt.wr_rd = 1'b1; |
reg_pkt.reset_bit = 1'b0; |
`vmm_callback(i2c_callback,write_reg(reg_pkt)); |
#1200; response_packet.tr = 1'b1; |
end |
end |
end |
end |
end |
|
end |
endtask |
|
|
endclass : i2c_master_driver |
|
|
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_reg_pkt.sv
New file
0,0 → 1,44
////////////////////////////////////////////////////////////////////////////////////////// |
// // |
// Verification Engineer: Atish Jaiswal // |
// Company Name : TooMuch Semiconductor Solutions Pvt Ltd. // |
// // |
// Description of the Source File: // |
// This source code defines Register Packet. This packet will be used while running // |
// Register Read-Write Testcases and this packet will be sent to Scoreboard from W/B // |
// Master Driver to Scoreboard and Coverage Module. // |
// // |
// // |
////////////////////////////////////////////////////////////////////////////////////////// |
|
`include "vmm.sv" |
|
class register_pkt extends vmm_data; |
|
vmm_log log; |
bit [7:0] reg_address; |
bit [7:0] data_byte; |
bit wr_rd; |
bit reset_bit; |
|
function new(); |
super.new(this.log); |
this.log = new("Reg Data", "class"); |
endfunction |
|
function vmm_data copy(vmm_data to = null); |
copy = new this; |
endfunction |
|
|
function void display(); |
this.log.start_msg(vmm_log::NOTE_TYP); |
void'(this.log.text($psprintf("slave_address is %b", this.reg_address))); |
void'(this.log.text($psprintf("data_byte is %b", this.data_byte))); |
void'(this.log.text($psprintf("write_read is %b", this.wr_rd))); |
void'(this.log.text($psprintf("reset_bit is %b", this.reset_bit))); |
this.log.end_msg(); |
endfunction |
|
endclass |
|
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_callback.sv
New file
0,0 → 1,24
`include "vmm.sv" |
|
class i2c_callback extends vmm_xactor_callbacks; |
|
virtual task pre_transaction(scoreboard_pkt sb_pkt); |
endtask |
|
virtual task post_transaction(scoreboard_pkt sb_pkt); |
endtask |
|
virtual task write_reg(register_pkt reg_pkt); |
endtask |
|
virtual task read_reg(register_pkt reg_pkt); |
endtask |
|
virtual task send_pkt_to_monitor(stimulus_packet mon_stim_pkt); |
endtask |
|
virtual task protocol_checks_coverage(monitor_pkt mon_pkt); |
endtask |
|
|
endclass |
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_data_packet.sv
New file
0,0 → 1,41
////////////////////////////////////////////////////////////////////////////////////////// |
// // |
// Verification Engineer: Atish Jaiswal // |
// Company Name : TooMuch Semiconductor Solutions Pvt Ltd. // |
// // |
// Description of the Source File: // |
// This file is the data packet class for Scenario Generator. // |
// The Packet Randomizes data_pkt whose size will be assigned in Scenario Generator. // |
// // |
// // |
////////////////////////////////////////////////////////////////////////////////////////// |
|
`include "vmm.sv" |
|
class i2c_data_packet extends vmm_data; |
vmm_log log; |
rand bit [7:0] data_pkt[]; // data packets to be transfered |
|
function new(); |
super.new(this.log); |
this.log = new("Data_packet", "class"); |
endfunction |
|
function void display(); |
int i; |
this.log.start_msg(vmm_log::NOTE_TYP); |
while( i < data_pkt.size) |
begin |
void'(this.log.text($psprintf("Data_Byte[%0d] is %b", i, this.data_pkt[i]))); |
i++; |
end |
this.log.end_msg(); |
endfunction |
|
|
function vmm_data copy(vmm_data to = null); |
copy = new this; |
endfunction |
|
endclass : i2c_data_packet |
|
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_interface.sv
New file
0,0 → 1,107
////////////////////////////////////////////////////////////////////////////////////////// |
// // |
// Verification Engineer: Atish Jaiswal // |
// Company Name : TooMuch Semiconductor Solutions Pvt Ltd. // |
// // |
// Description of the Source File: // |
// This source code is used to declare interface. // |
// // |
// // |
////////////////////////////////////////////////////////////////////////////////////////// |
|
|
interface i2c_pin_if(); |
|
reg clk; // System_clk |
logic rst; // Reset |
logic [7:0] addr_in; // W/B Address Input lines |
logic [7:0] data_in; // W/B Data Input lines |
wire [7:0] data_out; // W/B Data Output lines |
logic wb_stb_i; // W/B Strobe |
logic wb_cyc_i; // W/B Cycle valid |
logic we; // W/B Write Enable |
wire trans_comp; // Transacation Complete |
logic ack_o; // W/B Acknowledgment |
wire irq; // Interrupt from DUT |
logic scl_o; // SCL O/P |
reg scl_oe; // SCL O/P Enable |
wire scl; // SCL I/P |
logic sda_o; // SDL O/P |
logic sda_oe; // SDA O/P Enable |
wire sda; // SDA I/P |
|
|
modport dut_mp ( |
input clk, |
input rst, |
input addr_in, |
input data_in, |
output data_out, |
input wb_stb_i, |
input wb_cyc_i, |
input we, |
output ack_o, |
output trans_comp, |
output irq, |
output scl , |
output scl_o, |
output scl_oe, |
output sda_o, |
output sda_oe, |
output sda |
); |
|
|
modport driver_mp ( |
input clk, |
input rst, |
input addr_in, |
input data_in, |
output data_out, |
input wb_stb_i, |
input wb_cyc_i, |
input we, |
output trans_comp, |
output ack_o, |
output irq, |
output scl , |
output scl_o, |
output scl_oe, |
output sda_o, |
output sda_oe, |
output sda |
); |
|
|
modport monitor_mp ( |
input clk, |
input rst, |
input addr_in, |
input data_in, |
input data_out, |
input wb_stb_i, |
input wb_cyc_i, |
input we, |
input ack_o, |
input trans_comp, |
input irq, |
input scl , |
input sda , |
input scl_o, |
input scl_oe, |
input sda_o, |
input sda_oe |
); |
|
|
modport slave_mp ( |
output scl , |
output sda , |
output scl_o , |
output scl_oe, |
output sda_o , |
output sda_oe |
); |
|
endinterface : i2c_pin_if |
|
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_top.sv
New file
0,0 → 1,61
////////////////////////////////////////////////////////////////////////////////////////// |
// // |
// Verification Engineer: Atish Jaiswal // |
// Company Name : TooMuch Semiconductor Solutions Pvt Ltd. // |
// // |
// Description of the Source File: // |
// This source code implements I2C M/S Core's Top Module. // |
// Top Module instantiates program block and DUT and connects them with each other. // |
// sda and scl lines are anded with scl and sda lines from both sides (DUT as well as // |
// Environment). Both sda and scl lines are pulled up by verilog pullup construct. // |
// // |
////////////////////////////////////////////////////////////////////////////////////////// |
|
`include "vmm_clkgen.sv" |
`include "vmm_program_test.sv" |
|
|
module top; |
|
i2c_pin_if pif(); // Interface |
clkgen c_gen(pif); // Clock Generator |
program_test p_test(pif); // Program Block |
|
wire dut_sda_o; |
wire dut_sda_oe; |
wire dut_sda_in; |
wire dut_scl_o; |
wire dut_scl_oe; |
wire dut_scl_in; |
wire temp_sda; |
wire temp_scl; |
|
assign dut_sda_o = 1'b0; |
assign temp_sda = pif.sda_oe & dut_sda_oe; |
assign temp_scl = pif.scl_oe & dut_scl_oe; |
assign pif.sda = temp_sda ? 1'bz : 1'b0; |
assign pif.scl = temp_scl ? 1'bz : 1'b0; |
pullup p1_if(pif.sda); // Pull up sda line |
pullup p2_if(pif.scl); // Pull up scl line |
|
// I2C Core (DUT) |
block i2c_core( .scl_in(pif.scl), |
.scl_o(dut_scl_o), |
.scl_oe(dut_scl_oe), |
.sda_in(pif.sda), |
.sda_o(dut_sda_o), |
.sda_oe(dut_sda_oe), |
.wb_add_i(pif.addr_in), |
.wb_data_i(pif.data_in), |
.wb_data_o(pif.data_out), |
.wb_stb_i(pif.wb_stb_i), |
.wb_cyc_i(pif.wb_cyc_i), |
.wb_we_i(pif.we), |
.wb_ack_o(pif.ack_o), |
.irq(pif.irq), |
.trans_comp(pif.trans_comp), |
.wb_clk_i(pif.clk), |
.wb_rst_i(pif.rst) |
); |
|
endmodule |
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/sb_callback.sv
New file
0,0 → 1,72
////////////////////////////////////////////////////////////////////////////////////////// |
// // |
// Verification Engineer: Atish Jaiswal // |
// Company Name : TooMuch Semiconductor Solutions Pvt Ltd. // |
// // |
// Description of the Source File: // |
// This source code implements all callback function defined in faced class named // |
// vmm_i2c_callback. All callback functions invoke another function/task in Scoreboard // |
// and Coverage Collector Module. // |
// // |
////////////////////////////////////////////////////////////////////////////////////////// |
|
|
`include "vmm.sv" |
`include "vmm_i2c_scoreboard.sv" |
`include "vmm_i2c_coverage.sv" |
`include "vmm_i2c_callback.sv" |
`include "vmm_i2c_monitor.sv" |
|
class sb_callback extends i2c_callback; |
|
vmm_log log = new("scorebd_cb","CALLBACK"); |
scoreboard_pkt sb_pkt; // Scoreboard Packet |
register_pkt reg_pkt; // Register Packet |
stimulus_packet mon_stim_pkt; // Stimulus Packet |
monitor_pkt mon_pkt; // Monitor Packet |
i2c_scoreboard i2c_sb; // Scoreboard's Instance |
i2c_coverage i2c_cov; // Coverage Instance |
i2c_monitor i2c_mon; // Monitor's Instance |
|
function new(i2c_scoreboard i2c_sb, i2c_coverage i2c_cov, i2c_monitor i2c_mon); |
this.i2c_sb = i2c_sb; |
this.i2c_cov = i2c_cov; |
this.i2c_mon = i2c_mon; |
endfunction |
|
|
// This task invoke pre_txn_push task in Scoreboard and pre_txn_start_cov task in Coverage module and send sb_pkt as a formal argument. |
virtual task pre_transaction(scoreboard_pkt sb_pkt); |
this.i2c_sb.pre_txn_push(sb_pkt); |
this.i2c_cov.pre_txn_start_cov(sb_pkt); |
endtask |
|
// This task invoke post_txn_push task in Scoreboard and send sb_pkt as a formal argument. |
virtual task post_transaction(scoreboard_pkt sb_pkt); |
this.i2c_sb.post_txn_push(sb_pkt); |
endtask |
|
// This task invoke write_reg task in Scoreboard and write_reg_cov task in Coverage module and send reg_pkt as a formal argument. |
virtual task write_reg(register_pkt reg_pkt); |
this.i2c_sb.write_reg(reg_pkt); |
this.i2c_cov.write_reg_cov(reg_pkt); |
endtask |
|
// This task invoke read_reg task in Scoreboard and read_reg_cov task in Coverage module and send reg_pkt as a formal argument. |
virtual task read_reg(register_pkt reg_pkt); |
this.i2c_sb.read_reg(reg_pkt); |
this.i2c_cov.read_reg_cov(reg_pkt); |
endtask |
|
// This task invoke get_packet_from_driver task in Monitor and send mon_stim_pkt as a formal argument. |
virtual task send_pkt_to_monitor(stimulus_packet mon_stim_pkt); |
this.i2c_mon.get_packet_from_driver(mon_stim_pkt); |
endtask |
|
// This task invoke protocol_checks_cov task in Coverage Module and send mon_pkt as a formal argument. |
virtual task protocol_checks_coverage(monitor_pkt mon_pkt); |
this.i2c_cov.protocol_checks_cov(mon_pkt); |
endtask |
|
endclass |
|
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_clkgen.sv
New file
0,0 → 1,21
////////////////////////////////////////////////////////////////////////////////////////// |
// // |
// Verification Engineer: Atish Jaiswal // |
// Company Name : TooMuch Semiconductor Solutions Pvt Ltd. // |
// // |
// Description of the Source File: // |
// This source code generates clock for the interface. // |
// // |
////////////////////////////////////////////////////////////////////////////////////////// |
|
module clkgen(i2c_pin_if i); |
|
initial begin |
forever begin |
#5 i.clk = 1; |
#5 i.clk = 0; |
end |
end |
|
endmodule |
|
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_mon_pkt.sv
New file
0,0 → 1,46
////////////////////////////////////////////////////////////////////////////////////////// |
// // |
// Verification Engineer: Atish Jaiswal // |
// Company Name : TooMuch Semiconductor Solutions Pvt Ltd. // |
// // |
// Description of the Source File: // |
// This source code defines Monitor Packet. This packet will be sent to Scoreboard and // |
// Coverage Module from Monitor Transactor. // |
// // |
// // |
////////////////////////////////////////////////////////////////////////////////////////// |
|
`include "vmm.sv" |
|
class monitor_pkt extends vmm_data; |
|
vmm_log log; |
bit start_bit; // Start bit |
bit stop_bit; // Stop bit |
bit slave_ack; // Slave Acknowledgment |
bit data_ack; // Data Acknowledgment |
bit intr_ack; // Interrupt Generation Acknowledgment |
|
// Class Constructor |
function new(); |
super.new(this.log); |
this.log = new("Monitor Data", "class"); |
endfunction |
|
function vmm_data copy(vmm_data to = null); |
copy = new this; |
endfunction |
|
// Display Function |
function void display(); |
this.log.start_msg(vmm_log::NOTE_TYP); |
void'(this.log.text($psprintf("start_bit is %0b", this.start_bit))); |
void'(this.log.text($psprintf("stop_bit is %0b", this.stop_bit))); |
void'(this.log.text($psprintf("slave_ack is %b", this.slave_ack))); |
void'(this.log.text($psprintf("data_ack is %b", this.data_ack))); |
void'(this.log.text($psprintf("intr_ack is %b", this.intr_ack))); |
this.log.end_msg(); |
endfunction |
|
endclass |
|
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_scenario_generator.sv
New file
0,0 → 1,132
////////////////////////////////////////////////////////////////////////////////////////// |
// // |
// Verification Engineer: Atish Jaiswal // |
// Company Name : TooMuch Semiconductor Solutions Pvt Ltd. // |
// // |
// Description of the Source File: // |
// This source code implements Scenario Generator. Please note that this Scenario // |
// Generator is coded and its different than the one getting created by using macro // |
// `vmm_scenario_gen(defined in VMM). // |
// // |
// If type of test-case to be run is given in command line(rand_gen=0) and other // |
// variable are assgined then it will use those values and then randomize only stimlus // |
// packet and data packet and then stimulus packet will be sent to both drivers. // |
// // |
// When type of test-case to be run is not given in command line (rand_gen=1) then it // |
// will randomize Scenario Packet first to find out what kind of test-case it to be run// |
// Accordingly it will randomized stimulus and data_pkt and then Stimulus packet will // |
// be sent to both drivers. // |
// // |
////////////////////////////////////////////////////////////////////////////////////////// |
|
`include "vmm.sv" |
class i2c_scenario_generator extends vmm_xactor; |
|
vmm_log log = new("lOG", "GENERATOR"); |
|
scenario_packet sc_packet; // Scenario Packet |
stimulus_packet stim_packet; // Stimulus Packet |
i2c_data_packet d_pkt; // Data Packet |
stimulus_packet_channel m_req_chan; // Scenario_Gen to W/B Driver |
stimulus_packet_channel s_req_chan; // Scenario_Gen to I2C Master/Slave Driver |
int stop_after_n_inst; |
static int DONE; // Done to check whether all scenarios have been sent |
|
bit rand_gen = 1'b0; |
integer transaction_count; |
bit master_slave; |
bit register_check; |
bit reset_check; |
bit tx_rx; |
|
function new( string name, string instance_name, stimulus_packet_channel m_req_chan = null, stimulus_packet_channel s_req_chan = null); |
super.new("scenario_generator ", "scenario_generator"); |
if(m_req_chan == null) m_req_chan = new("master_stimulus_packet_channel", "m_req_chan"); |
this.m_req_chan = m_req_chan; |
if(s_req_chan == null) s_req_chan = new("slave_stimulus_packet_channel", "s_req_chan"); |
this.s_req_chan = s_req_chan; |
this.DONE = this.notify.configure(1,vmm_notify::ON_OFF); |
sc_packet = new; |
stim_packet = new; |
d_pkt = new; |
$value$plusargs("rand_gen=%b",rand_gen); // Gets value of read_gen from Command line |
$value$plusargs("master_slave=%b",master_slave); // Gets value of master_slave from Command line |
$value$plusargs("register_check=%b",register_check); // Gets value of register_check bit from Command line |
$value$plusargs("reset_check=%b",reset_check); // Gets vlaue of reset_check bit from Command line |
$value$plusargs("tx_rx=%b",tx_rx); // Gets value of tx_rx from Command line |
endfunction |
|
|
|
virtual protected task main(); |
super.main(); |
begin |
string str; |
stimulus_packet m_response; |
stimulus_packet s_response; |
`vmm_note(log,"I2C Scenario from Scenario generator"); |
|
while (transaction_count != 0) |
begin |
if(!rand_gen) // If type of test-cases to run is assigned in command line |
begin |
sc_packet.master_slave = master_slave; |
sc_packet.transaction_count = transaction_count; |
sc_packet.register_check = register_check; |
sc_packet.tx_rx = tx_rx; |
end |
else // If type of test-cases to run is to be randomized. |
begin |
if(sc_packet.randomize()); else `vmm_error(log, "I2C Scenario Generator : Randomization of I2C Scenario Packet Packet Failed"); |
master_slave = sc_packet.master_slave; |
sc_packet.transaction_count = transaction_count; |
register_check = sc_packet.register_check; |
reset_check = sc_packet.reset_check; |
tx_rx = sc_packet.tx_rx; |
end |
sc_packet.display(); |
`vmm_note(log, $psprintf("Scenario Generator: packet to Driver @ %t", $time)); |
|
// If register read_write testcase are to be run, it will randomize stimulus packet for register data and addres and read/write operation. |
// Other fields of stimulus packet will be assigned here only. |
if(register_check) // Register test-case to be run |
begin |
stim_packet.master_slave = master_slave; |
stim_packet.tr = tx_rx; |
stim_packet.register_check = register_check; |
stim_packet.reset_check = reset_check; |
if(stim_packet.randomize()); else `vmm_error(log, "I2C Master Stimulus: Randomization of I2C Stimulus Packet Failed"); |
stim_packet.display(); |
this.m_req_chan.put(stim_packet); // sending packet to master driver |
this.s_req_chan.put(stim_packet); // sending packet to slave driver |
end |
|
// If data transacation test-caser are to be run, it will stimulus packet, get the size of data_bytes(no of bytes) and again randomized |
// data_pkt class for data_bytes. All fields of stimulus packet wil be assigned here and then sent to both dirvers. |
|
else // Data Transacation test-case to be run |
begin |
stim_packet.master_slave = master_slave; |
stim_packet.tr = tx_rx; |
stim_packet.register_check = register_check; |
stim_packet.reset_check = reset_check; |
if(stim_packet.randomize()); else `vmm_error(log, "I2C Master Stimulus: Randomization of I2C Stimulus Packet Failed"); |
d_pkt.data_pkt = new[stim_packet.byte_count]; |
if(d_pkt.randomize()); else `vmm_error(log, "I2C Master Stimulus: Randomization of I2C Data Packet Failed"); |
stim_packet.data_packet = d_pkt.data_pkt; |
stim_packet.display(); |
d_pkt.display(); |
this.m_req_chan.put(stim_packet); // sending packet to master driver |
this.s_req_chan.put(stim_packet); // sending packet to slave driver |
end |
transaction_count--; |
end |
notify.indicate(DONE); // Indicate Enviorment that all scenarios have been sent to drivers. |
end |
endtask |
|
|
endclass |
|
|
|
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_program_test.sv
New file
0,0 → 1,24
////////////////////////////////////////////////////////////////////////////////////////// |
// // |
// Verification Engineer: Atish Jaiswal // |
// Company Name : TooMuch Semiconductor Solutions Pvt Ltd. // |
// // |
// Description of the Source File: // |
// This source code implements I2C M/S Core's Program Block. // |
// This Program Block instantiate i2c_env and run the main thread of environment. // |
// // |
// // |
////////////////////////////////////////////////////////////////////////////////////////// |
`include "vmm_i2c_env.sv" |
|
program program_test(i2c_pin_if pif); |
|
initial begin |
i2c_env env; |
env = new(pif); |
env.run(); |
end |
|
endprogram |
|
|
i2c_master_slave_core/trunk
Property changes :
Added: svn:mergeinfo
i2c_master_slave_core/web_uploads
Property changes :
Added: svn:mergeinfo
i2c_master_slave_core/branches
Property changes :
Added: svn:mergeinfo
/i2c_master_slave_core/tags/t1/i2c_master_slave_core/doc/i2c_spec.pdf
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
i2c_master_slave_core/tags/t1/i2c_master_slave_core/doc/i2c_spec.pdf
Property changes :
Added: svn:mime-type
+ application/octet-stream
/i2c_master_slave_core/tags/t1/i2c_master_slave_core/doc/i2c_spec.doc
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
i2c_master_slave_core/tags/t1/i2c_master_slave_core/doc/i2c_spec.doc
Property changes :
Added: svn:mime-type
+ application/octet-stream
/i2c_master_slave_core/tags/t1/i2c_master_slave_core/verilog/rtl/shift.v
New file
0,0 → 1,52
////////////////////////////Shift.v///////////////////////////////////////////////////////////////////// |
// // |
//Design Engineer: Ravi Gupta // |
//Company Name : Toomuch Semiconductor |
//Email : ravi1.gupta@toomuchsemi.com // |
// // |
//Purpose : Used for shifting address and data in both transmit and recieve mode // |
//created : 22-11-07 // |
// // |
//////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
/*// synopsys translate_off |
`include "oc8051_timescale.v" |
// synopsys translate_on |
|
`include "oc8051_defines.v"*/ |
|
|
module shift(clk,asyn_rst,load,shift_en,serial_in,data_in,serial_out,data_out); |
|
input clk,asyn_rst,load,shift_en,serial_in; |
input [7:0]data_in; |
|
output serial_out; |
output [7:0]data_out; |
|
reg [7:0]data; |
|
always@(posedge clk or posedge asyn_rst or posedge load) |
begin |
if(asyn_rst) |
data<=8'h0; //clear the data register upon asynchronous reset. |
|
else if(load) |
data<=data_in; //Load the internal register upon insertion of load bit. |
|
else if(shift_en) |
data<={data[6:0],serial_in}; //Upon shift_en high every time a new serial data is coming to LSB bit and data will be shifted |
//to one bit. |
else |
data<=data; //Prevent formation of latches |
end |
|
|
assign data_out = data; //Output the data in a data_register |
assign serial_out = data[7]; //MSB is transmitted first in I2C protocol. |
|
|
endmodule |
|
//change loading into asynchronous mode |
|
/i2c_master_slave_core/tags/t1/i2c_master_slave_core/verilog/rtl/counter.v
New file
0,0 → 1,41
//////////////////////////counter.v/////////////////////////////////////////////////////////////////////////////// |
// |
//Designed Engineer: Ravi Gupta // |
//Company Name : Toomuch Semiconductor |
//Email : ravi1.gupta@toomuchsemi.com // |
// |
//Purpose : Used for counting clock pulses for prescale register and number of bytes transferred // |
//Created : 22-11-07 // |
// |
////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
/*// synopsys translate_off |
`include "oc8051_timescale.v" |
// synopsys translate_on |
|
`include "oc8051_defines.v"*/ |
|
|
module counter (clk,asyn_rst,enable,load,data_in,out); |
|
input clk,asyn_rst,enable,load; |
input [7:0] data_in; |
output [7:0] out; |
|
reg [7:0]data; |
|
always@(posedge clk or posedge asyn_rst) |
begin |
if(asyn_rst) |
data<=8'h0; //clear all bits upon asynchronous reset. |
else if(load) |
data<=data_in; //load the counter with incoming data if load signal is high |
else if(enable) |
data<=data + 1'b1; //Increment the counter if enable bit is high |
else |
data<=data; //else hold the data;else part is mention to avoid latch formation |
end |
|
assign out=data; |
|
endmodule |
/i2c_master_slave_core/tags/t1/i2c_master_slave_core/verilog/rtl/controller_interface.v
New file
0,0 → 1,546
////////////////////////////////////////////controller_interface.v//////////////////////////////////////// |
// // |
//Design Engineer: Ravi Gupta // |
//Company Name : Toomuch Semiconductor |
//Email : ravi1.gupta@toomuchsemi.com // |
// // |
//Purpose : This core will be used as an interface between I2C core and Processor // |
//Created : 6-12-2007 // |
// // |
// // |
// // |
// // |
// // |
// // |
// // |
// // |
//Modification : Change the control register,added halt reset and inter_rst in control register |
///////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
/*// synopsys translate_off |
`include "oc8051_timescale.v" |
// synopsys translate_on |
|
`include "oc8051_defines.v"*/ |
|
|
module processor_interface (clk,rst,add_bus,data_in,data_out,as,ds,rw,bus_busy,byte_trans,slave_addressed,arb_lost,slave_rw,inter,ack_rec, |
core_en,inter_en,mode,master_rw,ack,rep_start,data,i2c_data,slave_add,time_out_reg,prescale,irq,time_out,inter_rst,halt,data_en,time_rst); |
input clk; //System clock |
input rst; //system reset |
|
//signals connecting core to processor |
///////////////////////////////////// |
|
input [7:0]add_bus; //contains address of internal register |
input [7:0]data_in; //trnasport the data for i2c core |
input as; //asserted high indicates vallid address has been placed on the address bus |
input ds; //asserted high indicates valid data on data bus |
input rw; //"1" indicates that processor has to write else read |
output irq; //interrupt to processor |
output inter_rst; //this bit will be written by processor when it will clear the interrupt. |
output [7:0]data_out; |
output halt; |
output data_en; |
input time_rst; |
|
//signals from core to reflect te status of core and buses |
/////////////////////////////////////////////////////////// |
|
input bus_busy; //signal from core indicates bus is busy |
input byte_trans; //signal from core indicates byte transfer is in progress |
input slave_addressed; //signal from core indicares core has been identified as slave |
input arb_lost; //signal from core indicates bus error |
input slave_rw; //signal from core indicates operation of slave core |
input inter; //signal from core.this will interrupt the processor if this bit as well as interrupt enable is high |
input ack_rec; //signal from core to reflect the status of ack bit |
input time_out; |
|
//bits of control register |
////////////////////////// |
|
inout core_en; //this bit must be cleared before any other bit of control register have any effect on core |
inout inter_en; //To intrrupt the core this bit must be set when interrupt is pending |
inout mode; //Transaction from "0" to "1" directes core to act as master else slave |
inout master_rw; //set directiion for master either to transmit or receive |
inout ack; //value of acknowledgment bit to be transmitted on SDA line during ack cycle |
inout rep_start; //set this bit if processor wants a repeated start |
|
//data register |
//////////////// |
|
inout [7:0]prescale; //contains the value for generating SCL frequency |
inout [7:0]time_out_reg; //contains the value for maximum low period for scl |
inout [7:0]slave_add; //this is the programmble slave address |
inout [7:0]data; //data for i2c core |
input [7:0]i2c_data; //data from core for processor |
|
//defining registers addresses |
///////////////////////////// |
|
`define PRER 8'b0000_0010 |
`define CTR 8'b0000_0100 |
`define SR 8'b0000_1000 |
`define TO 8'b0000_1010 |
`define ADDR 8'b0000_1100 |
`define DR 8'b0000_1110 |
`define RR 8'b0000_0000 |
|
/*//defing the machine state |
////////////////////////// |
|
parameter processor_idle=2'b00; |
parameter processor_address=2'b01; |
parameter processor_data=2'b10; |
parameter processor_ack=2'b11;*/ |
|
//Definig internal registers and wires |
///////////////////////////////////// |
|
wire core_en,inter_en,mode,master_rw,ack,rep_start,inter_rst,halt; |
wire prescale_reg_en; |
wire ctr_reg_en; |
wire sr_reg_en; |
wire to_reg_en; |
wire addr_reg_en; |
wire dr_reg_en; |
reg [7:0]data_out,sr_reg,ctr_reg,dr_reg,rr_reg; |
wire [7:0]data_in; //if address on add_bus matches with register address then set this high. |
wire data_ie; //this is signal used for enaling the data line in read or write cycle. |
wire as_d; //delay version of address strobe signal for detection of rising and falling edge |
reg as_delay_sig; //same signal. |
wire ds_d; //delayed version of data strobe. |
wire decode; |
wire rr_reg_en; |
|
reg ds_delay_sig; |
|
reg prescale_reg_en_sig; |
assign prescale_reg_en = prescale_reg_en_sig; |
|
reg ctr_reg_en_sig; |
assign ctr_reg_en = ctr_reg_en_sig; |
|
reg sr_reg_en_sig; |
assign sr_reg_en = sr_reg_en_sig; |
|
reg to_reg_en_sig; |
assign to_reg_en = to_reg_en_sig; |
|
reg addr_reg_en_sig; |
assign addr_reg_en = addr_reg_en_sig; |
|
reg dr_reg_en_sig; |
assign dr_reg_en = dr_reg_en_sig; |
|
reg as_d_sig; |
assign as_d = as_d_sig; |
|
reg ds_d_sig; |
assign ds_d = ds_d_sig; |
|
reg data_ie_sig; |
assign data_ie = data_ie_sig; |
|
//reg core_en_sig; |
//assign core_en = core_en_sig; |
|
//reg inter_en_sig; |
//assign inter_en = inter_en_sig; |
|
//reg mode_sig; |
//assign mode = mode_sig; |
|
//reg master_rw_sig; |
//assign master_rw = master_rw_sig; |
|
//reg ack_sig; |
//assign ack = ack_sig; |
|
//reg rep_start_sig; |
//assign rep_start = rep_start_sig; |
|
reg [7:0]data_sig; |
assign data = dr_reg; |
|
reg [7:0]prescale_sig; |
assign prescale = prescale_sig; |
|
reg [7:0]time_out_sig; |
assign time_out_reg = time_out_sig; |
|
reg [7:0]slave_add_sig; |
assign slave_add = slave_add_sig; |
|
//reg [7:0]data_out_sig; |
//assign data_out = data_out_sig; |
|
reg decode_sig; |
assign decode = decode_sig; |
|
//reg inter_rst_sig; |
//assign inter_rst = inter_rst_sig; |
|
//reg halt_sig; |
//assign halt = halt_sig; |
assign data_en = dr_reg_en_sig; |
|
reg rr_reg_en_sig; |
assign rr_reg_en = rr_reg_en_sig; |
|
|
|
assign core_en = ctr_reg [7]; |
assign inter_en = ctr_reg [6]; |
assign mode = ctr_reg [5]; |
assign master_rw = ctr_reg [4]; |
assign ack = ctr_reg [3]; |
assign rep_start = ctr_reg [2]; |
assign inter_rst = ctr_reg [1]; |
assign halt = ctr_reg [0]; |
|
|
|
|
|
|
//generating delayed version of inputs for detection of rising and falling edge. |
////////////////////////////////////////////////////////////////////////////// |
|
always@(posedge clk or posedge rst) |
begin |
|
if(rst) |
begin |
as_delay_sig<=1'b0; |
as_d_sig<=1'b0; |
ds_delay_sig<=1'b0; |
ds_d_sig<=1'b0; |
end |
|
else |
begin |
as_delay_sig<=as; |
as_d_sig<=as_delay_sig; |
ds_delay_sig<=ds; |
ds_d_sig<=ds_delay_sig; |
end |
end |
|
always@(posedge clk or posedge rst) |
begin |
if(rst) |
decode_sig<=1'b0; |
else if(!as_d && as) |
decode_sig<=1'b1; |
//else |
//decode_sig<=1'b0; |
end |
|
//address decoding logic |
/////////////////////// |
|
//always@(posedge clk or posedge rst) |
always@(rst or as or add_bus or posedge time_rst) |
begin |
|
if(rst || time_rst) |
begin |
prescale_reg_en_sig<=1'b0; |
ctr_reg_en_sig<=1'b0; |
sr_reg_en_sig<=1'b0; |
to_reg_en_sig<=1'b0; |
addr_reg_en_sig<=1'b0; |
dr_reg_en_sig<=1'b0; |
rr_reg_en_sig <= 1'b0; |
|
//add_match_sig<=1'b0; |
end |
|
|
|
else if(as) |
begin |
if(add_bus == `PRER) |
begin |
rr_reg_en_sig <= 1'b0; |
prescale_reg_en_sig<=1'b1; |
ctr_reg_en_sig<=1'b0; |
sr_reg_en_sig<=1'b0; |
to_reg_en_sig<=1'b0; |
addr_reg_en_sig<=1'b0; |
dr_reg_en_sig<=1'b0; |
//add_match_sig<=1'b1; |
end |
|
else if(add_bus == `CTR) |
begin |
rr_reg_en_sig <= 1'b0; |
prescale_reg_en_sig<=1'b0; |
ctr_reg_en_sig<=1'b1; |
sr_reg_en_sig<=1'b0; |
to_reg_en_sig<=1'b0; |
addr_reg_en_sig<=1'b0; |
dr_reg_en_sig<=1'b0; |
//add_match_sig<=1'b1; |
end |
|
else if(add_bus == `SR) |
begin |
rr_reg_en_sig <= 1'b0; |
prescale_reg_en_sig<=1'b0; |
ctr_reg_en_sig<=1'b0; |
sr_reg_en_sig<=1'b1; |
to_reg_en_sig<=1'b0; |
addr_reg_en_sig<=1'b0; |
dr_reg_en_sig<=1'b0; |
//add_match_sig<=1'b1; |
end |
|
else if(add_bus == `TO) |
begin |
rr_reg_en_sig <= 1'b0; |
prescale_reg_en_sig<=1'b0; |
ctr_reg_en_sig<=1'b0; |
sr_reg_en_sig<=1'b0; |
to_reg_en_sig<=1'b1; |
addr_reg_en_sig<=1'b0; |
dr_reg_en_sig<=1'b0; |
//add_match_sig<=1'b1; |
end |
|
else if(add_bus == `ADDR) |
begin |
rr_reg_en_sig <= 1'b0; |
prescale_reg_en_sig<=1'b0; |
ctr_reg_en_sig<=1'b0; |
sr_reg_en_sig<=1'b0; |
to_reg_en_sig<=1'b0; |
addr_reg_en_sig<=1'b1; |
dr_reg_en_sig<=1'b0; |
//add_match_sig<=1'b1; |
end |
|
else if(add_bus == `DR) |
begin |
|
prescale_reg_en_sig<=1'b0; |
ctr_reg_en_sig<=1'b0; |
sr_reg_en_sig<=1'b0; |
to_reg_en_sig<=1'b0; |
addr_reg_en_sig<=1'b0; |
dr_reg_en_sig<=1'b1; |
rr_reg_en_sig <= 1'b0; |
//add_match_sig<=1'b1; |
end |
|
else if(add_bus == `RR) |
begin |
rr_reg_en_sig <= 1'b1; |
prescale_reg_en_sig<=1'b0; |
ctr_reg_en_sig<=1'b0; |
sr_reg_en_sig<=1'b0; |
to_reg_en_sig<=1'b0; |
addr_reg_en_sig<=1'b0; |
dr_reg_en_sig<=1'b0; |
//add_match_sig<=1'b1; |
end |
|
else |
begin |
rr_reg_en_sig <= 1'b0; |
prescale_reg_en_sig<=1'b0; |
ctr_reg_en_sig<=1'b0; |
sr_reg_en_sig<=1'b0; |
to_reg_en_sig<=1'b0; |
addr_reg_en_sig<=1'b0; |
dr_reg_en_sig<=1'b0; |
//add_match_sig<=1'b0; |
end |
|
|
end |
else |
begin |
prescale_reg_en_sig<=1'b0; |
ctr_reg_en_sig<=1'b0; |
sr_reg_en_sig<=1'b0; |
to_reg_en_sig<=1'b0; |
addr_reg_en_sig<=1'b0; |
dr_reg_en_sig<=1'b0; |
rr_reg_en_sig <= 1'b0; |
end |
|
end |
|
//assigning value of data_ie line |
////////////////////////////////// |
always@(posedge clk or posedge rst) |
begin |
if(rst) |
data_ie_sig<=1'b0; |
else if(!ds_d && ds) |
data_ie_sig<=1'b1; |
|
end |
|
|
//read data to/from the register specified by processor addrress. |
|
|
//always@(rst or addr_reg_en or ctr_reg_en or dr_reg_en or sr_reg_en or prescale_reg_en or to_reg_en or data_ie or rw or data_in ) |
|
always@(posedge clk or posedge rst) |
begin |
if(rst) |
begin |
sr_reg <= 8'b0; |
dr_reg <= 8'b0; |
rr_reg <= 8'b0; |
//ctr_reg <= 8'b0; |
end |
|
/*else if(ctr_reg_en) |
begin |
//sr_reg <= {byte_trans,slave_addressed,bus_busy,arb_lost,time_out,slave_rw,inter,ack_rec}; |
ctr_reg <= data_in; |
end*/ |
else |
begin |
sr_reg <= {byte_trans,slave_addressed,bus_busy,arb_lost,time_out,slave_rw,inter,ack_rec}; |
rr_reg <= i2c_data; |
end |
end |
|
always@(posedge clk or posedge rst or posedge time_rst) |
begin |
if(rst || time_rst) |
begin |
//initializing control register |
ctr_reg <= 8'b0; |
/*core_en_sig <= 1'b0; |
inter_en_sig <= 1'b0; |
mode_sig <= 1'b0; |
master_rw_sig <= 1'b0; |
ack_sig <= 1'b0; |
rep_start_sig <= 1'b0; |
inter_rst_sig<=1'b0;*/ |
//initializing data and timer register |
data_sig <= 8'b00000000; |
prescale_sig <= 8'b00000000; |
time_out_sig <= 8'b00000000; |
data_out <= 8'b00000000; |
end |
|
else if (data_ie) |
begin |
//address register |
if(addr_reg_en) //if address matches with slave address register |
begin |
if(rw) //processor write cycle |
slave_add_sig <= {data_in[7:1] , 1'b0}; |
else //processor read cycle |
data_out <= slave_add; |
end |
|
//control register |
if(ctr_reg_en) //if address matches with cntrol register |
begin |
if(rw) //processor write cycle |
//begin |
/*core_en_sig <= #2 ctr_reg [7]; |
inter_en_sig <= #2 ctr_reg [6]; |
mode_sig <= #2 ctr_reg [5]; |
master_rw_sig <= #2 ctr_reg [4]; |
ack_sig <= #2 ctr_reg [3]; |
rep_start_sig <= #2 ctr_reg [2]; |
inter_rst_sig <= #2 ctr_reg [1]; |
halt_sig <= #2 ctr_reg [0];*/ |
//end |
|
//else |
ctr_reg <= data_in; //processor read cycle |
else |
data_out <= ctr_reg; |
end |
|
else if(!byte_trans && bus_busy) |
ctr_reg[1:0] <= 2'b0; |
//data register |
|
if(dr_reg_en) |
begin |
if(rw) |
dr_reg <= data_in; |
else |
data_out <= dr_reg; |
end |
|
if(rr_reg_en) |
begin |
data_out <= rr_reg; |
end |
|
//staus register |
|
if(sr_reg_en) |
begin |
if(!rw) |
//begin |
//if(data_in[0]==1'b0) |
//inter_rst_sig <= 1'b0; |
//else |
//inter_rst_sig <= 1'b1; |
//end |
//else |
//begin |
data_out <= sr_reg; |
//inter_rst_sig<=1'b0; |
//end |
//else |
//inter_rst_sig<=1'b0; |
|
end |
|
|
//prescale register |
|
if(prescale_reg_en) |
begin |
if(rw) |
prescale_sig <= data_in; |
else |
data_out <= prescale; |
end |
|
//time_out register |
|
if(to_reg_en) |
begin |
if(rw) |
time_out_sig <= data_in; |
else |
data_out <= time_out_reg; |
end |
end |
end |
|
//assigning values to bidirectional bus |
////////////////////////////////////// |
|
//assign data_bus = (!rw && data_ie) ? data_out : 8'bzzzzzzzz; |
//assign data_in = (rw) ? data_bus : 8'bzzzzzzzz; |
|
//interuupt pin to processor |
assign irq = (inter && inter_en) ? 1'b1 : 1'b0; |
endmodule |
|
|
|
|
|
|
|
|
|
|
/i2c_master_slave_core/tags/t1/i2c_master_slave_core/verilog/rtl/i2c_blk.v
New file
0,0 → 1,172
////////////////////////////////////////////////////////////////////////////////////////// |
//Design Engineer: Ravi Gupta // |
//Company Name : Toomuch Semiconductor |
//Email : ravi1.gupta@toomuchsemi.com // |
// // |
// // |
//Purpose : This module will simply interconnect controller interface // // |
// controller_interface with ms_core. // |
// // |
// // |
//Date : 11-12-07 // |
// // |
// // |
// // |
// // |
// // |
// // |
// // |
////////////////////////////////////////////////////////////////////////////////////////// |
/*// synopsys translate_off |
`include "oc8051_timescale.v" |
// synopsys translate_on |
|
`include "oc8051_defines.v"*/ |
|
|
module block(scl_oe,scl_in,scl_o,sda_oe,sda_in,sda_o,wb_add_i,wb_data_i,wb_data_o,wb_we_i,wb_stb_i,wb_cyc_i,irq,trans_comp,wb_clk_i,wb_rst_i,wb_ack_o); |
|
//inout scl; //Bi-directional lines to follow i2c protocol for data transfer. |
input sda_in; //sda input |
output sda_oe; //control line for bidirectional buffer |
output sda_o; //input line for bi_firectional buffer |
input scl_in; |
output scl_o; |
output scl_oe; |
input [7:0]wb_data_i; //Bi-direction buses for transfering data to/from processor. |
input [7:0]wb_add_i; //Transfer the addresses of intenal registers. |
input wb_we_i; //signal from processor to indicate whether its a read or write cycle. |
input wb_stb_i; //when asserted indicates address is valid. |
input wb_cyc_i; //when asserted indicates data is valid. |
output irq; //interupt signal to processor. |
input wb_clk_i; //system clock. |
input wb_rst_i; //asynchrnous reset active high. |
inout trans_comp; //temprory signal for testing the core |
output [7:0]wb_data_o; |
output wb_ack_o; |
|
//declaratiion of internal signals |
////////////////////////////////// |
|
// control register |
wire [7:0] slave_add; // I2C address |
wire arb_lost; // indicates that arbitration for the i2c bus is lost |
wire bus_busy; // indicates the i2c bus is busy |
wire [7:0] i2c_up; // i2c data register |
wire [7:0] data; // uC data register |
wire core_en; // i2c enable - used as i2c reset |
wire inter_en; // interrupt enable |
wire inter; // interrupt pending |
wire mode; // i2c master/slave select |
wire master_rw; // master read/write |
wire rep_start; // generate a repeated start |
wire ack_rec; // value of received acknowledge |
wire slave_rw; // slave read/write |
wire ack; // value of acknowledge to be transmitted |
wire byte_trans; // indicates that one byte of data is being transferred |
wire slave_addressed; // address of core matches with address transferred |
wire time_out; // max low period for SCL has excedded |
wire [7:0]time_out_reg; // programmable max time for SCL low period |
wire [7:0]prescale; |
wire inter_rst; |
wire [7:0]wb_data_o; |
wire halt; |
wire data_en; |
wire time_rst; |
reg wb_ack_o; |
wire rst; |
|
assign trans_comp = byte_trans; |
|
always@(posedge wb_clk_i) |
begin |
wb_ack_o <= #1 wb_stb_i & wb_cyc_i & ~wb_ack_o; |
end |
|
//port map for i2c controller |
//////////////////////////// |
|
core i2c_core |
|
( |
.clk(wb_clk_i), |
.rst(core_en), |
.sda_oe(sda_oe), |
.sda_in(sda_in), |
.sda_o(sda_o), |
.scl_oe(scl_oe), |
.scl_o(scl_o), |
.scl_in(scl_in), |
.ack(ack), |
.mode(mode), |
.rep_start(rep_start), |
.master_rw(master_rw), |
.data_in(data[7:0]), |
.slave_add(slave_add[7:0]), |
.bus_busy(bus_busy), |
.byte_trans(byte_trans), |
.slave_addressed(slave_addressed), |
.arb_lost(arb_lost), |
.slave_rw(slave_rw), |
.time_out(time_out), |
.inter(inter), |
.ack_rec(ack_rec), |
.i2c_up(i2c_up[7:0]), |
.time_out_reg(time_out_reg[7:0]), |
.prescale_reg(prescale[7:0]), |
.inter_en(inter_en), |
.inter_rst(inter_rst), |
.data_en(data_en), |
.halt_rst(halt), |
.h_rst(wb_rst_i), |
.time_rst(time_rst)); |
|
|
//port map for controller interface |
/////////////////////////////////// |
|
processor_interface processor_interface |
|
( |
.clk(wb_clk_i), |
.rst(wb_rst_i), |
.add_bus(wb_add_i[7:0]), |
.data_in(wb_data_i[7:0]), |
.as(wb_stb_i), |
.ds(wb_cyc_i), |
.rw(wb_we_i), |
.bus_busy(bus_busy), |
.byte_trans(byte_trans), |
.slave_addressed(slave_addressed), |
.arb_lost(arb_lost), |
.slave_rw(slave_rw), |
.inter(inter), |
.ack_rec(ack_rec), |
.core_en(core_en), |
.inter_en(inter_en), |
.mode(mode), |
.master_rw(master_rw), |
.ack(ack), |
.rep_start(rep_start), |
.data(data[7:0]), |
.i2c_data(i2c_up[7:0]), |
.slave_add(slave_add), |
.time_out_reg(time_out_reg[7:0]), |
.prescale(prescale[7:0]), |
.irq(irq), |
.time_out(time_out), |
.inter_rst(inter_rst), |
.halt(halt), |
.data_en(data_en), |
.time_rst(time_rst), |
.data_out(wb_data_o)); |
|
//always@(scl or sda) |
//$display($time,"scl=%b\tsda=%b\t\n",scl,sda); |
|
|
endmodule |
|
|
|
|
/i2c_master_slave_core/tags/t1/i2c_master_slave_core/verilog/rtl/ms_core.v
New file
0,0 → 1,1157
///////////////////////////////////////ms_core.v//////////////////////////////////////////////////////////////////////// |
// // |
//Design engineer: Ravi Gupta // |
//Company Name : Toomuch Semiconductor |
//Email : ravi1.gupta@toomuchsemi.com // |
// // |
//Purpose : This is the core which will be used to interface I2C bus. // |
//Created : 23-11-07 // |
// |
//Modification : Changes made in data_reg_ld // |
// |
//Modification : Change byte_trans generation bit // |
// |
//Modification : Implemented a halt bit that will be generated at the completion of 9th scl pulse in master_mode only // |
// |
//Modification : After core reset(time out feature) core will go in idle escaping stop generation so need to clear // |
//all // |
//of status register. // |
// |
//Modification : Remove the sm_state clause,so that even if there is no acknowledegement it will not stop the // |
//generation of SCL and SDA // |
//untill it gets command to generate stop from processor. // |
// |
//Modification : Now also checking for detect_start in acknowledgement state for repeted start condition. // |
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
module core(clk,rst,sda_oe,sda_in,sda_o,scl_oe,scl_in,scl_o,ack,mode,rep_start,master_rw,data_in,slave_add,bus_busy,byte_trans,slave_addressed,arb_lost,slave_rw,time_out,inter,ack_rec,i2c_up,time_out_reg,prescale_reg,inter_rst,inter_en,halt_rst,data_en,time_rst,h_rst); |
|
////////////////////////////////////////////////signal defination//////////////////////////////////////////////////////////////// |
|
input clk; //System Clock |
input rst; //Main Reset |
output sda_oe; //I2C serial data line output to be connected to control line of bidirectional buffer on physical SDA line |
input sda_in; //I2C serial data line input |
output sda_o; //I2C sda line always asssign to zero this is to be connected to input of bidirectional buffer on physical SDA line |
output scl_oe; //I2C serial clock line output to be connected to control line of bidirectiional buffer on physical scl line |
input scl_in; //I2C serial clock line input |
output scl_o; //SCL output line to be connected to input of bidirectional line |
input ack; //Acknowledgement signal from control register |
input mode; //master/slave mode select |
input rep_start; //repeated start |
input master_rw; //command to core in master mode |
input [7:0]data_in; //data from processor to be outputed on I2C |
input [7:0]slave_add; //I2C slave address |
input data_en; |
output time_rst; |
input h_rst; |
|
//status signal: |
|
output bus_busy; //bus busy |
inout byte_trans; //transfer of byte is in progress_reg_en |
|
inout slave_addressed; //addressed as slave |
inout arb_lost; //arbitration has lost |
inout slave_rw; //indicates the operation by slave |
inout time_out; //indicates that SCL LOW time has been exceeded |
output inter; //interrupt pending,will be used for interrupting processor |
input inter_rst; //use to clear the interrupt |
input inter_en; //processor wants to take interrupt or not |
|
//signal for processor |
input halt_rst; |
output ack_rec; //indicates that ack has been recieved,will be used to inform if master reciever wants to terminate the transfer |
output [7:0]i2c_up; //I2C data for micro processor |
//timing control registers |
input [7:0]time_out_reg; //max SCL low period. |
input [7:0]prescale_reg; //clock divider for generating SCL frequency. |
|
/////////////////////////////////////////End of port defination////////////////////////////////////////////////////////////////// |
|
wire master_slave,arbitration_lost,bb,gen_start,rep_start,byte_trans_delay,byte_trans_fall; |
|
//wire scl_out,sda_out,clk_cnt_enable,clk_cnt_rst,bit_cnt_enable,bit_cnt_rst,timer_cnt_enable,timer_cnt_rst,scl_in,sda_in,sda_out_reg,stop_scl_reg,master_sda, gen_stop; |
wire master_sda,scl_in,gen_stop,sm_stop,detect_stop,detect_start,addr_match,core_rst,stop_scl,scl_out,neg_scl_sig,sda_sig; |
//reg [7:0]clk1_cnt,bit1_cnt,timer1_cnt; |
reg posedge_mode,negedge_mode; |
reg [2:0]scl_state; |
reg [1:0]state; |
reg [2:0]scl_main_state; |
wire [7:0] add_reg,shift_reg; |
wire [7:0]clk_cnt,bit_cnt; |
reg [7:0]time_cnt; |
reg [7:0]i2c_up; |
wire bit_cnt_enable,bit_cnt_rst,clk_cnt_enable,clk_cnt_rst,data_reg_ld,data_reg_en,sda_in,serial_out,i2c_serial_out,add_reg_ld,add_reg_en,posedge_mode_sig,negedge_mode_sig,interrupt; |
wire [7:0]zero; |
wire [7:0]reg_clr; |
|
wire slave_sda,sda_out,halt,arb_rst,interrupt_rst,d_detect_stop; |
|
shift shift_data(neg_scl,rst,data_reg_ld,data_reg_en,sda_in,data_in,serial_out,shift_reg); //shift register for transferring the data |
shift shift_add(neg_scl,rst,add_reg_ld,add_reg_en,sda_in,reg_clr,i2c_serial_out,add_reg); //shift register for transferring address |
counter clock_counter(clk,rst,clk_cnt_enable,clk_cnt_rst,zero,clk_cnt); //This will count number of clock pulses for prescale |
counter bit_counter(neg_scl,rst,bit_cnt_enable,bit_cnt_rst,zero,bit_cnt); //Implementation of bit counter |
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
reg clk_cnt_enable_sig; |
assign clk_cnt_enable = clk_cnt_enable_sig; |
|
reg clk_cnt_rst_sig; |
assign clk_cnt_rst = clk_cnt_rst_sig; |
|
|
//reg sda_in_sig; |
//assign sda_in = sda_in_sig; |
|
reg sm_stop_sig; |
assign sm_stop = sm_stop_sig; |
|
//reg scl_in_sig; |
//assign scl_in = scl_in_sig; |
|
reg gen_start_sig; |
assign gen_start = gen_start_sig; |
|
reg gen_stop_sig; |
assign gen_stop = gen_stop_sig; |
|
reg master_slave_sig; |
assign master_slave = master_slave_sig; |
|
reg detect_start_sig; |
assign detect_start=detect_start_sig; |
|
reg detect_stop_sig; |
assign detect_stop=detect_stop_sig; |
|
reg byte_trans_sig; |
assign byte_trans= byte_trans_sig; |
|
reg bb_sig; |
assign bb=bb_sig; |
|
reg slave_addressed_sig; |
assign slave_addressed=slave_addressed_sig; |
|
reg slave_rw_sig; |
assign slave_rw=slave_rw_sig; |
|
reg inter_sig; |
assign inter=inter_sig; |
assign interrupt=inter_sig; |
|
reg time_out_sig; |
assign time_out=time_out_sig; |
|
reg ack_rec_sig; |
assign ack_rec=ack_rec_sig; |
|
reg add_reg_enable_sig; |
assign add_reg_en=add_reg_enable_sig; |
|
reg data_reg_en_sig; |
assign data_reg_en=data_reg_en_sig; |
|
reg data_reg_ld_sig; |
assign data_reg_ld=data_reg_ld_sig; |
|
reg stop_scl_sig; |
assign stop_scl=stop_scl_sig; |
|
reg core_rst_sig; |
assign core_rst=core_rst_sig; |
|
reg sda_out_sig; |
assign sda_out=sda_out_sig; |
|
reg scl_out_sig; |
assign scl_out=scl_out_sig; |
|
reg master_sda_sig; |
assign master_sda=master_sda_sig; |
|
reg slave_sda_sig; |
assign slave_sda=slave_sda_sig; |
|
reg arbitration_lost_sig; |
assign arbitration_lost=arbitration_lost_sig; |
|
reg arb_lost_sig; |
assign arb_lost=arb_lost_sig; |
|
reg byte_trans_delay_sig; |
assign byte_trans_delay=byte_trans_delay_sig; |
|
reg byte_trans_fall_sig; |
assign byte_trans_fall=byte_trans_fall_sig; |
|
reg halt_sig; |
assign halt = halt_sig; |
|
reg arb_rst_sig; |
assign arb_rst=arb_rst_sig; |
|
reg interrupt_rst_sig; |
assign interrupt_rst=interrupt_rst_sig; |
|
