OpenCores
URL https://opencores.org/ocsvn/oms8051mini/oms8051mini/trunk

Subversion Repositories oms8051mini

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /oms8051mini
    from Rev 28 to Rev 29
    Reverse comparison

Rev 28 → Rev 29

/trunk/verif/agents/i2cs/i2c_slave_model.v
0,0 → 1,356
/////////////////////////////////////////////////////////////////////
//// ////
//// WISHBONE rev.B2 compliant synthesizable I2C Slave model ////
//// ////
//// ////
//// Authors: Richard Herveille (richard@asics.ws) www.asics.ws ////
//// John Sheahan (jrsheahan@optushome.com.au) ////
//// ////
//// Downloaded from: http://www.opencores.org/projects/i2c/ ////
//// ////
/////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001,2002 Richard Herveille ////
//// richard@asics.ws ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer.////
//// ////
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ////
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ////
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ////
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ////
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ////
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ////
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ////
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ////
//// POSSIBILITY OF SUCH DAMAGE. ////
//// ////
/////////////////////////////////////////////////////////////////////
 
// CVS Log
//
// $Id: i2c_slave_model.v,v 1.7 2006-09-04 09:08:51 rherveille Exp $
//
// $Date: 2006-09-04 09:08:51 $
// $Revision: 1.7 $
// $Author: rherveille $
// $Locker: $
// $State: Exp $
//
// Change History:
// $Log: not supported by cvs2svn $
// Revision 1.6 2005/02/28 11:33:48 rherveille
// Fixed Tsu:sta timing check.
// Added Thd:sta timing check.
//
// Revision 1.5 2003/12/05 11:05:19 rherveille
// Fixed slave address MSB='1' bug
//
// Revision 1.4 2003/09/11 08:25:37 rherveille
// Fixed a bug in the timing section. Changed 'tst_scl' into 'tst_sto'.
//
// Revision 1.3 2002/10/30 18:11:06 rherveille
// Added timing tests to i2c_model.
// Updated testbench.
//
// Revision 1.2 2002/03/17 10:26:38 rherveille
// Fixed some race conditions in the i2c-slave model.
// Added debug information.
// Added headers.
//
 
 
module i2c_slave_model (scl, sda);
 
//
// parameters
//
parameter I2C_ADR = 7'b001_0000;
 
//
// input && outpus
//
input scl;
inout sda;
 
//
// Variable declaration
//
wire debug = 1'b1;
 
reg [7:0] mem [255:0]; // initiate memory
reg [7:0] mem_adr; // memory address
reg [7:0] mem_do; // memory data output
 
reg sta, d_sta;
reg sto, d_sto;
 
reg [7:0] sr; // 8bit shift register
reg rw; // read/write direction
 
wire my_adr; // my address called ??
wire i2c_reset; // i2c-statemachine reset
reg [2:0] bit_cnt; // 3bit downcounter
wire acc_done; // 8bits transfered
reg ld; // load downcounter
 
reg sda_o; // sda-drive level
wire sda_dly; // delayed version of sda
 
// statemachine declaration
parameter idle = 3'b000;
parameter slave_ack = 3'b001;
parameter get_mem_adr = 3'b010;
parameter gma_ack = 3'b011;
parameter data = 3'b100;
parameter data_ack = 3'b101;
 
reg [2:0] state; // synopsys enum_state
 
//
// module body
//
 
initial
begin
sda_o = 1'b1;
state = idle;
end
 
// generate shift register
always @(posedge scl)
sr <= #1 {sr[6:0],sda};
 
//detect my_address
assign my_adr = (sr[7:1] == I2C_ADR);
// FIXME: This should not be a generic assign, but rather
// qualified on address transfer phase and probably reset by stop
 
//generate bit-counter
always @(posedge scl)
if(ld)
bit_cnt <= #1 3'b111;
else
bit_cnt <= #1 bit_cnt - 3'h1;
 
//generate access done signal
assign acc_done = !(|bit_cnt);
 
// generate delayed version of sda
// this model assumes a hold time for sda after the falling edge of scl.
// According to the Phillips i2c spec, there s/b a 0 ns hold time for sda
// with regards to scl. If the data changes coincident with the clock, the
// acknowledge is missed
// Fix by Michael Sosnoski
assign #1 sda_dly = sda;
 
 
//detect start condition
always @(negedge sda)
if(scl)
begin
sta <= #1 1'b1;
d_sta <= #1 1'b0;
sto <= #1 1'b0;
 
if(debug)
$display("DEBUG i2c_slave; start condition detected at %t", $time);
end
else
sta <= #1 1'b0;
 
always @(posedge scl)
d_sta <= #1 sta;
 
// detect stop condition
always @(posedge sda)
if(scl)
begin
sta <= #1 1'b0;
sto <= #1 1'b1;
 
if(debug)
$display("DEBUG i2c_slave; stop condition detected at %t", $time);
end
else
sto <= #1 1'b0;
 
//generate i2c_reset signal
assign i2c_reset = sta || sto;
 
// generate statemachine
always @(negedge scl or posedge sto)
if (sto || (sta && !d_sta) )
begin
state <= #1 idle; // reset statemachine
 
sda_o <= #1 1'b1;
ld <= #1 1'b1;
end
else
begin
// initial settings
sda_o <= #1 1'b1;
ld <= #1 1'b0;
 
case(state) // synopsys full_case parallel_case
idle: // idle state
if (acc_done && my_adr)
begin
state <= #1 slave_ack;
rw <= #1 sr[0];
sda_o <= #1 1'b0; // generate i2c_ack
 
#2;
if(debug && rw)
$display("DEBUG i2c_slave; command byte received (read) at %t", $time);
if(debug && !rw)
$display("DEBUG i2c_slave; command byte received (write) at %t", $time);
 
if(rw)
begin
mem_do <= #1 mem[mem_adr];
 
if(debug)
begin
#2 $display("DEBUG i2c_slave; data block read %x from address %x (1)", mem_do, mem_adr);
#2 $display("DEBUG i2c_slave; memcheck [%x]=%x", mem_adr, mem[mem_adr]);
end
end
end
 
slave_ack:
begin
if(rw)
begin
state <= #1 data;
sda_o <= #1 mem_do[7];
end
else
state <= #1 get_mem_adr;
 
ld <= #1 1'b1;
end
 
get_mem_adr: // wait for memory address
if(acc_done)
begin
state <= #1 gma_ack;
mem_adr <= #1 sr; // store memory address
sda_o <= #1 !(sr <= 255); // generate i2c_ack, for valid address
 
if(debug)
#1 $display("DEBUG i2c_slave; address received. adr=%x, ack=%b", sr, sda_o);
end
 
gma_ack:
begin
state <= #1 data;
ld <= #1 1'b1;
end
 
data: // receive or drive data
begin
if(rw)
sda_o <= #1 mem_do[7];
 
if(acc_done)
begin
state <= #1 data_ack;
mem_adr <= #2 mem_adr + 8'h1;
sda_o <= #1 (rw && (mem_adr <= 255) ); // send ack on write, receive ack on read
 
if(rw)
begin
#3 mem_do <= mem[mem_adr];
 
if(debug)
#5 $display("DEBUG i2c_slave; data block read %x from address %x (2)", mem_do, mem_adr);
end
 
if(!rw)
begin
mem[ mem_adr ] <= #1 sr; // store data in memory
 
if(debug)
#2 $display("DEBUG i2c_slave; data block write %x to address %x", sr, mem_adr);
end
end
end
 
data_ack:
begin
ld <= #1 1'b1;
 
if(rw)
if(sr[0]) // read operation && master send NACK
begin
state <= #1 idle;
sda_o <= #1 1'b1;
end
else
begin
state <= #1 data;
sda_o <= #1 mem_do[7];
end
else
begin
state <= #1 data;
sda_o <= #1 1'b1;
end
end
 
endcase
end
 
// read data from memory
always @(posedge scl)
if(!acc_done && rw)
mem_do <= #1 {mem_do[6:0], 1'b1}; // insert 1'b1 for host ack generation
 
// generate tri-states
assign sda = sda_o ? 1'bz : 1'b0;
 
 
//
// Timing checks
//
 
wire tst_sto = sto;
wire tst_sta = sta;
 
specify
specparam normal_scl_low = 4700,
normal_scl_high = 4000,
normal_tsu_sta = 4700,
normal_thd_sta = 4000,
normal_tsu_sto = 4000,
normal_tbuf = 4700,
 
fast_scl_low = 1300,
fast_scl_high = 600,
fast_tsu_sta = 1300,
fast_thd_sta = 600,
fast_tsu_sto = 600,
fast_tbuf = 1300;
 
$width(negedge scl, normal_scl_low); // scl low time
$width(posedge scl, normal_scl_high); // scl high time
 
$setup(posedge scl, negedge sda &&& scl, normal_tsu_sta); // setup start
$setup(negedge sda &&& scl, negedge scl, normal_thd_sta); // hold start
$setup(posedge scl, posedge sda &&& scl, normal_tsu_sto); // setup stop
 
$setup(posedge tst_sta, posedge tst_sto, normal_tbuf); // stop to start time
endspecify
 
endmodule
 
 
trunk/verif/agents/i2cs/i2c_slave_model.v Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: trunk/verif/defs/tb_defines.v =================================================================== --- trunk/verif/defs/tb_defines.v (revision 28) +++ trunk/verif/defs/tb_defines.v (revision 29) @@ -23,10 +23,12 @@ //-------------------------------------------------------------- // Target ID Mapping +// 4'b0011 -- I2CM // 4'b0010 -- UART // 4'b0001 -- SPI core // 4'b0000 -- External RAM //-------------------------------------------------------------- +`define ADDR_SPACE_I2CM 4'b0011 `define ADDR_SPACE_UART 4'b0010 `define ADDR_SPACE_SPI 4'b0001 `define ADDR_SPACE_RAM 4'b0000
/trunk/verif/run/filelist_tb.f
14,6 → 14,7
./time_scale.v \
../tb/tb_top.v \
../../verif/agents/uart/uart_agent.v \
../../verif/agents/i2cs/i2c_slave_model.v \
../../verif/agents/spi/atmel/AT45DBXXX_v2.0.3.v \
../../verif/agents/spi/st_m25p20a/acdc_check.v \
../../verif/agents/spi/st_m25p20a/internal_logic.v \
/trunk/verif/tb/tb_tasks.v
136,10 → 136,36
@(posedge app_clk);
reg_cs = 0;
 
//$display ("Config-Read: Id: %h Addr = %h, Data = %h", block_id,address, read_data);
$display ("Config-Read: Id: %h Addr = %h, Data = %h", block_id,address, read_data);
end
endtask
 
task cpu_byte_read_cmp;
input [3:0] block_id;
input [15:0] address;
input [7:0] exp_read_data;
reg [7:0] read_data;
begin
@(posedge app_clk);
reg_id = block_id;
 
// Byte-0
reg_cs = 1;
reg_wr = 0;
reg_be = 1'h1;
reg_addr = address;
@(posedge reg_ack);
#1 read_data[7:0] = reg_rdata[7:0];
@(posedge app_clk);
reg_cs = 0;
 
if(read_data !== exp_read_data) begin
$display ("ERROR: REG READ : Id: %h Addr = %h, Data = %h", block_id,address, read_data);
`TB_GLBL.test_err;
end else
$display ("Config-Read: Id: %h Addr = %h, Data = %h", block_id,address, read_data);
end
endtask
task cpu_byte_write;
input [3:0] block_id; // 0/1/2 --> ram/spi/uart
input [15:0] address;
/trunk/verif/tb/tb_top.v
129,6 → 129,7
wire clkout ;
wire reset_out_n ;
 
parameter I2CS_ADDR = 7'b0010_000; // I2C Slave Addr
//----------------------------------------
 
digital_core u_core (
165,12 → 166,36
.spi_sck (spi_sck ),
.spi_so (spi_so ),
.spi_si (spi_si ),
.spi_cs_n (spi_cs_n )
.spi_cs_n (spi_cs_n ),
 
// i2cm clock line
.i2cm_scl_i (scl ),
.i2cm_scl_o (i2cm_scl_o ),
.i2cm_scl_oen (i2cm_scl_oen ),
 
// i2cm data line
.i2cm_sda_i (sda ),
.i2cm_sda_o (i2cm_sda_o ),
.i2cm_sda_oen (i2cm_sda_oen )
 
 
 
);
 
// create i2c lines
delay m0_scl (i2cm_scl_oen ? 1'bz : i2cm_scl_o, scl),
m0_sda (i2cm_sda_oen ? 1'bz : i2cm_sda_o, sda);
 
pullup p1(scl); // pullup scl line
pullup p2(sda); // pullup sda line
 
// hookup i2c slave model
i2c_slave_model #(I2CS_ADDR) tb_i2cs (
.scl (scl ),
.sda (sda )
);
 
 
uart_agent tb_uart (
. test_clk (uart_clk_16x ),
. sin (si ),
264,6 → 289,8
uart_test1();
else if ( $test$plusargs("spi_test_1") )
spi_test1();
else if ( $test$plusargs("i2cm_test_1") )
i2cm_test1();
else begin
// 8051 Test Cases
#80000000
297,10 → 324,21
end
 
 
module delay (in, out);
input in;
output out;
 
assign out = in;
 
specify
(in => out) = (600,600);
endspecify
endmodule
 
 
`include "uart_test1.v"
`include "spi_test1.v"
`include "i2cm_test1.v"
`include "tb_tasks.v"
`include "spi_tasks.v"
 
/trunk/verif/testcase/i2cm_test1.v
0,0 → 1,135
/**********************************************************
I2C Master Test
**********************************************************/
task i2cm_test1;
reg [7:0] rdata;
begin
$display("############################################");
$display(" Testing I2CM Read/Write Access ");
$display("############################################");
@(posedge app_clk);
$display("---------- Initialize I2C Master ----------");
//Wrire Prescale registers
tb_top.cpu_byte_write(`ADDR_SPACE_I2CM,8'h0,8'hC7);
tb_top.cpu_byte_write(`ADDR_SPACE_I2CM,8'h1,8'h00);
// Core Enable
tb_top.cpu_byte_write(`ADDR_SPACE_I2CM,8'h2,8'h80);
// Writing Data
 
$display("---------- Writing Data ----------");
tb_top.cpu_byte_write(`ADDR_SPACE_I2CM,8'h3,8'h20); // Slave Addr + WR
tb_top.cpu_byte_write(`ADDR_SPACE_I2CM,8'h4,8'h90);
rdata [1] = 1'b1;
while(rdata[1]==1)
tb_top.cpu_byte_read(`ADDR_SPACE_I2CM,8'h4,rdata);
tb_top.cpu_byte_write(`ADDR_SPACE_I2CM,8'h3,8'h66);
tb_top.cpu_byte_write(`ADDR_SPACE_I2CM,8'h4,8'h10);
 
rdata [1] = 1'b1;
while(rdata[1]==1)
tb_top.cpu_byte_read(`ADDR_SPACE_I2CM,8'h4,rdata);
/* Byte1: 12 */
tb_top.cpu_byte_write(`ADDR_SPACE_I2CM,8'h3,8'h12);
tb_top.cpu_byte_write(`ADDR_SPACE_I2CM,8'h4,8'h10); // No Stop + Write
 
rdata [1] = 1'b1;
while(rdata[1]==1)
tb_top.cpu_byte_read(`ADDR_SPACE_I2CM,8'h4,rdata);
/* Byte1: 34 */
tb_top.cpu_byte_write(`ADDR_SPACE_I2CM,8'h3,8'h34);
tb_top.cpu_byte_write(`ADDR_SPACE_I2CM,8'h4,8'h10); // No Stop + Write
 
rdata [1] = 1'b1;
while(rdata[1]==1)
tb_top.cpu_byte_read(`ADDR_SPACE_I2CM,8'h4,rdata);
 
/* Byte1: 56 */
tb_top.cpu_byte_write(`ADDR_SPACE_I2CM,8'h3,8'h56);
tb_top.cpu_byte_write(`ADDR_SPACE_I2CM,8'h4,8'h10); // No Stop + Write
 
rdata [1] = 1'b1;
while(rdata[1]==1)
tb_top.cpu_byte_read(`ADDR_SPACE_I2CM,8'h4,rdata);
 
/* Byte1: 78 */
tb_top.cpu_byte_write(`ADDR_SPACE_I2CM,8'h3,8'h78);
tb_top.cpu_byte_write(`ADDR_SPACE_I2CM,8'h4,8'h50); // Stop + Write
 
rdata [1] = 1'b1;
while(rdata[1]==1)
tb_top.cpu_byte_read(`ADDR_SPACE_I2CM,8'h4,rdata);
 
//Reading Data
//Wrire Address
$display("---------- Writing Data ----------");
tb_top.cpu_byte_write(`ADDR_SPACE_I2CM,8'h3,8'h20);
tb_top.cpu_byte_write(`ADDR_SPACE_I2CM,8'h4,8'h90);
rdata [1] = 1'b1;
while(rdata[1]==1)
tb_top.cpu_byte_read(`ADDR_SPACE_I2CM,8'h4,rdata);
tb_top.cpu_byte_write(`ADDR_SPACE_I2CM,8'h3,8'h66);
tb_top.cpu_byte_write(`ADDR_SPACE_I2CM,8'h4,8'h50);
 
rdata [1] = 1'b1;
while(rdata[1]==1)
tb_top.cpu_byte_read(`ADDR_SPACE_I2CM,8'h4,rdata);
 
//Generate Read
$display("---------- Writing Data ----------");
tb_top.cpu_byte_write(`ADDR_SPACE_I2CM,8'h3,8'h21); // Slave Addr + RD
tb_top.cpu_byte_write(`ADDR_SPACE_I2CM,8'h4,8'h90);
rdata [1] = 1'b1;
while(rdata[1]==1)
tb_top.cpu_byte_read(`ADDR_SPACE_I2CM,8'h4,rdata);
 
/* BYTE-1 : 0x12 */
tb_top.cpu_byte_write(`ADDR_SPACE_I2CM,8'h4,8'h20); // RD + ACK
 
rdata [1] = 1'b1;
while(rdata[1]==1)
tb_top.cpu_byte_read(`ADDR_SPACE_I2CM,8'h4,rdata);
 
//Compare received data
tb_top.cpu_byte_read_cmp(`ADDR_SPACE_I2CM,8'h3,8'h12);
/* BYTE-2 : 0x34 */
tb_top.cpu_byte_write(`ADDR_SPACE_I2CM,8'h4,8'h20); // RD + ACK
 
rdata [1] = 1'b1;
while(rdata[1]==1)
tb_top.cpu_byte_read(`ADDR_SPACE_I2CM,8'h4,rdata);
 
//Compare received data
tb_top.cpu_byte_read_cmp(`ADDR_SPACE_I2CM,8'h3,8'h34);
 
/* BYTE-3 : 0x56 */
tb_top.cpu_byte_write(`ADDR_SPACE_I2CM,8'h4,8'h20); // RD + ACK
 
rdata [1] = 1'b1;
while(rdata[1]==1)
tb_top.cpu_byte_read(`ADDR_SPACE_I2CM,8'h4,rdata);
 
//Compare received data
tb_top.cpu_byte_read_cmp(`ADDR_SPACE_I2CM,8'h3,8'h56);
 
/* BYTE-4 : 0x78 */
tb_top.cpu_byte_write(`ADDR_SPACE_I2CM,8'h4,8'h68); // STOP + RD + NACK
 
rdata [1] = 1'b1;
while(rdata[1]==1)
tb_top.cpu_byte_read(`ADDR_SPACE_I2CM,8'h4,rdata);
 
//Compare received data
tb_top.cpu_byte_read_cmp(`ADDR_SPACE_I2CM,8'h3,8'h78);
 
repeat(100)@(posedge app_clk);
end
endtask //}
 
trunk/verif/testcase/i2cm_test1.v Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.