Thứ Năm, 18 tháng 4, 2019
No tit
module noisefter
(
clk ,
rst_n,
en ,
nfs ,
sgi ,
sgo
);
input clk ;
input rst_n;
input en ;
input [ 2:0] nfs ;
input sgi ; // input signal
output sgo ; // output signal
reg rsgo ;
reg sgi_1; // 1st state
reg sgi_2; // 2nd state
reg sgi_3; // 3rd state
reg sgi_4; // 4th state
reg sgi_5; // 5th state
reg sgi_6; // 6th state
reg sgi_7; // 7th state
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
sgi_1 <= 1'b1;
end
else if (en == 1'b1) begin
sgi_1 <= sgi;
end
else begin
sgi_1 <= sgi_1;
end
end
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
sgi_2 <= 1'b1;
end
else if (en == 1'b1) begin
sgi_2 <= sgi_1;
end
else begin
sgi_2 <= sgi_2;
end
end
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
sgi_3 <= 1'b1;
end
else if (en == 1'b1) begin
sgi_3 <= sgi_2;
end
else begin
sgi_3 <= sgi_3;
end
end
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
sgi_4 <= 1'b1;
end
else if (en == 1'b1) begin
sgi_4 <= sgi_3;
end
else begin
sgi_4 <= sgi_4;
end
end
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
sgi_5 <= 1'b1;
end
else if (en == 1'b1) begin
sgi_5 <= sgi_4;
end
else begin
sgi_5 <= sgi_5;
end
end
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
sgi_6 <= 1'b1;
end
else if (en == 1'b1) begin
sgi_6 <= sgi_5;
end
else begin
sgi_6 <= sgi_6;
end
end
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
sgi_7 <= 1'b1;
end
else if (en == 1'b1) begin
sgi_7 <= sgi_6;
end
else begin
sgi_7 <= sgi_7;
end
end
always @(sgi_1 or sgi_2 or sgi_3 or sgi_4 or sgi_5 or sgi_6 or sgi_7
or nfs or sgi) begin
case (nfs)
3'b000: begin
rsgo = sgi;
end
3'b001: begin
rsgo = (sgi == sgi_1) ? sgi : rsgo ;
end
3'b010: begin
rsgo = ((sgi & sgi_1 & sgi_2) || ~(sgi | sgi_1 | sgi_2) ) ? sgi : rsgo;
end
3'b011: begin
rsgo = ( (sgi & sgi_1 & sgi_2 & sgi_3)
|| ~(sgi | sgi_1 | sgi_2 | sgi_3) ) ? sgi : rsgo;
end
3'b100: begin
rsgo = ( (sgi & sgi_1 & sgi_2 & sgi_3 & sgi_4)
|| ~(sgi | sgi_1 | sgi_2 | sgi_3 | sgi_4) ) ? sgi : rsgo;
end
3'b101: begin
rsgo = ( (sgi & sgi_1 & sgi_2 & sgi_3 & sgi_4 & sgi_5)
|| ~(sgi | sgi_1 | sgi_2 | sgi_3 | sgi_4 | sgi_5) ) ? sgi : rsgo;
end
3'b110: begin
rsgo = ( (sgi&sgi_1&sgi_2&sgi_3&sgi_4&sgi_5&sgi_6)
|| ~(sgi|sgi_1|sgi_2|sgi_3|sgi_4|sgi_5|sgi_6) ) ? sgi : rsgo;
end
3'b111: begin
rsgo = ( (sgi & sgi_1 & sgi_2 & sgi_3 & sgi_4 & sgi_5 & sgi_6 & sgi_7)
|| ~(sgi|sgi_1|sgi_2|sgi_3|sgi_4|sgi_5|sgi_6|sgi_7)) ? sgi : rsgo;
end
endcase
end
assign sgo = rsgo;
endmodule
module bbsy
(
clk ,
rst_n,
en ,
scli ,
sdai ,
sclo ,
sdao ,
ms ,
bbsy ,
gbsy
);
parameter STRT = 2'h0; // change when start signal
parameter STOP = 2'h1; // change when stop signal
parameter SCLN = 2'h2; // change when negative of scli
parameter SCLP = 2'h3; // change when positive of scli
input clk ;
input rst_n;
input en ;
input scli ;
input sdai ;
input sclo ;
input sdao ;
input ms ;
output bbsy ; // indicate that bus is busy
output gbsy ; // indicate that this master (GIIC) is busy
reg rstop ;
reg rstart ;
reg rstopo ;
reg rstarto;
reg rbbsy ;
reg rgbsy ;
////////////////////////////////////////////////////////////////////////////////
// ===== detect sda posedge and negedge ===== //
wire sdao_pos;
wire sdao_neg;
reg sdao_dl ;
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
sdao_dl <= 1'b0;
end
else if (en == 1'b1) begin
sdao_dl <= sdao;
end
else begin
sdao_dl <= sdao_dl;
end
end
assign sdao_pos = (~sdao_dl) && sdao;
assign sdao_neg = sdao_dl && (~sdao);
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// ===== detect start, stop signal ===== //
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
rstopo <= 1'b0;
rstarto <= 1'b0;
end
else if ( (en == 1'b1) && (sclo == 1'b1) ) begin
if (sdao_pos == 1'b1) begin
rstopo <= 1'b1;
rstarto <= 1'b0;
end
else begin
rstopo <= 1'b0;
if (sdao_neg == 1'b1) begin
rstarto <= 1'b1;
end
else begin
rstarto <= 1'b0;
end
end
end
else begin
rstopo <= rstopo ;
rstarto <= rstarto;
end
end
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// ===== detect bus busy ===== //
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
rgbsy <= 1'b0;
end
else if (en == 1'b1) begin
if (rstarto == 1'b1) begin
rgbsy <= 1'b1;
end
else if (rstopo == 1'b1) begin
rgbsy <= 1'b0;
end
else begin
rgbsy <= rgbsy;
end
end
else begin
rgbsy <= rgbsy;
end
end
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// ===== detect scl posedge and negedge ===== //
wire scli_pos;
wire scli_neg;
reg scli_dl ;
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
scli_dl <= 1'b0;
end
else if (en == 1'b1) begin
scli_dl <= scli;
end
else begin
scli_dl <= scli_dl;
end
end
assign scli_pos = (~scli_dl) && scli;
assign scli_neg = scli_dl && (~scli);
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// ===== detect sda posedge and negedge ===== //
wire sdai_pos;
wire sdai_neg;
reg sdai_dl ;
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
sdai_dl <= 1'b0;
end
else if (en == 1'b1) begin
sdai_dl <= sdai;
end
else begin
sdai_dl <= sdai_dl;
end
end
assign sdai_pos = (~sdai_dl) && sdai;
assign sdai_neg = sdai_dl && (~sdai);
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// ===== detect start, stop signal ===== //
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
rstop <= 1'b0;
rstart <= 1'b0;
end
else if ( (en == 1'b1) && (scli == 1'b1) ) begin
if (sdai_pos == 1'b1) begin
rstop <= 1'b1;
rstart <= 1'b0;
end
else begin
rstop <= 1'b0;
if (sdai_neg == 1'b1) begin
rstart <= 1'b1;
end
else begin
rstart <= 1'b0;
end
end
end
else begin
rstop <= rstop ;
rstart <= rstart;
end
end
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// ===== detect bus busy ===== //
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
rbbsy <= 1'b0;
end
else if (en == 1'b1) begin
if (rstart == 1'b1) begin
rbbsy <= 1'b1;
end
else if (rstop == 1'b1) begin
rbbsy <= 1'b0;
end
else begin
rbbsy <= rbbsy;
end
end
else begin
rbbsy <= rbbsy;
end
end
////////////////////////////////////////////////////////////////////////////////
assign gbsy = rgbsy;
assign bbsy = rbbsy;
endmodule
module arbitration
(
clk ,
rst_n,
en ,
bbsy ,
gbsy ,
sda ,
msdao,
ssdao,
ms ,
st ,
ino ,
malc ,
salc ,
male ,
sale
);
input clk ; // clock
input rst_n; // reset
input en ; // enable arbitration
input bbsy ; // bus busy
input gbsy ; // master (this GIIC) busy
input sda ; // bus data wire
input msdao; // GIIC master data output
input ssdao; // GIIC slave data output
input ms ; // bit indicate master/slave
input st ; // start signal
input ino ; // bit indicate input/output
input malc ; // clear error MALE
input salc ; // clear error SALE
output male ; // Master Arbitration Lost Error
output sale ; // Slave Arbitration Lost Error
// 1. Master Arbitration Lost Error
// 1.1. start condition double issue error (start when bus is busy)
reg rmale_wisrr;
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
rmale_wisrr <= 1'b0;
end
else if (malc == 1'b1) begin
rmale_wisrr <= 1'b0;
end
else if (en == 1'b1) begin
rmale_wisrr <= (bbsy && (~gbsy) && (~rmale_wisrr)) ? st : rmale_wisrr;
end
else begin
rmale_wisrr <= rmale_wisrr;
end
end
// 1.2. sdao does not match the level on the sda line (start and transmit)
reg rmale_mmatchg;
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
rmale_mmatchg <= 1'b0;
end
else if (malc == 1'b1) begin
rmale_mmatchg <= 1'b0;
end
else if (en == 1'b1) begin
rmale_mmatchg <= (ms && gbsy && (~ino) && (~rmale_mmatchg)) ?
(msdao != sda) : rmale_mmatchg;
end
else begin
rmale_mmatchg <= rmale_mmatchg;
end
end
// 2. Slave Arbitration Lost Error
reg rsale_smatchg;
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
rsale_smatchg <= 1'b0;
end
else if (salc == 1'b1) begin
rsale_smatchg <= 1'b0;
end
else if (en == 1'b1) begin
rsale_smatchg <= ((~ms) && (~ino) && (~rsale_smatchg)) ?
(ssdao != sda) : rsale_smatchg;
end
else begin
rsale_smatchg <= rsale_smatchg;
end
end
assign male = rmale_wisrr || rmale_mmatchg;
assign sale = rsale_smatchg;
endmodule
module prescaler
(
clk ,
rst_n,
en ,
psc ,
dlk
);
input clk ;
input rst_n;
input en ;
input [3:0] psc ;
output dlk ; // div clk
reg [15:0] rpsc;
reg rdlk; // dlk = clk/(2^(psc+1)
wire [15:0] pow2; // pow2 = 2^psc
assign pow2 = 16'h01 << (psc - 4'h1);
always @(posedge clk or negedge rst_n) begin
if (rst_n == 0) begin
rpsc <= 16'h0001;
rdlk <= 1'b0 ;
end
else if ((en == 1'b1) && (psc != 4'h0) ) begin
if (rpsc >= pow2) begin
rpsc <= 16'h0001;
rdlk <= ~rdlk;
end
else begin
rpsc <= rpsc + 16'h0001;
rdlk <= rdlk;
end
end
else begin
rpsc <= 16'h0001;
rdlk <= 1'b0 ;
end
end
assign dlk = rdlk;
endmodule
module bitrate
(
clk ,
rst_n,
en ,
dlk ,
cnth ,
cntl ,
brh ,
brl ,
limh ,
liml
);
input clk ;
input rst_n;
input en ;
input dlk ;
input cnth ;
input cntl ;
input [7:0] brh ;
input [7:0] brl ;
output limh ;
output liml ;
reg [7:0] rbrh ;
reg [7:0] rbrl ;
reg rlimh;
reg rliml;
reg rdlk_dl; // rdlk_dl = DFF(rdlk)
wire rdlk_pos; // detect posedge rdlk
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
rdlk_dl <= 1'b0;
end
else if (en == 1'b1) begin
rdlk_dl <= dlk;
end
else begin
rdlk_dl <= 1'b0;
end
end
assign rdlk_pos = (~rdlk_dl) && dlk;
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
rbrh <= 8'h01;
rlimh <= 1'b0;
end
else if ( (en == 1'b1) && (cnth == 1'b1) && (rdlk_pos == 1'b1) ) begin
if (rbrh >= brh) begin
rbrh <= 8'h01;
rlimh <= 1'b1;
end
else begin
rbrh <= rbrh + 8'h01;
rlimh <= 1'b0;
end
end
else begin
rbrh <= rbrh;
rlimh <= 1'b0;
end
end
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
rbrl <= 8'h01;
rliml <= 1'b0;
end
else if ( (en == 1'b1) && (cntl == 1'b1) && (rdlk_pos == 1'b1) ) begin
if (rbrl >= brl) begin
rbrl <= 8'h01;
rliml <= 1'b1;
end
else begin
rbrl <= rbrl + 8'h01;
rliml <= 1'b0;
end
end
else begin
rbrl <= rbrl;
rliml <= 1'b0;
end
end
assign limh = rlimh;
assign liml = rliml;
endmodule
module timeout
(
clk ,
rst_n,
en ,
scli ,
dlk ,
tmo ,
tmoc ,
limt ,
cnt
);
parameter IDLE = 2'h0; // change when start signal
parameter SCLN = 2'h1; // change when negative of scli
parameter SCLP = 2'h2; // change when positive of scli
parameter OTHR = 2'h3; // other state
input clk ;
input rst_n;
input en ;
input scli ;
input dlk ;
input [15:0] tmo ;
input tmoc ;
output limt ;
output [15:0] cnt ;
reg rlimt;
reg [15:0] rcnt ;
reg [ 1:0] state;
reg [ 1:0] nxt_state;
reg rcount;
////////////////////////////////////////////////////////////////////////////////
// ===== detect scl posedge and negedge ===== //
wire scli_pos;
wire scli_neg;
reg scli_dl ;
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
scli_dl <= 1'b0;
end
else if (en == 1'b1) begin
scli_dl <= scli;
end
else begin
scli_dl <= scli_dl;
end
end
assign scli_pos = (~scli_dl) && scli;
assign scli_neg = scli_dl && (~scli);
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// ===== detect posedge rdlk ===== //
reg rdlk_dl ; // rdlk_dl = DFF(rdlk)
wire dlk_pos; // detect posedge rdlk
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
rdlk_dl <= 1'b0;
end
else if (en == 1'b1) begin
rdlk_dl <= dlk;
end
else begin
rdlk_dl <= rdlk_dl;
end
end
assign dlk_pos = (~rdlk_dl) && dlk;
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// ===== output limit of counter -> time out ===== //
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
rlimt <= 1'b0;
end
else if (en == 1'b1) begin
if (tmoc == 1'b1) begin
rlimt <= 1'b0;
end
else begin
rlimt <= (rcnt == tmo) ? 1'b1 : rlimt;
end
end
else begin
rlimt <= 1'b0;
end
end
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// ===== counter with time input ===== //
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
rcnt <= 16'h0000;
end
else if ( (en == 1'b1) && (rcount == 1'b1) && (rlimt == 1'b0) ) begin
rcnt <= (dlk_pos == 1'b1) ? rcnt + 16'h0001 : rcnt;
end
else begin
rcnt <= 16'h0000;
end
end
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// ===== FSM time out ===== //
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
state <= IDLE;
end
else if (en == 1'b1) begin
state <= nxt_state;
end
end
always @(state or scli_pos or scli_neg) begin
case (state)
IDLE: begin
if (scli_pos == 1'b1) begin
nxt_state = SCLP;
rcount = 1'b0;
end
else if (scli_neg == 1'b1) begin
nxt_state = SCLN;
rcount = 1'b0;
end
else begin
nxt_state = IDLE;
rcount = 1'b0;
end
end
SCLP: begin
if (scli_neg == 1'b1) begin
nxt_state = SCLN;
rcount = 1'b0;
end
else begin
nxt_state = SCLP;
rcount = 1'b1;
end
end
SCLN: begin
if (scli_pos == 1'b1) begin
nxt_state = SCLP;
rcount = 1'b0;
end
else begin
nxt_state = SCLN;
rcount = 1'b1;
end
end
OTHR: begin
nxt_state = IDLE;
rcount = 1'b0;
end
endcase
end
////////////////////////////////////////////////////////////////////////////////
assign limt = rlimt;
assign cnt = rcnt ;
endmodule
module mstart
(
clk ,
rst_n ,
en ,
st ,
dlk ,
brh ,
cur_scl, // current scl signal
cur_sda, // current sda signal
sclo ,
sdao ,
bsy ,
dne
);
parameter IDLE = 3'd0;
parameter STRT1 = 3'd1;
parameter STRT2 = 3'd2;
parameter STRT3 = 3'd3;
parameter STRT4 = 3'd4;
parameter STRT5 = 3'd5;
input clk ;
input rst_n ;
input en ;
input st ;
input dlk ;
input [ 7:0] brh ;
input cur_scl;
input cur_sda;
output sclo ;
output sdao ;
output bsy ;
output dne ;
reg rsclo ;
reg rsdao ;
reg rbsy ;
reg rdne ;
////////////////////////////////////////////////////////////////////////////////
// ===== detect dck posedge ===== //
wire dlk_pos;
reg dlk_dl ;
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
dlk_dl <= 1'b0;
end
else if (en == 1'b1) begin
dlk_dl <= dlk;
end
else begin
dlk_dl <= dlk_dl;
end
end
assign dlk_pos = (~dlk_dl) && dlk;
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// ===== start time ===== //
reg [ 7:0] stime;
reg stlim; // indicate stime = brh
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
stime <= 8'h00;
stlim <= 1'b0;
end
else if ((en == 1'b1) && (dlk_pos == 1'b1) ) begin
if (stime >= brh) begin
stime <= 8'h00;
stlim <= 1'b1;
end
else begin
stime <= stime + 8'h01;
stlim <= 1'b0;
end
end
else begin
stime <= stime;
stlim <= 1'b0;
end
end
////////////////////////////////////////////////////////////////////////////////
// scl: #00110
// sda: ##1100
reg [2:0] state;
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
state <= IDLE;
rsclo <= cur_scl;
rsdao <= cur_sda;
rbsy <= 1'b0;
rdne <= 1'b0;
end
else if (en == 1'b1) begin
case (state)
IDLE : begin
if (st == 1'b1) begin
state <= STRT1;
end
else begin
state <= IDLE ;
end
rsclo <= cur_scl;
rsdao <= cur_sda;
rbsy <= 1'b0;
rdne <= 1'b0;
end
STRT1: begin
if (stlim == 1'b1) begin
state <= STRT2;
end
else begin
state <= STRT1;
end
rsclo <= 1'b0;
rsdao <= rsdao;
rbsy <= 1'b1;
rdne <= 1'b0;
end
STRT2: begin
if (stlim == 1'b1) begin
state <= STRT3;
end
else begin
state <= STRT2;
end
rsclo <= 1'b0;
rsdao <= 1'b1;
rbsy <= 1'b1;
rdne <= 1'b0;
end
STRT3: begin
if (stlim == 1'b1) begin
state <= STRT4;
end
else begin
state <= STRT3;
end
rsclo <= 1'b1;
rsdao <= 1'b1;
rbsy <= 1'b1;
rdne <= 1'b0;
end
STRT4: begin
if (stlim == 1'b1) begin
state <= STRT5;
end
else begin
state <= STRT4;
end
rsclo <= 1'b1;
rsdao <= 1'b0;
rbsy <= 1'b1;
rdne <= 1'b0;
end
STRT5: begin
if (stlim == 1'b1) begin
state <= IDLE;
rdne <= 1'b1;
end
else begin
state <= STRT5;
rdne <= 1'b0;
end
rsclo <= 1'b0;
rsdao <= 1'b0;
rbsy <= 1'b1;
end
endcase
end
else begin
state <= IDLE;
rsclo <= cur_scl;
rsdao <= cur_sda;
rbsy <= 1'b0;
rdne <= 1'b0;
end
end
assign sclo = rsclo;
assign sdao = rsdao;
assign bsy = rbsy ;
assign dne = rdne ;
endmodule
module mstop
(
clk ,
rst_n ,
en ,
sp ,
dlk ,
brh ,
cur_scl,
cur_sda,
sclo ,
sdao ,
bsy ,
dne
);
parameter IDLE = 3'd0;
parameter STOP1 = 3'd1;
parameter STOP2 = 3'd2;
parameter STOP3 = 3'd3;
parameter STOP4 = 3'd4;
parameter STOP5 = 3'd5;
parameter STOP6 = 3'd6;
input clk ;
input rst_n ;
input en ;
input sp ;
input dlk ;
input [ 7:0] brh ;
input cur_scl;
input cur_sda;
output sclo ;
output sdao ;
output bsy ;
output dne ;
reg rsclo ;
reg rsdao ;
reg rbsy ;
reg rdne ;
////////////////////////////////////////////////////////////////////////////////
// ===== detect dck posedge ===== //
wire dlk_pos;
reg dlk_dl ;
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
dlk_dl <= 1'b0;
end
else if (en == 1'b1) begin
dlk_dl <= dlk;
end
else begin
dlk_dl <= dlk_dl;
end
end
assign dlk_pos = (~dlk_dl) && dlk;
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// ===== stop time ===== //
reg [ 7:0] stome; // counter stop time
reg stlom; // indicate stome = brh
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
stome <= 8'h00;
stlom <= 1'b0;
end
else if ((en == 1'b1) && (dlk_pos == 1'b1) ) begin
if (stome >= brh) begin
stome <= 8'h00;
stlom <= 1'b1;
end
else begin
stome <= stome + 8'h01;
stlom <= 1'b0;
end
end
else begin
stome <= stome;
stlom <= 1'b0;
end
end
////////////////////////////////////////////////////////////////////////////////
// scl: #00111
// sda: ##0011
reg [2:0] state ;
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
state <= IDLE;
rsclo <= rsclo;
rsdao <= rsdao;
rbsy <= 1'b0 ;
rdne <= 1'b0 ;
end
else if (en == 1'b1) begin
case (state)
IDLE : begin
if (sp == 1'b1) begin
state <= STOP1;
end
else begin
state <= IDLE ;
end
rsclo <= cur_scl;
rsdao <= cur_sda;
rbsy <= 1'b0;
rdne <= 1'b0;
end
STOP1: begin
if (stlom == 1'b1) begin
state <= STOP2;
end
else begin
state <= STOP1;
end
rsclo <= 1'b0;
rsdao <= rsdao;
rbsy <= 1'b1;
rdne <= 1'b0;
end
STOP2: begin
if (stlom == 1'b1) begin
state <= STOP3;
end
else begin
state <= STOP2;
end
rsclo <= 1'b0;
rsdao <= 1'b0;
rbsy <= 1'b1;
rdne <= 1'b0;
end
STOP3: begin
if (stlom == 1'b1) begin
state <= STOP4;
end
else begin
state <= STOP3;
end
rsclo <= 1'b1;
rsdao <= 1'b0;
rbsy <= 1'b1;
rdne <= 1'b0;
end
STOP4: begin
if (stlom == 1'b1) begin
state <= STOP5;
end
else begin
state <= STOP4;
end
rsclo <= 1'b1;
rsdao <= 1'b1;
rbsy <= 1'b1;
rdne <= 1'b0;
end
STOP5: begin
if (stlom == 1'b1) begin
state <= STOP6;
end
else begin
state <= STOP5;
end
rsclo <= 1'b1;
rsdao <= 1'b1;
rbsy <= 1'b1;
rdne <= 1'b0;
end
STOP6: begin
if (stlom == 1'b1) begin
state <= IDLE;
end
else begin
state <= STOP6;
end
rsclo <= 1'b1;
rsdao <= 1'b1;
rbsy <= 1'b1;
rdne <= 1'b1;
end
default: begin
state <= IDLE;
rsclo <= rsclo;
rsdao <= rsdao;
rbsy <= rbsy ;
rdne <= rdne ;
end
endcase
end
else begin
state <= IDLE;
rsclo <= rsclo;
rsdao <= rsdao;
rbsy <= 1'b0 ;
rdne <= 1'b0 ;
end
end
assign sclo = rsclo;
assign sdao = rsdao;
assign bsy = rbsy ;
assign dne = rdne ;
endmodule
module fifo
(
clk ,
rst_n,
en ,
rd ,
clrq ,
clre ,
tkey ,
data ,
tdat ,
err ,
ffcr
);
parameter QUEUE_WIDTH = 15;
input clk ;
input rst_n;
input en ;
input rd ;
input clrq ; // clear queue
input [ 2:0] clre ; // clear error after master in IDLE state to avoid rick
input [23:0] tkey ;
input [ 7:0] data ;
output [ 7:0] tdat ;
output [ 2:0] err ;
output [ 3:0] ffcr ;
reg [ 7:0] rtdat ;
reg rfull ;
reg rempty;
reg [ 7:0] i ;
reg [ 7:0] pnter ;
reg [ 7:0] fifo[QUEUE_WIDTH:0];
wire wrte;
assign wrte = (tkey == 24'hC0FFEE) ? 1'b1 : 1'b0;
////////////////////////////////////////////////////////////////////////////////
wire read ;
wire rd_neg;
reg rd_dl;
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
rd_dl <= 1'b0;
end
else if (en == 1'b1) begin
rd_dl <= rd;
end
else begin
rd_dl <= rd_dl;
end
end
assign read = (~rd_dl) && rd;
assign rd_neg = rd_dl && (~rd);
////////////////////////////////////////////////////////////////////////////////
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
rfull <= 1'b0 ;
rempty <= 1'b0 ;
pnter <= 8'h00;
fifo[QUEUE_WIDTH] <= 8'h00;
for (i = 0; i < QUEUE_WIDTH; i = i + 1) begin
fifo[i] <= 8'h00;
end
end
else if (clrq == 1'b1) begin
rfull <= 1'b0 ;
rempty <= 1'b0 ;
pnter <= 8'h00;
fifo[QUEUE_WIDTH] <= 8'h00;
for (i = 0; i < QUEUE_WIDTH; i = i + 1) begin
fifo[i] <= 8'h00;
end
end
else if (clre[2] != 1'b0) begin
rfull <= 1'b0 ;
rempty <= rempty;
pnter <= pnter ;
fifo[QUEUE_WIDTH] <= 8'h00;
for (i = 0; i < QUEUE_WIDTH; i = i + 1) begin
fifo[i] <= fifo[i];
end
end
else if (en == 1'b1) begin
rfull <= ((pnter == QUEUE_WIDTH) && ((tkey == 24'hC0FFEE))) ? 1'b1 : rfull;
rempty <= ((pnter == 8'h00) && ((read == 1'b1))) ?
1'b1 : (rempty && (pnter == 8'h00));
fifo[QUEUE_WIDTH] <= 8'h00;
case ({rd_neg,wrte})
2'b00: begin
pnter <= pnter;
for (i = 0; i < QUEUE_WIDTH; i = i + 1) begin
fifo[i] <= fifo[i];
end
end
2'b01: begin
pnter <= (pnter >= QUEUE_WIDTH) ? QUEUE_WIDTH : (pnter + 8'h01);
for (i = 0; i < QUEUE_WIDTH; i = i + 1) begin
if (i == pnter) begin
fifo[i] <= (pnter >= QUEUE_WIDTH) ? fifo[i] : data;
end
else begin
fifo[i] <= fifo[i];
end
end
end
2'b10: begin
pnter <= (pnter == 8'h00) ? 8'h00 : (pnter - 8'h01);
for (i = 0; i < QUEUE_WIDTH; i = i + 1) begin
fifo[i] <= fifo[i+1];
end
end
2'b11: begin
pnter <= pnter;
for (i = 0; i < QUEUE_WIDTH; i = i + 1) begin
if (i == (pnter - 8'h01)) begin
fifo[i] <= data;
end
else begin
fifo[i] <= fifo[i+1];
end
end
end
endcase
end
else begin
rfull <= rfull ;
rempty <= rempty;
pnter <= pnter ;
fifo[QUEUE_WIDTH] <= 8'h00;
for (i = 0; i < QUEUE_WIDTH; i = i + 1) begin
fifo[i] <= fifo[i];
end
end
end
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
rtdat <= 8'h00;
end
else if (en == 1'b1) begin
rtdat <= (read == 1'b1) ? fifo[0] : rtdat;
end
else begin
rtdat <= rtdat ;
end
end
assign tdat = rtdat;
assign err = {rfull,rempty,1'b0};
assign ffcr = pnter;
endmodule
module lifo
(
clk ,
rst_n,
en ,
wr ,
addr ,
clrq ,
data ,
rdat ,
lfcr
);
parameter QUEUE_WIDTH = 15;
input clk ;
input rst_n;
input en ;
input wr ;
input [ 3:0] addr ;
input clrq ; // clear queue
input [ 7:0] data ;
output [ 7:0] rdat ;
output [ 3:0] lfcr ;
reg [ 7:0] rrdat;
reg [ 7:0] i ;
reg [ 7:0] pnter;
reg [ 7:0] lifo[QUEUE_WIDTH:0];
////////////////////////////////////////////////////////////////////////////////
wire write ;
reg wr_dl ;
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
wr_dl <= 1'b0;
end
else if (en == 1'b1) begin
wr_dl <= wr;
end
else begin
wr_dl <= wr_dl;
end
end
assign write = (~wr_dl) && wr;
////////////////////////////////////////////////////////////////////////////////
// write data to lifo
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
pnter <= 8'h00;
for (i = 0; i < QUEUE_WIDTH; i = i + 1) begin
lifo[i] <= 8'h00;
end
end
else if (clrq == 1'b1) begin
pnter <= 8'h00;
for (i = 0; i < QUEUE_WIDTH; i = i + 1) begin
lifo[i] <= 8'h00;
end
end
else if ((en == 1'b1) && (write == 1'b1) ) begin
pnter <= (pnter == QUEUE_WIDTH) ? pnter : (pnter + 8'h01);
lifo[0] <= data;
for (i = 1; i < QUEUE_WIDTH; i = i + 1) begin
lifo[i] <= lifo[i - 1];
end
end
else begin
pnter <= pnter;
for (i = 0; i < QUEUE_WIDTH; i = i + 1) begin
lifo[i] <= lifo[i];
end
end
end
assign rdat = lifo[addr];
assign lfcr = pnter;
endmodule
module mtransmit
(
clk ,
rst_n,
en ,
tr ,
sdai ,
tdat ,
rmit ,
ackc ,
limh ,
liml ,
bsy ,
sclo ,
sdao ,
bc ,
acko ,
shf ,
ino , // input and output
rmiti,
acke ,
cnth ,
cntl ,
dne
);
parameter IDLE = 3'd0;
parameter TRAN1 = 3'd1;
parameter TRAN2 = 3'd2;
parameter TRAN3 = 3'd3;
parameter WACK1 = 3'd4;
parameter WACK2 = 3'd5;
parameter WACK3 = 3'd6;
input clk ;
input rst_n;
input en ;
input tr ;
input sdai ;
input [ 7:0] tdat ;
input [ 3:0] rmit ;
input ackc ;
input limh ;
input liml ;
output bsy ; // 0: free, 1: transfering
output sclo ;
output sdao ;
output [ 3:0] bc ;
output acko ;
output [ 7:0] shf ;
output ino ;
output rmiti;
output acke ; // 0: no error ack, 1: error ack
output cnth ;
output cntl ;
output dne ;
reg rbsy ; // 0: free, 1: transfering
reg rsclo ;
reg rsdao ;
reg [ 3:0] rbc ;
reg racko ;
reg rrmiti;
reg racke ;
reg rcnth ;
reg rcntl ;
reg rino ;
reg rdne ;
reg [2:0] state;
reg [3:0] rrmit;
reg [7:0] rshf ;
reg [7:0] resf ; // back up rshf
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
state <= IDLE ;
rbsy <= 1'b0 ;
rsclo <= 1'b0 ;
rsdao <= 1'b0 ;
rrmit <= rmit ;
rshf <= 8'h00;
resf <= 8'h00;
rbc <= 4'h0 ;
racko <= 1'b1 ;
rrmiti <= 1'b0 ;
racke <= 1'b0 ;
rcnth <= 1'b0 ;
rcntl <= 1'b0 ;
rdne <= 1'b0 ;
rino <= 1'b0 ;
end
else if (en == 1'b1) begin
case (state)
IDLE : begin
if ((tr == 1'b1) && (en == 1'b1)) begin
state <= TRAN1;
end
else begin
state <= IDLE ;
end
rbsy <= 1'b0;
rsclo <= 1'b0;
rsdao <= 1'b0;
rrmit <= rmit;
rshf <= tdat;
resf <= tdat;
rbc <= 4'h0;
racko <= 1'b1;
rrmiti <= 1'b0;
racke <= (ackc == 1'b1) ? 1'b0 : racke;
rcnth <= 1'b0;
rcntl <= 1'b0;
rino <= 1'b0;
rdne <= 1'b0;
end
TRAN1: begin
if (liml == 1'b1) begin
state <= TRAN2;
rcntl <= 1'b0;
end
else begin
state <= TRAN1;
rcntl <= 1'b1;
end
rcnth <= 1'b0 ;
rbsy <= 1'b1 ;
rsclo <= 1'b0 ;
rsdao <= rshf[7];
rrmit <= rrmit ;
rshf <= rshf ;
resf <= resf ;
rbc <= rbc ;
racko <= 1'b1 ;
rrmiti <= 1'b0 ;
racke <= (ackc == 1'b1) ? 1'b0 : racke;
rino <= 1'b0 ;
rdne <= 1'b0 ;
end
TRAN2: begin
if (limh == 1'b1) begin
state <= TRAN3;
rcnth <= 1'b0;
end
else begin
state <= TRAN2;
rcnth <= 1'b1;
end
rcntl <= 1'b0 ;
rbsy <= 1'b1 ;
rsclo <= 1'b1 ;
rsdao <= rsdao;
rrmit <= rrmit;
rshf <= rshf ;
resf <= resf ;
rbc <= rbc ;
racko <= 1'b1 ;
rrmiti <= 1'b0 ;
racke <= (ackc == 1'b1) ? 1'b0 : racke;
rino <= 1'b0 ;
rdne <= 1'b0 ;
end
TRAN3: begin
if (liml == 1'b1) begin
if (rbc == 4'h7) begin
state <= WACK1;
end
else begin
state <= TRAN1;
end
rcntl <= 1'b0;
rbc <= rbc + 4'h1;
rshf <= rshf << 1'b1;
end
else begin
state <= TRAN3;
rcntl <= 1'b1;
rbc <= rbc;
rshf <= rshf;
end
rcnth <= 1'b0 ;
rbsy <= 1'b1 ;
rsclo <= 1'b0 ;
rsdao <= rsdao;
rrmit <= rrmit;
resf <= resf ;
racko <= 1'b1 ;
rrmiti <= 1'b0 ;
racke <= (ackc == 1'b1) ? 1'b0 : racke;
rino <= (rbc == 4'h7) ? 1'b1 : 1'b0;
rdne <= 1'b0 ;
end
WACK1: begin
if (liml == 1'b1) begin
state <= WACK2;
rcntl <= 1'b0 ;
end
else begin
state <= WACK1;
rcntl <= 1'b1;
end
rcnth <= 1'b0 ;
rbsy <= 1'b1 ;
rsclo <= 1'b0 ;
rsdao <= rsdao;
rrmit <= rrmit;
rshf <= rshf ;
resf <= resf ;
rbc <= rbc ;
racko <= 1'b1 ;
rrmiti <= 1'b0 ;
racke <= (ackc == 1'b1) ? 1'b0 : racke;
rino <= 1'b1 ;
rdne <= 1'b0 ;
end
WACK2: begin
if (limh == 1'b1) begin
state <= WACK3;
rcnth <= 1'b0;
rdne <= 1'b1;
end
else begin
state <= WACK2;
rcnth <= 1'b1;
rdne <= 1'b0;
end
rcntl <= 1'b0 ;
rbsy <= 1'b1 ;
rsclo <= 1'b1 ;
rsdao <= rsdao;
rrmit <= rrmit;
rshf <= rshf ;
resf <= resf ;
rbc <= rbc ;
racko <= sdai ;
rrmiti <= 1'b0 ;
rino <= 1'b1 ;
racke <= (ackc == 1'b1) ? 1'b0 : racke;
end
WACK3: begin
if (racko == 1'b0) begin // transfer completed
if (liml == 1'b1) begin
state <= TRAN1;
rcntl <= 1'b0;
rbc <= 4'h0;
rbsy <= 1'b1;
end
else begin
state <= WACK3;
rcntl <= 1'b1;
rbc <= rbc ;
rbsy <= 1'b1;
end
rdne <= rdne;
rrmit <= rmit;
rshf <= tdat;
resf <= tdat;
rrmiti <= 1'b0;
racke <= (ackc == 1'b1) ? 1'b0 : racke;
end
else begin // nack
if (rrmit == 4'h0) begin // not re-transfer
if (liml == 1'b1) begin
state <= IDLE;
rcntl <= 1'b0;
rdne <= 1'b1;
rbc <= 4'h0;
rbsy <= 1'b1;
racke <= (ackc == 1'b1) ? 1'b0 : 1'b1;
end
else begin
state <= WACK3;
rcntl <= 1'b1;
rdne <= rdne;
rbc <= rbc ;
rbsy <= 1'b1;
racke <= (ackc == 1'b1) ? 1'b0 : racke;
end
rrmit <= rrmit;
rshf <= rshf;
resf <= resf;
rrmiti <= 1'b0;
end
else begin // re-transfer
if (liml == 1'b1) begin
state <= TRAN1;
rcntl <= 1'b0;
rdne <= 1'b1;
rbc <= 4'h0;
rbsy <= 1'b1;
rrmit <= rrmit - 4'h1;
end
else begin
state <= WACK3;
rcntl <= 1'b1;
rdne <= rdne;
rbc <= rbc ;
rbsy <= 1'b1;
rrmit <= rrmit;
end
rshf <= resf;
resf <= resf;
rrmiti <= 1'b1;
racke <= (ackc == 1'b1) ? 1'b0 : racke;
end
end
rcnth <= 1'b0 ;
rsclo <= 1'b0 ;
rsdao <= rsdao;
racko <= racko;
rino <= 1'b1 ;
end
endcase
end
else begin
state <= IDLE ;
rbsy <= 1'b0 ;
rsclo <= 1'b0 ;
rsdao <= 1'b0 ;
rrmit <= rmit ;
rshf <= 8'h00;
resf <= 8'h00;
rbc <= 4'h0 ;
racko <= 1'b1 ;
rrmiti <= 1'b0 ;
racke <= (ackc == 1'b1) ? 1'b0 : racke;
rcnth <= 1'b0 ;
rcntl <= 1'b0 ;
rdne <= 1'b0 ;
rino <= 1'b0 ;
end
end
assign bsy = rbsy ;
assign sclo = rsclo ;
assign sdao = rsdao ;
assign bc = rbc ;
assign acko = racko ;
assign shf = rshf ;
assign ino = rino ;
assign rmiti = rrmiti;
assign acke = racke ;
assign cnth = rcnth ;
assign cntl = rcntl ;
assign dne = rdne ;
endmodule
module mreceive
(
clk ,
rst_n,
en ,
re ,
acki ,
sdai ,
limh ,
liml ,
bsy ,
sclo ,
sdao ,
bc ,
rdat ,
shf ,
ino ,
cnth ,
cntl ,
lfwr ,
dne
);
parameter IDLE = 3'd0;
parameter RECV1 = 3'd1;
parameter RECV2 = 3'd2;
parameter RECV3 = 3'd3;
parameter XACK1 = 3'd4;
parameter XACK2 = 3'd5;
parameter XACK3 = 3'd6;
input clk ;
input rst_n;
input en ;
input re ;
input acki ;
input sdai ;
input limh ;
input liml ;
output bsy ; // 0: free, 1: transfering
output sclo ;
output sdao ;
output [ 3:0] bc ;
output [ 7:0] rdat ;
output [ 7:0] shf ;
output ino ;
output cnth ;
output cntl ;
output lfwr ;
output dne ;
reg rbsy ; // 0: free, 1: transfering
reg rsclo;
reg rsdao;
reg [ 3:0] rbc ;
reg [ 7:0] rrdat;
reg rcnth;
reg rcntl;
reg rino ;
reg rlfwr;
reg rdne ;
reg [2:0] state;
reg [7:0] rshf;
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
state <= IDLE ;
rbsy <= 1'b0;
rsclo <= 1'b0;
rsdao <= 1'b1;
rshf <= 8'h00;
rbc <= 4'h0;
rrdat <= 8'h00;
rcnth <= 1'b0;
rcntl <= 1'b0;
rino <= 1'b1;
rlfwr <= 1'b0;
rdne <= 1'b0;
end
else if (en == 1'b1) begin
case (state)
IDLE : begin
if (re == 1'b1) begin
state <= RECV1;
end
else begin
state <= IDLE ;
end
rbsy <= 1'b0;
rsclo <= 1'b0;
rsdao <= 1'b1;
rshf <= rshf;
rbc <= 4'h0;
rrdat <= rrdat;
rcnth <= 1'b0;
rcntl <= 1'b0;
rino <= 1'b1;
rlfwr <= 1'b0;
rdne <= 1'b0;
end
RECV1: begin
if (liml == 1'b1) begin
state <= RECV2;
rcntl <= 1'b0;
end
else begin
state <= RECV1;
rcntl <= 1'b1;
end
rcnth <= 1'b0;
rbsy <= 1'b1;
rsclo <= 1'b0;
rsdao <= 1'b1;
rshf <= rshf;
rbc <= rbc;
rrdat <= rrdat;
rino <= 1'b1;
rlfwr <= 1'b0;
rdne <= 1'b0;
end
RECV2: begin
if (limh == 1'b1) begin
state <= RECV3;
rcnth <= 1'b0;
end
else begin
state <= RECV2;
rcnth <= 1'b1;
end
rshf <= (rsclo == 1'b0) ? {rshf[6:0],sdai} : rshf;
rbc <= (rsclo == 1'b0) ? rbc + 4'h1 : rbc;
rcntl <= 1'b0;
rbsy <= 1'b1;
rsclo <= 1'b1;
rsdao <= 1'b1;
rrdat <= rrdat;
rino <= 1'b1;
rlfwr <= 1'b0;
rdne <= 1'b0;
end
RECV3: begin
if (liml == 1'b1) begin
rcntl <= 1'b0;
if (rbc == 4'h8) begin
state <= XACK1;
end
else begin
state <= RECV1;
end
end
else begin
state <= RECV3;
rcntl <= 1'b1;
end
rino <= 1'b1;
rbc <= rbc;
rcnth <= 1'b0;
rbsy <= 1'b1;
rsclo <= 1'b0;
rsdao <= 1'b1;
rshf <= rshf;
rrdat <= rrdat;
rlfwr <= 1'b0;
rdne <= 1'b0 ;
end
XACK1: begin
if (liml == 1'b1) begin
state <= XACK2;
rcntl <= 1'b0;
end
else begin
state <= XACK1;
rcntl <= 1'b1;
end
rcnth <= 1'b0;
rbsy <= 1'b1;
rsclo <= 1'b0;
rsdao <= acki;
rshf <= rshf;
rbc <= rbc;
rrdat <= rrdat;
rino <= 1'b0;
rlfwr <= 1'b0;
rdne <= 1'b0;
end
XACK2: begin
if (limh == 1'b1) begin
state <= XACK3;
rcnth <= 1'b0;
rlfwr <= 1'b1;
end
else begin
state <= XACK2;
rcnth <= 1'b1;
rlfwr <= 1'b0;
end
rcntl <= 1'b0;
rbsy <= 1'b1;
rsclo <= 1'b1;
rsdao <= rsdao;
rshf <= rshf;
rbc <= rbc;
rrdat <= rshf;
rino <= 1'b0;
rdne <= 1'b0;
end
XACK3: begin
if (liml == 1'b1) begin
rcntl <= 1'b0;
if (acki == 1'b0) begin
state <= RECV1;
end
else if (acki == 1'b1) begin
state <= IDLE;
end
else begin
state <= XACK3;
end
end
else begin
state <= XACK3;
rcntl <= 1'b1;
end
rcnth <= 1'b0;
rrdat <= rrdat;
rbsy <= 1'b1;
rsclo <= 1'b0;
rsdao <= rsdao;
rshf <= rshf;
rbc <= 4'h0;
rino <= 1'b0;
rlfwr <= rlfwr;
rdne <= 1'b1;
end
endcase
end
else begin
state <= IDLE ;
rbsy <= 1'b0;
rsclo <= 1'b0;
rsdao <= 1'b1;
rshf <= 8'h00;
rbc <= 4'h0;
rrdat <= rrdat;
rcnth <= 1'b0;
rcntl <= 1'b0;
rino <= 1'b1;
rlfwr <= rlfwr;
rdne <= 1'b0;
end
end
assign bsy = rbsy ;
assign sclo = rsclo;
assign sdao = rsdao;
assign bc = rbc ;
assign rdat = rrdat;
assign shf = rshf ;
assign ino = rino ;
assign cnth = rcnth;
assign cntl = rcntl;
assign lfwr = rlfwr;
assign dne = rdne ;
endmodule
module sdetect
(
clk ,
rst_n,
en ,
scli ,
sdai ,
stop ,
start,
reset
);
parameter STRT = 2'h0; // change when start signal
parameter STOP = 2'h1; // change when stop signal
parameter SCLN = 2'h2; // change when negative of scli
parameter SCLP = 2'h3; // change when positive of scli
input clk ;
input rst_n;
input en ;
input scli ;
input sdai ;
output stop ;
output start;
output reset;
reg rstop ;
reg rstart;
reg rreset;
////////////////////////////////////////////////////////////////////////////////
// ===== detect scl posedge and negedge ===== //
reg scli_01;
reg scli_02;
reg scli_03;
reg scli_04;
reg scli_05;
reg scli_06;
reg scli_07;
reg scli_08;
reg scli_09;
reg scli_10;
reg sdai_01;
reg sdai_02;
reg sdai_03;
reg sdai_04;
reg sdai_05;
reg sdai_06;
reg sdai_07;
reg sdai_08;
reg sdai_09;
reg sdai_10;
// D-FF to avoid the noise
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
scli_01 <= 1'b0;
scli_02 <= 1'b0;
scli_03 <= 1'b0;
scli_04 <= 1'b0;
scli_05 <= 1'b0;
scli_06 <= 1'b0;
scli_07 <= 1'b0;
scli_08 <= 1'b0;
scli_09 <= 1'b0;
scli_10 <= 1'b0;
end
else begin
scli_01 <= scli;
scli_02 <= scli_01;
scli_03 <= scli_02;
scli_04 <= scli_03;
scli_05 <= scli_04;
scli_06 <= scli_05;
scli_07 <= scli_06;
scli_08 <= scli_07;
scli_09 <= scli_08;
scli_10 <= scli_09;
end
end
// D-FF to avoid the noise
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
sdai_01 <= 1'b0;
sdai_02 <= 1'b0;
sdai_03 <= 1'b0;
sdai_04 <= 1'b0;
sdai_05 <= 1'b0;
sdai_06 <= 1'b0;
sdai_07 <= 1'b0;
sdai_08 <= 1'b0;
sdai_09 <= 1'b0;
sdai_10 <= 1'b0;
end
else begin
sdai_01 <= sdai;
sdai_02 <= sdai_01;
sdai_03 <= sdai_02;
sdai_04 <= sdai_03;
sdai_05 <= sdai_04;
sdai_06 <= sdai_05;
sdai_07 <= sdai_06;
sdai_08 <= sdai_07;
sdai_09 <= sdai_08;
sdai_10 <= sdai_09;
end
end
reg scli_dl ;
wire scli_pos;
wire scli_neg;
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
scli_dl <= 1'b0;
end
else if (en == 1'b1) begin
scli_dl <= scli_10;
end
else begin
scli_dl <= scli_dl;
end
end
assign scli_pos = (~scli_dl) && scli_10;
assign scli_neg = scli_dl && (~scli_10);
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// ===== detect sda posedge and negedge ===== //
wire sdai_pos;
wire sdai_neg;
reg sdai_dl ;
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
sdai_dl <= 1'b0;
end
else if (en == 1'b1) begin
sdai_dl <= sdai_10;
end
else begin
sdai_dl <= sdai_dl;
end
end
assign sdai_pos = (~sdai_dl) && sdai_10;
assign sdai_neg = sdai_dl && (~sdai_10);
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// ===== detect reset signal ===== //
reg [1:0] state;
reg [1:0] nxt_state;
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
state <= 2'b00;
end
else if (en == 1'b1) begin
state <= nxt_state;
end
end
always @(state or scli or sdai or rstart or rstop) begin
case (state)
STRT: begin
if (rstart == 1'b1) begin
nxt_state = STOP;
rreset = 1'b0;
end
else begin
nxt_state = STRT;
rreset = 1'b0;
end
end
STOP: begin
if (scli == 1'b1) begin
if (rstop == 1'b1) begin
nxt_state = STRT;
rreset = 1'b1;
end
else begin
nxt_state = STOP;
rreset = 1'b0;
end
end
else if (scli == 1'b0) begin
nxt_state = SCLN;
rreset = 1'b0;
end
else begin
nxt_state = STRT;
rreset = 1'b0;
end
end
SCLN: begin // scli = 0
if (scli == 1'b1) begin
nxt_state = SCLP;
rreset = 1'b0;
end
else begin
nxt_state = SCLN;
rreset = 1'b0;
end
end
SCLP: begin // scli = 1
if (scli == 1'b1) begin
if (rstop == 1'b1) begin
nxt_state = STRT;
rreset = 1'b1;
end
else begin
nxt_state = SCLP;
rreset = 1'b0;
end
end
else begin
nxt_state = STRT;
rreset = 1'b0;
end
end
endcase
end
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// ===== detect start, stop signal ===== //
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
rstop <= 1'b0;
rstart <= 1'b0;
end
else if ( (en == 1'b1) && (scli == 1'b1) ) begin
if (sdai_pos == 1'b1) begin
rstop <= 1'b1;
rstart <= 1'b0;
end
else begin
rstop <= 1'b0;
if (sdai_neg == 1'b1) begin
rstart <= 1'b1;
end
else begin
rstart <= 1'b0;
end
end
end
else begin
rstop <= rstop ;
rstart <= rstart;
end
end
////////////////////////////////////////////////////////////////////////////////
assign stop = rstop ;
assign start = rstart;
assign reset = rreset;
endmodule
module stransmit
(
clk ,
rst_n,
en ,
tr ,
scli ,
sdai ,
tdat ,
bsy ,
bc ,
sdao ,
shf ,
ino ,
dne
);
parameter IDLE = 2'd0;
parameter TRAVP = 2'd1;
parameter TRAVN = 2'd2;
input clk ;
input rst_n;
input en ;
input tr ;
input scli ;
input sdai ;
input [7:0] tdat ;
output bsy ; // [0]: free, [1]: transfering
output [3:0] bc ;
output sdao ;
output [7:0] shf ;
output ino ;
output dne ;
reg rbsy ; // 0: free, 1: transfering
reg [3:0] rbc ;
reg rsdao;
reg rdne ;
reg ack ;
reg scli_01;
reg scli_02;
reg scli_03;
reg scli_04;
reg scli_05;
reg scli_06;
reg scli_07;
reg scli_08;
reg scli_09;
reg scli_10;
// D-FF to avoid the noise
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
scli_01 <= 1'b0;
scli_02 <= 1'b0;
scli_03 <= 1'b0;
scli_04 <= 1'b0;
scli_05 <= 1'b0;
scli_06 <= 1'b0;
scli_07 <= 1'b0;
scli_08 <= 1'b0;
scli_09 <= 1'b0;
scli_10 <= 1'b0;
end
else begin
scli_01 <= scli;
scli_02 <= scli_01;
scli_03 <= scli_02;
scli_04 <= scli_03;
scli_05 <= scli_04;
scli_06 <= scli_05;
scli_07 <= scli_06;
scli_08 <= scli_07;
scli_09 <= scli_08;
scli_10 <= scli_09;
end
end
reg scli_dl ;
wire scli_pos;
wire scli_neg;
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
scli_dl <= 1'b0;
end
else if (en == 1'b1) begin
scli_dl <= scli_10;
end
else begin
scli_dl <= scli_dl;
end
end
assign scli_pos = (~scli_dl) && scli_10;
assign scli_neg = scli_dl && (~scli_10);
reg [1:0] state;
reg [7:0] rshf;
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
state <= IDLE ;
rsdao <= 1'b0;
rbc <= 4'h0;
rshf <= 8'h00;
rbsy <= 1'b0;
rdne <= 1'b0;
ack <= ack;
end
else if (en == 1'b1) begin
case (state)
IDLE : begin
if (tr == 1'b1) begin
state <= TRAVP;
end
else begin
state <= IDLE ;
end
rsdao <= tdat[7];
rbc <= 4'h0;
rshf <= tdat;
rbsy <= 1'b0;
rdne <= 1'b0;
ack <= ack;
end
TRAVP: begin
if (scli_pos == 1'b1) begin
state <= TRAVN;
rshf <= rshf << 4'h1;
if (rbc == 4'h8) begin
ack <= sdai;
rdne <= 1'b1;
end
else begin
ack <= 1'b1;
rdne <= 1'b0;
end
end
else begin
state <= state;
rshf <= rshf;
ack <= 1'b1;
rdne <= 1'b0;
end
rsdao <= rsdao;
rbc <= rbc;
rbsy <= 1'b1;
end
TRAVN: begin
if (scli_neg == 1'b1) begin
if (rbc == 4'h8) begin
rbc <= 4'h0;
rshf <= tdat;
rdne <= 1'b1;
if (ack == 1'b0) begin
state <= TRAVP;
rsdao <= tdat[7];
end
else begin
state <= IDLE;
rsdao <= rsdao;
end
end
else begin
rsdao <= rshf[7];
rshf <= rshf;
state <= TRAVP;
rbc <= rbc + 4'h1;
rdne <= 1'b0;
end
end
else begin
state <= TRAVN;
rsdao <= rsdao;
rbc <= rbc;
rshf <= rshf;
rdne <= rdne;
end
rbsy <= 1'b1;
ack <= ack;
end
endcase
end
else begin
state <= IDLE ;
rsdao <= 1'b0;
rbc <= 4'h0;
rshf <= 8'h00;
rbsy <= 1'b0;
rdne <= 1'b0;
ack <= ack;
end
end
assign bsy = rbsy ;
assign bc = rbc ;
assign sdao = rsdao;
assign shf = rshf ;
assign ino = (rbc == 4'h8) ? 1'b1 : 1'b0;
assign dne = rdne ;
endmodule
module sreceive
(
clk ,
rst_n,
en ,
re ,
scli ,
sdai ,
hol ,
adrck,
saddr,
bsy ,
bc ,
rdat ,
sdao ,
shf ,
ino ,
dne
);
parameter IDLE = 2'd0;
parameter RECVP = 2'd1;
parameter RECVN = 2'd2;
input clk ;
input rst_n;
input en ;
input re ;
input scli ;
input sdai ;
input hol ;
input adrck; // 0: no check, just receive data, 1: address checking
input [7:0] saddr;
output bsy ; // 0: free, 1: transfering
output [3:0] bc ;
output [7:0] rdat ;
output sdao ;
output [7:0] shf ;
output ino ;
output dne ;
reg rbsy ; // 0: free, 1: transfering
reg [3:0] rbc ;
reg [7:0] rrdat;
reg rsdao;
reg rino ;
reg rdne ;
reg scli_01;
reg scli_02;
reg scli_03;
reg scli_04;
reg scli_05;
reg scli_06;
reg scli_07;
reg scli_08;
reg scli_09;
reg scli_10;
reg sdai_01;
reg sdai_02;
reg sdai_03;
reg sdai_04;
reg sdai_05;
reg sdai_06;
reg sdai_07;
reg sdai_08;
reg sdai_09;
reg sdai_10;
// D-FF to avoid the noise
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
scli_01 <= 1'b0;
scli_02 <= 1'b0;
scli_03 <= 1'b0;
scli_04 <= 1'b0;
scli_05 <= 1'b0;
scli_06 <= 1'b0;
scli_07 <= 1'b0;
scli_08 <= 1'b0;
scli_09 <= 1'b0;
scli_10 <= 1'b0;
end
else begin
scli_01 <= scli;
scli_02 <= scli_01;
scli_03 <= scli_02;
scli_04 <= scli_03;
scli_05 <= scli_04;
scli_06 <= scli_05;
scli_07 <= scli_06;
scli_08 <= scli_07;
scli_09 <= scli_08;
scli_10 <= scli_09;
end
end
// D-FF to avoid the noise
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
sdai_01 <= 1'b0;
sdai_02 <= 1'b0;
sdai_03 <= 1'b0;
sdai_04 <= 1'b0;
sdai_05 <= 1'b0;
sdai_06 <= 1'b0;
sdai_07 <= 1'b0;
sdai_08 <= 1'b0;
sdai_09 <= 1'b0;
sdai_10 <= 1'b0;
end
else begin
sdai_01 <= sdai;
sdai_02 <= sdai_01;
sdai_03 <= sdai_02;
sdai_04 <= sdai_03;
sdai_05 <= sdai_04;
sdai_06 <= sdai_05;
sdai_07 <= sdai_06;
sdai_08 <= sdai_07;
sdai_09 <= sdai_08;
sdai_10 <= sdai_09;
end
end
reg scli_dl ;
wire scli_pos;
wire scli_neg;
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
scli_dl <= 1'b0;
end
else if (en == 1'b1) begin
scli_dl <= scli_10;
end
else begin
scli_dl <= scli_dl;
end
end
assign scli_pos = (~scli_dl) && scli_10;
assign scli_neg = scli_dl && (~scli_10);
reg [ 1:0] state;
reg [ 7:0] rshf;
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
state <= IDLE;
rbsy <= 1'b0 ;
rshf <= 8'h00;
rbc <= 4'h0 ;
rrdat <= 8'h00;
rsdao <= 1'b1 ;
rino <= 1'b1 ;
rdne <= 1'b0 ;
end
else if (en == 1'b1) begin
case (state)
IDLE : begin
if (re == 1'b1) begin
state <= RECVP;
end
else begin
state <= IDLE;
end
rbsy <= 1'b0 ;
rshf <= rshf ;
rbc <= 4'h0 ;
rrdat <= rrdat;
rsdao <= 1'b1 ;
rino <= 1'b1 ;
rdne <= 1'b0 ;
end
RECVP: begin
if (scli_pos == 1'b1) begin
if (rbc == 4'h8) begin
rshf <= rshf;
end
else begin
rshf <= {rshf[6:0],sdai_10};
end
rbc <= rbc + 4'h1;
state <= RECVN;
end
else begin
rshf <= rshf;
rbc <= rbc;
state <= RECVP;
end
rbsy <= 1'b1;
rrdat <= rrdat;
rsdao <= rsdao;
rino <= rino ;
rdne <= 1'b0;
end
RECVN: begin
if (scli_neg == 1'b1) begin
if (rbc == 4'h8) begin
state <= RECVP;
rrdat <= rshf;
if (adrck == 1'b0) begin
rsdao <= 1'b0;
end
else begin
if ({rshf[7:1],(hol && rshf[0])} == saddr) begin
rsdao <= 1'b0;
end
else begin
rsdao <= 1'b1;
end
end
rino <= 1'b0 ;
rdne <= 1'b0;
end
else if (rbc == 4'h9) begin
state <= IDLE ;
rrdat <= rrdat;
rsdao <= rsdao;
rino <= 1'b0 ;
rdne <= 1'b1 ;
end
else begin
state <= RECVP;
rrdat <= rrdat;
rsdao <= 1'b1 ;
rino <= rino ;
rdne <= 1'b0 ;
end
end
else begin
state <= state;
rrdat <= rrdat;
rsdao <= rsdao;
rino <= rino ;
rdne <= rdne ;
end
rshf <= rshf;
rbsy <= 1'b1;
rbc <= rbc ;
end
endcase
end
else begin
state <= IDLE;
rbsy <= 1'b0 ;
rshf <= 8'h00;
rbc <= 4'h0 ;
rrdat <= rrdat;
rsdao <= 1'b1 ;
rino <= 1'b1 ;
rdne <= 1'b0 ;
end
end
assign bsy = rbsy ;
assign bc = rbc ;
assign rdat = rrdat;
assign sdao = rsdao;
assign shf = rshf ;
assign ino = rino ;
assign dne = rdne ;
endmodule
module master
(
// input
clk ,
rst_n,
en ,
scli ,
sdai ,
tr ,
ack ,
st ,
rs ,
sp ,
dlk ,
tdat ,
empt ,
spme ,
rmit ,
ackc ,
brh ,
brl ,
// output
bsy ,
sclo ,
sdao ,
rdat ,
shf ,
ino ,
bc ,
acke ,
rmiti,
ffrd ,
lfwr ,
tran_dne,
recv_dne
);
parameter IDLE = 4'd0;
parameter STRT = 4'd1;
parameter STOP = 4'd2;
parameter RSET = 4'd3;
parameter TRAN = 4'd4;
parameter RECV = 4'd5;
parameter WACK = 4'd6;
parameter XACK = 4'd7;
parameter WAIT = 4'd8;
input clk ;
input rst_n;
input en ;
input scli ;
input sdai ;
input tr ;
input ack ;
input st ;
input rs ;
input sp ;
input dlk ;
input [ 7:0] tdat ;
input empt ;
input spme ;
input [ 3:0] rmit ;
input ackc ;
input [ 7:0] brh ;
input [ 7:0] brl ;
// output
output bsy ;
output sclo;
output sdao;
output [ 7:0] rdat;
output [ 7:0] shf ;
output ino ;
output [ 3:0] bc ;
output acke ;
output rmiti;
output ffrd ;
output lfwr ;
output tran_dne;
output recv_dne;
reg rbsy ;
reg rffrd;
reg rsclo;
reg rsdao;
////////////////////
// FSM //
////////////////////
reg [ 3:0] state;
reg rstart;
reg rstop;
reg rtransmit;
reg rreceive;
reg rcounter;
////////////////////
// bitrate //
////////////////////
wire bitrate_en ;
wire bitrate_dlk ;
wire bitrate_cnth;
wire bitrate_cntl;
wire [7:0] bitrate_brh ;
wire [7:0] bitrate_brl ;
wire bitrate_limh;
wire bitrate_liml;
////////////////////
// mstart //
////////////////////
wire mstart_en ;
wire mstart_st ;
wire mstart_dlk ;
wire [ 7:0] mstart_brh ;
wire mstart_cur_scl;
wire mstart_cur_sda;
wire mstart_sclo ;
wire mstart_sdao ;
wire mstart_bsy ;
wire mstart_dne ;
////////////////////
// mstop //
////////////////////
wire mstop_en ;
wire mstop_sp ;
wire mstop_dlk ;
wire [ 7:0] mstop_brh ;
wire mstop_cur_scl;
wire mstop_cur_sda;
wire mstop_sclo ;
wire mstop_sdao ;
wire mstop_bsy ;
wire mstop_dne ;
////////////////////
// mtransmit //
////////////////////
wire mtransmit_en ;
wire mtransmit_tr ;
wire mtransmit_sdai ;
wire [ 7:0] mtransmit_tdat ;
wire [ 3:0] mtransmit_rmit ;
wire mtransmit_ackc ;
wire mtransmit_limh ;
wire mtransmit_liml ;
wire mtransmit_bsy ;
wire mtransmit_sclo ;
wire mtransmit_sdao ;
wire [ 3:0] mtransmit_bc ;
wire mtransmit_acko ;
wire [ 7:0] mtransmit_shf ;
wire mtransmit_ino ;
wire mtransmit_rmiti;
wire mtransmit_acke ;
wire mtransmit_cnth ;
wire mtransmit_cntl ;
wire mtransmit_dne ;
////////////////////
// mreceive //
////////////////////
wire mreceive_en ;
wire mreceive_re ;
wire mreceive_acki;
wire mreceive_sdai;
wire mreceive_limh;
wire mreceive_liml;
wire mreceive_bsy ;
wire mreceive_sclo;
wire mreceive_sdao;
wire [ 3:0] mreceive_bc ;
wire [ 7:0] mreceive_rdat;
wire [ 7:0] mreceive_shf ;
wire mreceive_ino ;
wire mreceive_cnth;
wire mreceive_cntl;
wire mreceive_lfwr;
wire mreceive_dne ;
////////////////////
// bitrate //
////////////////////
assign bitrate_en = en;
assign bitrate_dlk = dlk;
assign bitrate_cnth = mtransmit_cnth || mreceive_cnth;
assign bitrate_cntl = mtransmit_cntl || mreceive_cntl;
assign bitrate_brh = brh;
assign bitrate_brl = brl;
bitrate bitrate_01
(
.clk (clk ),
.rst_n(rst_n ),
.en (bitrate_en ),
.dlk (bitrate_dlk ),
.cnth (bitrate_cnth),
.cntl (bitrate_cntl),
.brh (bitrate_brh ),
.brl (bitrate_brl ),
.limh (bitrate_limh),
.liml (bitrate_liml)
);
////////////////////
// mstart //
////////////////////
assign mstart_en = en ;
assign mstart_st = rstart;
assign mstart_dlk = dlk ;
assign mstart_brh = brh ;
assign mstart_cur_scl = sclo ;
assign mstart_cur_sda = sdao ;
mstart mstart_01
(
.clk (clk ),
.rst_n (rst_n ),
.en (mstart_en ),
.st (mstart_st ),
.dlk (mstart_dlk ),
.brh (mstart_brh ),
.cur_scl(mstart_cur_scl),
.cur_sda(mstart_cur_sda),
.sclo (mstart_sclo ),
.sdao (mstart_sdao ),
.bsy (mstart_bsy ),
.dne (mstart_dne )
);
////////////////////
// mstop //
////////////////////
assign mstop_en = en ;
assign mstop_sp = rstop;
assign mstop_dlk = dlk ;
assign mstop_brh = brh ;
assign mstop_cur_scl = sclo ;
assign mstop_cur_sda = sdao ;
mstop mstop_01
(
.clk (clk ),
.rst_n (rst_n ),
.en (mstop_en ),
.sp (mstop_sp ),
.dlk (mstop_dlk ),
.brh (mstop_brh ),
.cur_scl(mstop_cur_scl),
.cur_sda(mstop_cur_sda),
.sclo (mstop_sclo ),
.sdao (mstop_sdao ),
.bsy (mstop_bsy ),
.dne (mstop_dne )
);
////////////////////
// mtransmit //
////////////////////
assign mtransmit_en = en && rtransmit;
assign mtransmit_tr = tr;
assign mtransmit_sdai = sdai;
assign mtransmit_tdat = tdat;
assign mtransmit_rmit = rmit;
assign mtransmit_ackc = ackc;
assign mtransmit_limh = bitrate_limh;
assign mtransmit_liml = bitrate_liml;
mtransmit mtransmit_01
(
.clk (clk ),
.rst_n(rst_n ),
.en (mtransmit_en ),
.tr (mtransmit_tr ),
.sdai (mtransmit_sdai ),
.tdat (mtransmit_tdat ),
.rmit (mtransmit_rmit ),
.ackc (mtransmit_ackc ),
.limh (mtransmit_limh ),
.liml (mtransmit_liml ),
.bsy (mtransmit_bsy ),
.sclo (mtransmit_sclo ),
.sdao (mtransmit_sdao ),
.bc (mtransmit_bc ),
.acko (mtransmit_acko ),
.shf (mtransmit_shf ),
.ino (mtransmit_ino ),
.rmiti(mtransmit_rmiti),
.acke (mtransmit_acke ),
.cnth (mtransmit_cnth ),
.cntl (mtransmit_cntl ),
.dne (mtransmit_dne )
);
////////////////////
// mreceive //
////////////////////
assign mreceive_en = en && rreceive;
assign mreceive_re = ~tr;
assign mreceive_acki = ack;
assign mreceive_sdai = sdai;
assign mreceive_limh = bitrate_limh;
assign mreceive_liml = bitrate_liml;
mreceive mreceive_01
(
.clk (clk ),
.rst_n(rst_n ),
.en (mreceive_en ),
.re (mreceive_re ),
.acki (mreceive_acki),
.sdai (mreceive_sdai),
.limh (mreceive_limh),
.liml (mreceive_liml),
.bsy (mreceive_bsy ),
.sclo (mreceive_sclo),
.sdao (mreceive_sdao),
.bc (mreceive_bc ),
.rdat (mreceive_rdat),
.shf (mreceive_shf ),
.ino (mreceive_ino ),
.cnth (mreceive_cnth),
.cntl (mreceive_cntl),
.lfwr (mreceive_lfwr),
.dne (mreceive_dne )
);
////////////////////////////////////////////////////////////////////////////////
// ===== FSM master ===== //
reg lst; //deLay for st signal
reg lrs; //deLay for rs signal
reg lsp; //deLay for sp signal
reg rino;
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
state <= IDLE;
lst <= 1'b0;
lrs <= 1'b0;
lsp <= 1'b0;
rffrd <= 1'b0;
rstart <= 1'b0;
rstop <= 1'b0;
rtransmit <= 1'b0;
rreceive <= 1'b0;
rbsy <= 1'b0;
rsclo <= 1'b1;
rsdao <= 1'b1;
rino <= 1'b0;
end
else if (en == 1'b1) begin
case (state)
IDLE: begin
if ((sp || lsp) == 1'b1) begin
state <= IDLE;
lst <= (st == 1'b1) ? 1'b1 : lst;
lrs <= (rs == 1'b1) ? 1'b1 : lrs;
lsp <= 1'b0;
rbsy <= 1'b0;
end
else if ( (st || lst || rs || lrs) == 1'b1 ) begin
state <= STRT;
lst <= 1'b0;
lrs <= 1'b0;
lsp <= (sp == 1'b1) ? 1'b1 : lsp;
rbsy <= 1'b1;
end
else begin
state <= IDLE;
lst <= 1'b0;
lrs <= 1'b0;
lsp <= 1'b0;
rbsy <= 1'b0;
end
rffrd <= 1'b0;
rstart <= 1'b0;
rstop <= 1'b0;
rtransmit <= 1'b0;
rreceive <= 1'b0;
rsclo <= 1'b1;
rsdao <= 1'b1;
rino <= 1'b0;
end
STRT: begin
if (mstart_dne == 1'b1) begin
if ((sp || lsp) == 1'b1) begin
state <= STOP;
rffrd <= 1'b0;
end
else if (tr == 1'b1) begin
if (empt == 1'b0) begin
state <= TRAN;
rffrd <= 1'b1;
end
else begin
state <= WAIT;
rffrd <= 1'b0;
end
end
else begin
state <= RECV;
rffrd <= 1'b0;
end
end
else begin
state <= STRT;
end
rstart <= 1'b1;
rstop <= 1'b0;
rtransmit <= 1'b0;
rreceive <= 1'b0;
rbsy <= 1'b1;
lst <= (st == 1'b1) ? 1'b1 : lst;
lrs <= (rs == 1'b1) ? 1'b1 : lrs;
lsp <= (sp == 1'b1) ? 1'b1 : lsp;
rsclo <= mstart_sclo;
rsdao <= mstart_sdao;
rino <= 1'b0;
end
STOP: begin
if (mstop_dne == 1'b1) begin
state <= IDLE;
end
else begin
state <= STOP;
end
rstart <= 1'b0;
rstop <= 1'b1;
rtransmit <= 1'b0;
rreceive <= 1'b0;
rffrd <= 1'b0;
rbsy <= 1'b1;
lst <= (st == 1'b1) ? 1'b1 : lst;
lrs <= (rs == 1'b1) ? 1'b1 : lrs;
lsp <= (sp == 1'b1) ? 1'b1 : lsp;
rsclo <= mstop_sclo;
rsdao <= mstop_sdao;
rino <= 1'b0;
end
TRAN: begin
if (mtransmit_dne == 1'b1) begin
state <= WACK;
end
else begin
state <= (empt == 1'b0) ? TRAN : WAIT;
end
rffrd <= 1'b0;
rstart <= 1'b0;
rstop <= 1'b0;
rreceive <= 1'b0;
rtransmit <= 1'b1;
rbsy <= 1'b1;
lst <= (st == 1'b1) ? 1'b1 : lst;
lrs <= (rs == 1'b1) ? 1'b1 : lrs;
lsp <= (sp == 1'b1) ? 1'b1 : lsp;
rsclo <= mtransmit_sclo;
rsdao <= mtransmit_sdao;
rino <= mtransmit_ino;
end
RECV: begin
if (mreceive_dne == 1'b1) begin
state <= XACK;
end
else begin
state <= RECV;
end
rstart <= 1'b0;
rstop <= 1'b0;
rtransmit <= 1'b0;
rreceive <= 1'b1;
rffrd <= 1'b0;
rbsy <= 1'b1;
lst <= (st == 1'b1) ? 1'b1 : lst;
lrs <= (rs == 1'b1) ? 1'b1 : lrs;
lsp <= (sp == 1'b1) ? 1'b1 : lsp;
rsclo <= mreceive_sclo;
rsdao <= mreceive_sdao;
rino <= mreceive_ino;
end
WACK: begin
if (mtransmit_dne == 1'b1) begin
state <= WACK;
rffrd <= (empt == 1'b0) ? ~mtransmit_rmiti : 1'b0;
lst <= (st == 1'b1) ? 1'b1 : lst;
lrs <= (rs == 1'b1) ? 1'b1 : lrs;
lsp <= (sp == 1'b1) ? 1'b1 : lsp;
end
else begin
if ((sp || lsp) == 1'b1) begin
state <= STOP;
rffrd <= rffrd;
lst <= (st == 1'b1) ? 1'b1 : lst;
lrs <= (rs == 1'b1) ? 1'b1 : lrs;
lsp <= 1'b0;
end
else if ((st || lst || rs || lrs) == 1'b1) begin
state <= STRT;
rffrd <= rffrd;
lst <= 1'b0;
lrs <= 1'b0;
lsp <= (sp == 1'b1) ? 1'b1 : lsp;
end
else if (tr == 1'b0) begin
state <= RECV;
rffrd <= rffrd;
lst <= (st == 1'b1) ? 1'b1 : lst;
lrs <= (rs == 1'b1) ? 1'b1 : lrs;
lsp <= (sp == 1'b1) ? 1'b1 : lsp;
end
else if (((~mtransmit_bsy && spme) || (empt && spme)) == 1'b1) begin
state <= STOP ;
rffrd <= rffrd;
lst <= (st == 1'b1) ? 1'b1 : lst;
lrs <= (rs == 1'b1) ? 1'b1 : lrs;
lsp <= 1'b0;
end
else begin
state <= (empt == 1'b0) ? TRAN : WAIT;
rffrd <= (empt == 1'b0) ? rffrd : 1'b0;
lst <= (st == 1'b1) ? 1'b1 : lst;
lrs <= (rs == 1'b1) ? 1'b1 : lrs;
lsp <= (sp == 1'b1) ? 1'b1 : lsp;
end
end
rstart <= rstart ;
rstop <= rstop ;
rtransmit <= ~empt ;
rreceive <= rreceive ;
rbsy <= 1'b1 ;
rsclo <= mtransmit_sclo;
rsdao <= mtransmit_sdao;
rino <= mtransmit_ino;
end
XACK: begin
if (mreceive_dne == 1'b1) begin
state <= XACK;
rffrd <= 1'b0;
lst <= (st == 1'b1) ? 1'b1 : lst;
lrs <= (rs == 1'b1) ? 1'b1 : lrs;
lsp <= (sp == 1'b1) ? 1'b1 : lsp;
end
else begin
if ((sp || lsp) == 1'b1) begin
state <= STOP;
rffrd <= 1'b0;
lst <= (st == 1'b1) ? 1'b1 : lst;
lrs <= (rs == 1'b1) ? 1'b1 : lrs;
lsp <= 1'b0;
end
else if ((st || lst || rs || lrs) == 1'b1) begin
state <= STRT;
rffrd <= 1'b0;
lst <= 1'b0;
lrs <= 1'b0;
lsp <= (sp == 1'b1) ? 1'b1 : lsp;
end
else if (tr == 1'b1) begin
state <= TRAN;
rffrd <= 1'b1;
lst <= (st == 1'b1) ? 1'b1 : lst;
lrs <= (rs == 1'b1) ? 1'b1 : lrs;
lsp <= (sp == 1'b1) ? 1'b1 : lsp;
end
else if (mreceive_bsy == 1'b0) begin
state <= STOP;
rffrd <= 1'b0;
lst <= (st == 1'b1) ? 1'b1 : lst;
lrs <= (rs == 1'b1) ? 1'b1 : lrs;
lsp <= 1'b0;
end
else begin
state <= RECV;
rffrd <= 1'b0;
lst <= (st == 1'b1) ? 1'b1 : lst;
lrs <= (rs == 1'b1) ? 1'b1 : lrs;
lsp <= (sp == 1'b1) ? 1'b1 : lsp;
end
end
rstart <= rstart ;
rstop <= rstop ;
rtransmit <= rtransmit;
rreceive <= rreceive ;
rbsy <= 1'b1 ;
rsclo <= mreceive_sclo;
rsdao <= mreceive_sdao;
rino <= mreceive_ino;
end
WAIT: begin
if ((sp || lsp) == 1'b1) begin
state <= STOP ;
rffrd <= rffrd;
lst <= (st == 1'b1) ? 1'b1 : lst;
lrs <= (rs == 1'b1) ? 1'b1 : lrs;
lsp <= 1'b0;
end
else if ((st || lst || rs || lrs) == 1'b1) begin
state <= STRT;
rffrd <= rffrd;
lst <= 1'b0;
lrs <= 1'b0;
lsp <= (sp == 1'b1) ? 1'b1 : lsp;
end
else if (tr == 1'b0) begin
state <= RECV;
rffrd <= rffrd;
lst <= (st == 1'b1) ? 1'b1 : lst;
lrs <= (rs == 1'b1) ? 1'b1 : lrs;
lsp <= (sp == 1'b1) ? 1'b1 : lsp;
end
else if ((empt && spme) == 1'b1) begin
state <= STOP ;
rffrd <= rffrd;
lst <= (st == 1'b1) ? 1'b1 : lst;
lrs <= (rs == 1'b1) ? 1'b1 : lrs;
lsp <= 1'b0;
end
else if (empt == 1'b0) begin
state <= TRAN;
rffrd <= 1'b1;
lst <= (st == 1'b1) ? 1'b1 : lst;
lrs <= (rs == 1'b1) ? 1'b1 : lrs;
lsp <= (sp == 1'b1) ? 1'b1 : lsp;
end
else begin
state <= WAIT;
rffrd <= 1'b0;
lst <= (st == 1'b1) ? 1'b1 : lst;
lrs <= (rs == 1'b1) ? 1'b1 : lrs;
lsp <= (sp == 1'b1) ? 1'b1 : lsp;
end
rstart <= 1'b0;
rstop <= 1'b0;
rtransmit <= 1'b0;
rreceive <= 1'b0;
rbsy <= 1'b1;
rsclo <= rsclo;
rsdao <= rsdao;
rino <= rino ;
end
default: begin
state <= STOP;
rstart <= 1'b0;
rstop <= 1'b0;
rtransmit <= 1'b0;
rreceive <= 1'b0;
rffrd <= 1'b0;
rbsy <= 1'b1;
lst <= (st == 1'b1) ? 1'b1 : lst;
lrs <= (rs == 1'b1) ? 1'b1 : lrs;
lsp <= (sp == 1'b1) ? 1'b1 : lsp;
rsclo <= rsclo;
rsdao <= rsdao;
rino <= rino ;
end
endcase
end
else begin
state <= IDLE;
lst <= 1'b0;
lrs <= 1'b0;
lsp <= 1'b0;
rffrd <= 1'b0;
rstart <= 1'b0;
rstop <= 1'b0;
rtransmit <= 1'b0;
rreceive <= 1'b0;
rbsy <= 1'b0;
rsclo <= rsclo;
rsdao <= rsdao;
rino <= rino ;
end
end
////////////////////////////////////////////////////////////////////////////////
assign bsy = rbsy;
assign sclo = rsclo;
assign sdao = rsdao;
assign rdat = mreceive_rdat;
assign shf = (tr == 1'b1) ? mtransmit_shf : mreceive_shf;
assign ino = rino;
assign bc = (tr == 1'b1) ? mtransmit_bc : mreceive_bc ;
assign acke = mtransmit_acke;
assign rmiti = mtransmit_rmiti;
assign ffrd = rffrd;
assign lfwr = mreceive_lfwr;
assign tran_dne = mtransmit_dne;
assign recv_dne = mreceive_dne;
endmodule
module slave
(
// input
clk ,
rst_n,
en ,
timeo,
arhol,
addr ,
tdat ,
scli ,
sdai ,
// output
bsy ,
tr ,
rdat ,
sclo ,
sdao ,
reset,
shf ,
bc ,
ino ,
ffrd ,
lfwr ,
tran_dne,
recv_dne
);
parameter IDLE = 4'd0;
parameter ADDR1 = 4'd1;
parameter ADDR2 = 4'd2;
parameter TRAN = 4'd4;
parameter RECV = 4'd5;
parameter WACK = 4'd6;
parameter XACK = 4'd7;
input clk ;
input rst_n;
input en ;
input timeo;
input arhol; // [1]: 10-bit address, [0]: 7-bit address
input [ 9:0] addr ;
input [ 7:0] tdat ;
input scli ;
input sdai ;
output bsy ;
output tr ; // [1]: transfer, [0]: receive
output [ 7:0] rdat ;
output sclo ;
output sdao ;
output reset;
output [ 7:0] shf ;
output [ 3:0] bc ;
output ino ;
output ffrd ;
output lfwr ;
output tran_dne;
output recv_dne;
reg rw ;
reg rbsy ;
reg rsclo;
reg rsdao;
reg rtr ;
reg rffrd;
reg rrecvint;
reg rrecvi_01;
reg rrecvi_02;
reg rrecvi_03;
reg rrecvi_04;
reg rrecvi_05;
reg rrecvi_06;
reg rrecvi_07;
reg rrecvi_08;
reg rrecvi_09;
reg rrecvi_10;
reg rreseti_01;
reg rreseti_02;
reg rreseti_03;
reg rreseti_04;
reg rreseti_05;
reg rreseti_06;
reg rreseti_07;
reg rreseti_08;
reg rreseti_09;
reg rreseti_10;
////////////////////
// FSM //
////////////////////
reg [ 3:0] state;
reg rtransmit;
reg rreceive;
reg radrck;
reg [ 7:0] rsaddr;
reg rhol;
////////////////////
// sdetect //
////////////////////
wire sdetect_en ;
wire sdetect_scli ;
wire sdetect_sdai ;
wire sdetect_stop ;
wire sdetect_start;
wire sdetect_reset;
////////////////////
// stransmit //
////////////////////
wire stransmit_en ;
wire stransmit_tr ;
wire stransmit_scli;
wire stransmit_sdai;
wire [ 7:0] stransmit_tdat;
wire stransmit_bsy ; // [0]: free, [1]: transfering
wire [ 3:0] stransmit_bc ;
wire stransmit_sdao;
wire [ 7:0] stransmit_shf ;
wire stransmit_ino ;
wire stransmit_dne ;
////////////////////
// sreceive //
////////////////////
wire sreceive_en ;
wire sreceive_re ;
wire sreceive_scli ;
wire sreceive_sdai ;
wire sreceive_hol ;
wire sreceive_adrck;
wire [ 7:0] sreceive_saddr;
wire sreceive_bsy ; // 0: free, 1: transfering
wire [ 3:0] sreceive_bc ;
wire [ 7:0] sreceive_rdat ;
wire sreceive_sdao ;
wire [ 7:0] sreceive_shf ;
wire sreceive_ino ;
wire sreceive_dne ;
////////////////////
// sdetect //
////////////////////
assign sdetect_en = en ;
assign sdetect_scli = scli;
assign sdetect_sdai = sdai;
sdetect sdetect_01
(
.clk (clk ),
.rst_n(rst_n ),
.en (sdetect_en ),
.scli (sdetect_scli ),
.sdai (sdetect_sdai ),
.stop (sdetect_stop ),
.start(sdetect_start),
.reset(sdetect_reset)
);
////////////////////
// stransmit //
////////////////////
assign stransmit_en = en && rtransmit;
assign stransmit_tr = rtransmit;
assign stransmit_scli = scli;
assign stransmit_sdai = sdai;
assign stransmit_tdat = tdat;
stransmit stransmit_01
(
.clk (clk ),
.rst_n(rst_n ),
.en (stransmit_en ),
.tr (stransmit_tr ),
.scli (stransmit_scli),
.sdai (stransmit_sdai),
.tdat (stransmit_tdat),
.bsy (stransmit_bsy ),
.bc (stransmit_bc ),
.sdao (stransmit_sdao),
.shf (stransmit_shf ),
.ino (stransmit_ino ),
.dne (stransmit_dne )
);
////////////////////
// sreceive //
////////////////////
assign sreceive_en = en && rreceive;
assign sreceive_re = rreceive;
assign sreceive_scli = scli;
assign sreceive_sdai = sdai;
assign sreceive_hol = rhol;
assign sreceive_adrck = radrck;
assign sreceive_saddr = rsaddr;
sreceive sreceive_01
(
.clk (clk ),
.rst_n(rst_n ),
.en (sreceive_en ),
.re (sreceive_re ),
.scli (sreceive_scli ),
.sdai (sreceive_sdai ),
.hol (sreceive_hol ),
.adrck(sreceive_adrck),
.saddr(sreceive_saddr),
.bsy (sreceive_bsy ),
.bc (sreceive_bc ),
.rdat (sreceive_rdat ),
.sdao (sreceive_sdao ),
.shf (sreceive_shf ),
.ino (sreceive_ino ),
.dne (sreceive_dne )
);
////////////////////////////////////////////////////////////////////////////////
// ===== FSM slave ===== //
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
state <= IDLE;
rtransmit <= 1'b0;
rreceive <= 1'b0;
radrck <= 1'b0;
rffrd <= 1'b0;
rhol <= 1'b0;
rtr <= 1'b0;
rbsy <= 1'b0;
rw <= 1'b0;
rsaddr <= 8'h00;
rsclo <= 1'b0;
rsdao <= 1'b0;
end
else if ( (en == 1'b1) && (timeo == 1'b0) ) begin
case (state)
IDLE: begin
if (sdetect_start == 1'b1) begin
state <= ADDR1;
rbsy <= 1'b1;
end
else begin
state <= IDLE;
rbsy <= 1'b0;
end
rtransmit <= 1'b0;
rreceive <= 1'b0;
radrck <= 1'b0;
rffrd <= 1'b0;
rhol <= 1'b0;
rtr <= 1'b0;
rw <= 1'b0;
rsaddr <= 8'h00;
rsclo <= rsclo;
rsdao <= rsdao;
end
ADDR1: begin
if (sdetect_stop == 1'b1) begin
state <= IDLE;
rreceive <= 1'b0;
radrck <= radrck;
rffrd <= 1'b0;
rw <= 1'b0;
rsaddr <= rsaddr;
end
else if (sreceive_dne == 1'b1) begin
rreceive <= 1'b0;
radrck <= radrck;
if (arhol == 1'b1) begin
if (sreceive_sdao == 1'b0) begin
state <= ADDR2;
rffrd <= 1'b0;
end
else begin
state <= IDLE;
rffrd <= 1'b0;
end
end
else begin
if (sreceive_sdao == 1'b0) begin
if (rdat[0] == 1'b0) begin // receive ~ write
state <= RECV;
rffrd <= 1'b0;
end
else begin // transfer ~ read
state <= TRAN;
rffrd <= 1'b1;
end
end
else begin
state <= IDLE;
rffrd <= rffrd;
end
end
rw <= rdat[0];
rsaddr <= rsaddr;
end
else begin
rreceive <= 1'b1;
radrck <= 1'b1;
if (arhol == 1'b0) begin
rsaddr <= {addr[7:1],1'b0};
end
else begin
rsaddr <= {5'b1111_0,addr[9:8],1'b0};
end
state <= ADDR1;
rffrd <= 1'b0;
rw <= rw;
end
rtransmit <= 1'b0;
rtr <= 1'b0;
rhol <= 1'b0;
rbsy <= 1'b1;
rsclo <= rsclo;
rsdao <= sreceive_sdao;
end
ADDR2: begin
if (sdetect_stop == 1'b1) begin
state <= IDLE;
rreceive <= 1'b0;
radrck <= 1'b0;
rsaddr <= rsaddr;
rffrd <= 1'b0;
end
else if (sdetect_start == 1'b1) begin
state <= ADDR1;
rreceive <= 1'b1;
radrck <= 1'b1;
rsaddr <= rsaddr;
rffrd <= 1'b0;
end
else if (sreceive_dne == 1'b1) begin
rreceive <= rreceive;
radrck <= 1'b0;
rsaddr <= rsaddr;
if (sreceive_sdao == 1'b0) begin
if (rw == 1'b0) begin // receive ~ write
state <= RECV;
rffrd <= 1'b0;
end
else begin // transfer ~ read
state <= TRAN;
rffrd <= 1'b1;
end
end
else begin
state <= IDLE;
rffrd <= 1'b0;
end
end
else begin
state <= state;
rreceive <= 1'b1;
radrck <= 1'b1;
rsaddr <= addr[7:0];
state <= ADDR2;
rffrd <= 1'b0;
end
rtransmit <= 1'b0;
rhol <= 1'b1;
rtr <= 1'b0;
rw <= rw;
rbsy <= 1'b1;
rsclo <= rsclo;
rsdao <= sreceive_sdao;
end
TRAN: begin // master read
if (sdetect_stop == 1'b1) begin
state <= IDLE;
rffrd <= 1'b0;
end
else if (sdetect_start == 1'b1) begin
state <= ADDR1;
rffrd <= 1'b0;
end
else if (stransmit_dne == 1'b1) begin
state <= WACK;
rffrd <= 1'b1;
end
else begin
state <= TRAN;
rffrd <= 1'b0;
end
rtransmit <= 1'b1;
rreceive <= 1'b0;
radrck <= 1'b0;
rsaddr <= rsaddr;
rhol <= rhol;
rtr <= 1'b1;
rbsy <= 1'b1;
rw <= rw;
rsclo <= rsclo;
rsdao <= stransmit_sdao;
end
RECV: begin // master transmit
if (sdetect_stop == 1'b1) begin
state <= IDLE;
end
else if (sdetect_start == 1'b1) begin
state <= ADDR1;
end
else if (sreceive_dne == 1'b1) begin
state <= XACK;
end
else begin
state <= RECV;
end
rtransmit <= 1'b0 ;
rreceive <= 1'b1 ;
rffrd <= 1'b0 ;
radrck <= 1'b0 ;
rsaddr <= rsaddr;
rhol <= rhol ;
rtr <= 1'b0 ;
rbsy <= 1'b1 ;
rw <= rw ;
rsclo <= rsclo;
rsdao <= sreceive_sdao;
end
WACK: begin
if (stransmit_dne == 1'b1) begin
state <= WACK;
rtransmit <= 1'b1;
end
else begin
if ((sdetect_stop == 1'b1) || (stransmit_bsy == 1'b0)) begin
state <= IDLE;
rtransmit <= 1'b0;
end
else if (sdetect_start == 1'b1) begin
state <= ADDR1;
rtransmit <= 1'b0;
end
else begin
state <= TRAN;
rtransmit <= 1'b1;
end
end
rreceive <= rreceive;
rffrd <= 1'b0 ;
radrck <= 1'b0 ;
rsaddr <= rsaddr;
rhol <= rhol ;
rtr <= rtr ;
rbsy <= 1'b1 ;
rw <= rw ;
rsclo <= rsclo;
rsdao <= rsdao;
end
XACK: begin
if (sreceive_dne == 1'b1) begin
state <= XACK;
rreceive <= 1'b1;
end
else begin
if (sdetect_stop == 1'b1) begin
state <= IDLE;
rreceive <= 1'b0;
end
else if (sdetect_start == 1'b1) begin
state <= ADDR1;
rreceive <= 1'b0;
end
else begin
state <= RECV;
rreceive <= 1'b1;
end
end
rtransmit <= rtransmit;
rffrd <= 1'b0 ;
radrck <= 1'b0 ;
rsaddr <= rsaddr;
rhol <= rhol ;
rtr <= rtr ;
rbsy <= 1'b1 ;
rw <= rw ;
rsclo <= rsclo;
rsdao <= rsdao;
end
endcase
end
else begin
state <= IDLE;
rtransmit <= 1'b0;
rreceive <= 1'b0;
radrck <= 1'b0;
rffrd <= 1'b0;
rhol <= 1'b0;
rtr <= 1'b0;
rbsy <= 1'b0;
rw <= 1'b0;
rsclo <= 1'b0;
rsdao <= 1'b0;
end
end
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// FF to synchronize slave receive interrupt with data in queue occur same time
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
rrecvint <= 1'b0;
end
else if (en == 1'b1) begin
rrecvint <= sreceive_dne;
end
else begin
rrecvint <= 1'b0;
end
end
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// FF to extend receive interrupt keep in 10 clock
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
rrecvi_01 <= 1'b0;
rrecvi_02 <= 1'b0;
rrecvi_03 <= 1'b0;
rrecvi_04 <= 1'b0;
rrecvi_05 <= 1'b0;
rrecvi_06 <= 1'b0;
rrecvi_07 <= 1'b0;
rrecvi_08 <= 1'b0;
rrecvi_09 <= 1'b0;
rrecvi_10 <= 1'b0;
end
else if (en == 1'b1) begin
rrecvi_01 <= rrecvint;
rrecvi_02 <= rrecvi_01;
rrecvi_03 <= rrecvi_02;
rrecvi_04 <= rrecvi_03;
rrecvi_05 <= rrecvi_04;
rrecvi_06 <= rrecvi_05;
rrecvi_07 <= rrecvi_06;
rrecvi_08 <= rrecvi_07;
rrecvi_09 <= rrecvi_08;
rrecvi_10 <= rrecvi_09;
end
else begin
rrecvi_01 <= 1'b0;
rrecvi_02 <= 1'b0;
rrecvi_03 <= 1'b0;
rrecvi_04 <= 1'b0;
rrecvi_05 <= 1'b0;
rrecvi_06 <= 1'b0;
rrecvi_07 <= 1'b0;
rrecvi_08 <= 1'b0;
rrecvi_09 <= 1'b0;
rrecvi_10 <= 1'b0;
end
end
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// FF to extend reset interrupt keep in 10 clock
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
rreseti_01 <= 1'b0;
rreseti_02 <= 1'b0;
rreseti_03 <= 1'b0;
rreseti_04 <= 1'b0;
rreseti_05 <= 1'b0;
rreseti_06 <= 1'b0;
rreseti_07 <= 1'b0;
rreseti_08 <= 1'b0;
rreseti_09 <= 1'b0;
rreseti_10 <= 1'b0;
end
else if (en == 1'b1) begin
rreseti_01 <= sdetect_reset;
rreseti_02 <= rreseti_01;
rreseti_03 <= rreseti_02;
rreseti_04 <= rreseti_03;
rreseti_05 <= rreseti_04;
rreseti_06 <= rreseti_05;
rreseti_07 <= rreseti_06;
rreseti_08 <= rreseti_07;
rreseti_09 <= rreseti_08;
rreseti_10 <= rreseti_09;
end
else begin
rreseti_01 <= 1'b0;
rreseti_02 <= 1'b0;
rreseti_03 <= 1'b0;
rreseti_04 <= 1'b0;
rreseti_05 <= 1'b0;
rreseti_06 <= 1'b0;
rreseti_07 <= 1'b0;
rreseti_08 <= 1'b0;
rreseti_09 <= 1'b0;
rreseti_10 <= 1'b0;
end
end
////////////////////////////////////////////////////////////////////////////////
assign bsy = rbsy;
assign rdat = sreceive_rdat;
assign sclo = rsclo;
assign sdao = rsdao;
assign reset = sdetect_reset || rreseti_01 || rreseti_02 || rreseti_03
|| rreseti_04 || rreseti_05 || rreseti_06 || rreseti_07
|| rreseti_08 || rreseti_09 || rreseti_10;
assign shf = (rtr == 1'b1) ? stransmit_shf : sreceive_shf;
assign bc = (rtr == 1'b1) ? stransmit_bc : sreceive_bc ;
assign tr = rtr;
assign ino = (rtr == 1'b1) ? stransmit_ino : sreceive_ino;
assign ffrd = rffrd;
assign lfwr = sreceive_dne;
assign tran_dne = stransmit_dne;
assign recv_dne = rrecvi_01 || rrecvi_02 || rrecvi_03 || rrecvi_04
|| rrecvi_05 || rrecvi_06 || rrecvi_07 || rrecvi_08
|| rrecvi_09 || rrecvi_10;
endmodule
module apbif
(
// AMBA APB interface
PCLK , // in
PRESETn , // in
PADDR , // in
PWRITE , // in
PSEL , // in
PENABLE , // in
PSTRB , // in
PWDATA , // in
PRDATA , // out
PREADY , // out
PSLVERR , // out
// GIIC core
rdatr , // in
sttr , // in
shfr , // in
bcr , // in
isr , // in
err , // in
ffcr , // in
lfcr , // in
enar , // out
modr , // out
ackr , // out
ctlr , // out
pscr , // out
brhr , // out
brlr , // out
funcr , // out
tmor , // out
rmitr , // out
addrr , // out
tdatr , // out
ier , // out
clrr , // out
rlar // out
);
// APB
input PCLK ;
input PRESETn;
input [ 7:0] PADDR ;
input PWRITE ;
input PSEL ;
input PENABLE;
input [ 3:0] PSTRB ;
input [31:0] PWDATA ;
output [31:0] PRDATA ;
output PREADY ;
output PSLVERR;
// IIC
input [ 7:0] rdatr ;
input [ 7:0] sttr ;
input [ 7:0] shfr ;
input [ 7:0] bcr ;
input [ 7:0] isr ;
input [ 7:0] err ;
input [ 7:0] ffcr ;
input [ 7:0] lfcr ;
output [31:0] enar ;
output [ 7:0] modr ;
output [ 7:0] ackr ;
output [ 7:0] ctlr ;
output [ 7:0] pscr ;
output [ 7:0] brhr ;
output [ 7:0] brlr ;
output [ 7:0] funcr ;
output [15:0] tmor ;
output [ 7:0] rmitr ;
output [15:0] addrr ;
output [31:0] tdatr ;
output [ 7:0] ier ;
output [ 7:0] clrr ;
output [ 7:0] rlar ;
// APB control signal
wire [31:0] ctrl_rdat ;
wire [ 3:0] ctrl_wstrb ;
wire ctrl_we ;
wire ctrl_re ;
wire [ 7:0] ctrl_reg_addr;
wire [31:0] ctrl_wdat ;
// APB reg signal
wire [ 3:0] reg_wstrb ;
wire reg_we ;
wire reg_re ;
wire [ 7:0] reg_reg_addr;
wire [31:0] reg_wdat ;
wire [31:0] reg_rdat_apb;
wire [ 7:0] reg_rdatr ;
wire [ 7:0] reg_sttr ;
wire [ 7:0] reg_shfr ;
wire [ 7:0] reg_bcr ;
wire [ 7:0] reg_isr ;
wire [ 7:0] reg_err ;
wire [ 7:0] reg_ffcr ;
wire [ 7:0] reg_lfcr ;
wire [31:0] reg_enar ;
wire [ 7:0] reg_modr ;
wire [ 7:0] reg_ackr ;
wire [ 7:0] reg_ctlr ;
wire [ 7:0] reg_pscr ;
wire [ 7:0] reg_brhr ;
wire [ 7:0] reg_brlr ;
wire [ 7:0] reg_funcr ;
wire [15:0] reg_tmor ;
wire [ 7:0] reg_rmitr ;
wire [15:0] reg_addrr ;
wire [31:0] reg_tdatr ;
wire [ 7:0] reg_ier ;
wire [ 7:0] reg_clrr ;
wire [ 7:0] reg_rlar ;
assign reg_wstrb = ctrl_wstrb ;
assign reg_we = ctrl_we ;
assign reg_re = ctrl_re ;
assign reg_reg_addr = ctrl_reg_addr;
assign reg_wdat = ctrl_wdat ;
assign ctrl_rdat = reg_rdat_apb ;
assign reg_rdatr = rdatr ;
assign reg_sttr = sttr ;
assign reg_shfr = shfr ;
assign reg_bcr = bcr ;
assign reg_isr = isr ;
assign reg_err = err ;
assign reg_ffcr = ffcr ;
assign reg_lfcr = lfcr ;
apbif_ctrl apbif_ctrl_01
(
.PCLK (PCLK ),
.PRESETn (PRESETn ),
.PADDR (PADDR ),
.PWRITE (PWRITE ),
.PSEL (PSEL ),
.PENABLE (PENABLE ),
.PSTRB (PSTRB ),
.PWDATA (PWDATA ),
.PRDATA (PRDATA ),
.PREADY (PREADY ),
.PSLVERR (PSLVERR ),
.rdat (ctrl_rdat ),
.wstrb (ctrl_wstrb ),
.we (ctrl_we ),
.re (ctrl_re ),
.reg_addr(ctrl_reg_addr),
.wdat (ctrl_wdat )
);
apbif_reg apbif_reg_01
(
.PCLK (PCLK ),
.PRESETn (PRESETn ),
.wstrb (reg_wstrb ),
.we (reg_we ),
.re (reg_re ),
.reg_addr(reg_reg_addr),
.wdat (reg_wdat ),
.rdat_apb(reg_rdat_apb),
.rdatr (reg_rdatr ),
.sttr (reg_sttr ),
.shfr (reg_shfr ),
.bcr (reg_bcr ),
.isr (reg_isr ),
.err (reg_err ),
.ffcr (reg_ffcr ),
.lfcr (reg_lfcr ),
.enar (reg_enar ),
.modr (reg_modr ),
.ackr (reg_ackr ),
.ctlr (reg_ctlr ),
.pscr (reg_pscr ),
.brhr (reg_brhr ),
.brlr (reg_brlr ),
.funcr (reg_funcr ),
.tmor (reg_tmor ),
.rmitr (reg_rmitr ),
.addrr (reg_addrr ),
.tdatr (reg_tdatr ),
.ier (reg_ier ),
.clrr (reg_clrr ),
.rlar (reg_rlar )
);
assign enar = reg_enar ;
assign modr = reg_modr ;
assign ackr = reg_ackr ;
assign ctlr = reg_ctlr ;
assign pscr = reg_pscr ;
assign brhr = reg_brhr ;
assign brlr = reg_brlr ;
assign funcr = reg_funcr;
assign tmor = reg_tmor ;
assign rmitr = reg_rmitr;
assign addrr = reg_addrr;
assign tdatr = reg_tdatr;
assign ier = reg_ier ;
assign clrr = reg_clrr ;
assign rlar = reg_rlar ;
endmodule
////////////////////////////////////////////////////////////////////////////////
// Project name: GIIC (I2C-bus) //
// File name : apbif_ctrl //
// Description : APB control //
// Time: 20:05 02/20/2019 //
// Copyright © 2019 by Unillog //
////////////////////////////////////////////////////////////////////////////////
module apbif_ctrl
(
PCLK ,
PRESETn ,
PADDR ,
PWRITE ,
PSEL ,
PENABLE ,
PSTRB ,
PWDATA ,
PRDATA ,
PREADY ,
PSLVERR ,
rdat ,
wstrb ,
we ,
re ,
reg_addr,
wdat
);
// APB
input PCLK ;
input PRESETn ;
input [ 7:0] PADDR ;
input PWRITE ;
input PSEL ;
input PENABLE ;
input [ 3:0] PSTRB ;
input [31:0] PWDATA ;
output [31:0] PRDATA ;
output PREADY ;
output PSLVERR ;
// apbif_reg
input [31:0] rdat ;
output [ 3:0] wstrb ;
output we ;
output re ;
output [ 7:0] reg_addr;
output [31:0] wdat ;
reg [31:0] prdata_reg;
always @(posedge PCLK or negedge PRESETn) begin
if (PRESETn == 1'b0) begin
prdata_reg <= 32'h0000_0000;
end
else if (re == 1'b1) begin
prdata_reg <= rdat;
end
else begin
prdata_reg <= prdata_reg;
end
end
assign PRDATA = prdata_reg;
assign wstrb = PSTRB;
assign we = PSEL & PENABLE & PWRITE;
assign re = PSEL & ~PENABLE & ~PWRITE & (PSTRB == 4'b0000);
assign reg_addr = PADDR;
assign wdat = PWDATA;
assign PREADY = 1'b1; // bus always ready
assign PSLVERR = (PADDR[1:0] == 2'b00) ? 1'b0 : we; // error if valid addr
endmodule
////////////////////////////////////////////////////////////////////////////////
// Project name: GIIC (I2C-bus) //
// File name : apbif_reg //
// Description : APB register //
// Time: 20:05 02/20/2019 //
// Copyright © 2019 by Unillog //
////////////////////////////////////////////////////////////////////////////////
module apbif_reg
(
// APB control
PCLK ,
PRESETn ,
wstrb ,
we ,
re ,
reg_addr,
wdat ,
rdat_apb,
// IIC core
rdatr ,
sttr ,
shfr ,
bcr ,
isr ,
err ,
ffcr ,
lfcr ,
enar ,
modr ,
ackr ,
ctlr ,
pscr ,
brhr ,
brlr ,
funcr ,
tmor ,
rmitr ,
addrr ,
tdatr ,
ier ,
clrr ,
rlar
);
parameter OPBT_ENAR = 32'h0000_0000;
parameter OPBT_WPR = 16'h0000;
parameter OPBT_MODR = 8'h00;
parameter OPBT_ACKR = 8'h00;
parameter OPBT_CTLR = 8'h00;
parameter OPBT_PSCR = 8'h00;
parameter OPBT_BRHR = 8'h00;
parameter OPBT_BRLR = 8'h00;
parameter OPBT_FUNCR = 8'h00;
parameter OPBT_TMOR = 16'h0000;
parameter OPBT_RMITR = 8'h00;
parameter OPBT_ADDRR = 16'h0000;
parameter OPBT_TDATR = 8'h00;
parameter OPBT_IER = 8'h00;
parameter OPBT_CLRR = 8'h00;
parameter OPBT_RLAR = 8'h00;
parameter ENAR = 8'h00; // Enable Register
parameter WPR = 8'h04; // Protect Register
parameter MODR = 8'h08; // Mod Register
parameter ACKR = 8'h0C; // ACK Register
parameter CTLR = 8'h10; // Control Register
parameter PSCR = 8'h14; // Prescaler Register
parameter BRHR = 8'h18; // Bit Rate High Register
parameter BRLR = 8'h1C; // Bit Rate Low Register
parameter FUNCR = 8'h20; // Function Register
parameter TMOR = 8'h24; // Time Out Register
parameter RMITR = 8'h28; // Retransmit Register
parameter ADDRR = 8'h2C; // Address Register
parameter TDATR = 8'h30; // Transmit Data Register
parameter IER = 8'h34; // Interrupt Enable Register
parameter CLRR = 8'h38; // Clear Register
parameter RLAR = 8'h3C; // Receive LIFO Address Register
parameter RDATR = 8'h50; // Receive Data Register
parameter STTR = 8'h54; // Status Register
parameter SHFR = 8'h58; // Shift Register
parameter BCR = 8'h5C; // Bit Count Register
parameter ISR = 8'h60; // Interrupt Status Register
parameter ERR = 8'h64; // Error Register
parameter FFCR = 8'h68; // FIFO Counter Register
parameter LFCR = 8'h6C; // LIFO Counter Register
input PCLK ;
input PRESETn ;
// APB control
input [ 3:0] wstrb ;
input we ;
input re ;
input [ 7:0] reg_addr;
input [31:0] wdat ;
output [31:0] rdat_apb;
// GIIC core
input [ 7:0] rdatr;
input [ 7:0] sttr ;
input [ 7:0] shfr ;
input [ 7:0] bcr ;
input [ 7:0] isr ;
input [ 7:0] err ;
input [ 7:0] ffcr ;
input [ 7:0] lfcr ;
output [31:0] enar ;
output [ 7:0] modr ;
output [ 7:0] ackr ;
output [ 7:0] ctlr ;
output [ 7:0] pscr ;
output [ 7:0] brhr ;
output [ 7:0] brlr ;
output [ 7:0] funcr;
output [15:0] tmor ;
output [ 7:0] rmitr;
output [15:0] addrr;
output [31:0] tdatr;
output [ 7:0] ier ;
output [ 7:0] clrr ;
output [ 7:0] rlar ;
reg [31:0] r_rdat_apb; // Data read
reg [31:0] r_enar ; // Enable Register
reg [15:0] r_wpr ; // Protect Register
reg [ 7:0] r_modr ; // Mod Register
reg [ 7:0] r_ackr ; // ACK Register
reg [ 7:0] r_ctlr ; // Control Register
reg [ 7:0] r_pscr ; // Prescaler Register
reg [ 7:0] r_brhr ; // Bit Rate High Register
reg [ 7:0] r_brlr ; // Bit Rate Low Register
reg [ 7:0] r_funcr; // Function Register
reg [15:0] r_tmor ; // Time Out Register
reg [ 7:0] r_rmitr; // Retransmit Register
reg [15:0] r_addrr; // Address Register
reg [31:0] r_tdatr; // Transmit Data Register
reg [ 7:0] r_ier ; // Interrupt Enable Register
reg [ 7:0] r_clrr ; // Clear Register
reg [ 7:0] r_rlar ; // Receive LIFO Address Register
// Enable Register 00 ENAR
// KCE[31:1] ICE
always @(posedge PCLK or negedge PRESETn) begin
if (PRESETn == 1'b0) begin
r_enar <= OPBT_ENAR;
end
else if ( (we == 1'b1) && (reg_addr == ENAR) &&
({wdat[31:1],1'b0} == 32'hCAFE_CAFE) ) begin
r_enar[31:8] <= 24'h00_0000;
r_enar[ 7:0] <= (wstrb[0] == 1'b1) ? {7'b0000_000,wdat[0]} : r_enar;
end
else begin
r_enar <= r_enar;
end
end
// Protect Register 04 WPR
// RLAWP CLWP IEWP TDATWP ADDRWP RMITWP
// TMOWP FUNCWP BRATWP PSCWP CTLWP ACKWP MODWP
always @(posedge PCLK or negedge PRESETn) begin
if (PRESETn == 1'b0) begin
r_wpr <= OPBT_WPR;
end
else if ( (we == 1'b1) && (reg_addr == WPR) ) begin
r_wpr[15:13] <= 3'b000;
r_wpr[12: 8] <= (wstrb[1] == 1'b1) ? wdat[12:8] : r_wpr[15:8];
r_wpr[ 7: 0] <= (wstrb[0] == 1'b1) ? wdat[ 7:0] : r_wpr[ 7:0];
end
else begin
r_wpr <= r_wpr;
end
end
// Mod Register 08 MODR
// MS TR
always @(posedge PCLK or negedge PRESETn) begin
if (PRESETn == 1'b0) begin
r_modr <= OPBT_MODR;
end
else if ( (we == 1'b1) && (reg_addr == MODR) && (r_wpr[0] == 1'b1) ) begin
r_modr <= (wstrb[0] == 1'b1) ? {6'b0000_00,wdat[1:0]} : r_modr;
end
else begin
r_modr[7:2] <= r_modr[7:2];
r_modr[ 1] <= (err[1]) ? 1'b0 : r_modr[1];
r_modr[ 0] <= (err[1]) ? 1'b0 : r_modr[0];
end
end
// ACK Register 0C ACKR
// ACK
always @(posedge PCLK or negedge PRESETn) begin
if (PRESETn == 1'b0) begin
r_ackr <= OPBT_ACKR;
end
else if ( (we == 1'b1) && (reg_addr == ACKR) && (r_wpr[1] == 1'b1) ) begin
r_ackr <= (wstrb[0] == 1'b1) ? {7'b0000_000,wdat[0]} : r_ackr;
end
else begin
r_ackr <= r_ackr;
end
end
// Control Register 10 CTLR
// ST RS SP
always @(posedge PCLK or negedge PRESETn) begin
if (PRESETn == 1'b0) begin
r_ctlr <= OPBT_CTLR;
end
else if ( (we == 1'b1) && (reg_addr == CTLR) && (r_wpr[2] == 1'b1) ) begin
r_ctlr <= (wstrb[0] == 1'b1) ? {5'b0000_0,wdat[2:0]} : r_ctlr;
end
else begin
r_ctlr <= OPBT_CTLR;
end
end
// Prescaler Register 14 PSCR
// PSC[3:0]
always @(posedge PCLK or negedge PRESETn) begin
if (PRESETn == 1'b0) begin
r_pscr <= OPBT_PSCR;
end
else if ( (we == 1'b1) && (reg_addr == PSCR) && (r_wpr[3] == 1'b1) ) begin
r_pscr <= (wstrb[0] == 1'b1) ? {4'h0,wdat[3:0]} : r_pscr ;
end
else begin
r_pscr <= r_pscr;
end
end
// Bit Rate High Register 18 BRHR
// BRH[7:0]
always @(posedge PCLK or negedge PRESETn) begin
if (PRESETn == 1'b0) begin
r_brhr <= OPBT_BRHR;
end
else if ( (we == 1'b1) && (reg_addr == BRHR) && (r_wpr[4] == 1'b1) ) begin
r_brhr <= (wstrb[0] == 1'b1) ? wdat[7:0] : r_brhr;
end
else begin
r_brhr <= r_brhr;
end
end
// Bit Rate Low Register 1C BRLR
// BRL[7:0]
always @(posedge PCLK or negedge PRESETn) begin
if (PRESETn == 1'b0) begin
r_brlr <= OPBT_BRLR;
end
else if ( (we == 1'b1) && (reg_addr == BRLR) && (r_wpr[4] == 1'b1) ) begin
r_brlr <= (wstrb[0] == 1'b1) ? wdat[7:0] : r_brlr;
end
else begin
r_brlr <= r_brlr;
end
end
// Function Register 20 FUNCR
// ALE RMITE TMOE
always @(posedge PCLK or negedge PRESETn) begin
if (PRESETn == 1'b0) begin
r_funcr <= OPBT_FUNCR;
end
else if ( (we == 1'b1) && (reg_addr == FUNCR) && (r_wpr[5] == 1'b1) ) begin
r_funcr <= (wstrb[0] == 1'b1) ? {1'b0,wdat[6:0]} : r_funcr;
end
else begin
r_funcr <= r_funcr;
end
end
// Time Out Register 24 TMOR
// TMO[15:0]
always @(posedge PCLK or negedge PRESETn) begin
if (PRESETn == 1'b0) begin
r_tmor <= OPBT_TMOR;
end
else if ( (we == 1'b1) && (reg_addr == TMOR) && (r_wpr[6] == 1'b1)) begin
r_tmor[15:8] <= (wstrb[1] == 1'b1) ? wdat[15:8] : r_tmor[15:8];
r_tmor[ 7:0] <= (wstrb[0] == 1'b1) ? wdat[ 7:0] : r_tmor[ 7:0];
end
else begin
r_tmor <= r_tmor;
end
end
// Retransmit Register 28 RMITR
// - - - - RMIT[3:0]
always @(posedge PCLK or negedge PRESETn) begin
if (PRESETn == 1'b0) begin
r_rmitr <= OPBT_RMITR;
end
else if ( (we == 1'b1) && (reg_addr == RMITR) && (r_wpr[7] == 1'b1)) begin
r_rmitr <= (wstrb[0] == 1'b1) ? {4'h0,wdat[3:0]} : r_rmitr;
end
else begin
r_rmitr <= r_rmitr;
end
end
// Address Register 2C ADDRR
// HOL - - - - - ADDR10 ADDR7
always @(posedge PCLK or negedge PRESETn) begin
if (PRESETn == 1'b0) begin
r_addrr <= OPBT_ADDRR;
end
else if ( (we == 1'b1) && (reg_addr == ADDRR) && (r_wpr[8] == 1'b1) ) begin
r_addrr[15:8] <= (wstrb[1] == 1'b1) ? {wdat[15],5'b00000,wdat[9:8]}
: r_addrr[15:8];
r_addrr[ 7:0] <= (wstrb[0] == 1'b1) ? wdat[7:0] : r_addrr[ 7:0];
end
else begin
r_addrr <= r_addrr;
end
end
// Transmit Data Register 30 TDATR
// TDAT[31:0]
always @(posedge PCLK or negedge PRESETn) begin
if (PRESETn == 1'b0) begin
r_tdatr <= {24'hC0FFEE,OPBT_TDATR};
end
else if ( (we == 1'b1) && (reg_addr == TDATR) && (r_wpr[9] == 1'b1) ) begin
r_tdatr[31:0] <= (wstrb[0] == 1'b1) ? {24'hC0FFEE,wdat[7:0]} : r_tdatr[31:0];
end
else begin
r_tdatr[31:0] <= {24'h0000_00,r_tdatr[7:0]};
end
end
// Interrupt Enable Register 34 IER
// QEMIE RESETIE RMITIE RECVIE TRANIE
always @(posedge PCLK or negedge PRESETn) begin
if (PRESETn == 1'b0) begin
r_ier <= OPBT_IER;
end
else if ( (we == 1'b1) && (reg_addr == IER) && (r_wpr[10] == 1'b1)) begin
r_ier <= (wstrb[0] == 1'b1) ? {3'b000,wdat[4:0]} : r_ier;
end
else begin
r_ier <= r_ier;
end
end
// Clear Register 38 CLRR
// FQUEC QFLC - LQUEC TMOC ACKC MALC SALC
always @(posedge PCLK or negedge PRESETn) begin
if (PRESETn == 1'b0) begin
r_clrr <= OPBT_CLRR;
end
else if ( (we == 1'b1) && (reg_addr == CLRR) && (r_wpr[11] == 1'b1) ) begin
r_clrr <= (wstrb[0] == 1'b1) ? {wdat[7:6],1'b0,wdat[4:0]}: r_clrr;
end
else begin
r_clrr <= OPBT_CLRR;
end
end
// Clear Register 3C RLAR
// RLA[7:0]
always @(posedge PCLK or negedge PRESETn) begin
if (PRESETn == 1'b0) begin
r_rlar <= OPBT_RLAR;
end
else if ( (we == 1'b1) && (reg_addr == RLAR) && (r_wpr[12] == 1'b1) ) begin
r_rlar <= (wstrb[0] == 1'b1) ? {4'h0,wdat[3:0]} : r_rlar;
end
else begin
r_rlar <= r_rlar;
end
end
////////////////////////////////////////////////////////////////////////////////
// FOR APB READ //
/////////////////
always @(reg_addr or
r_enar or r_wpr or r_modr or r_ackr or r_ctlr or r_pscr or r_brhr or
r_brlr or r_funcr or r_tmor or r_rmitr or r_addrr or r_tdatr or r_ier
or r_clrr or r_rlar
or rdatr or sttr or shfr or bcr or isr or err or ffcr or lfcr) begin
case (reg_addr)
ENAR : begin
r_rdat_apb <= r_enar;
end
WPR : begin
r_rdat_apb <= {16'h0000,r_wpr};
end
MODR : begin
r_rdat_apb <= {24'h00_0000,r_modr};
end
ACKR : begin
r_rdat_apb <= {24'h00_0000,r_ackr};
end
CTLR : begin
r_rdat_apb <= {24'h00_0000,r_ctlr};
end
PSCR : begin
r_rdat_apb <= {24'h00_0000,r_pscr};
end
BRHR: begin
r_rdat_apb <= {24'h00_0000,r_brhr};
end
BRLR : begin
r_rdat_apb <= {24'h00_0000,r_brlr};
end
FUNCR: begin
r_rdat_apb <= {24'h00_0000,r_funcr};
end
TMOR: begin
r_rdat_apb <= {16'h0000,r_tmor};
end
RMITR: begin
r_rdat_apb <= {24'h00_0000,r_rmitr};
end
ADDRR: begin
r_rdat_apb <= {16'h0000,r_addrr};
end
TDATR: begin
r_rdat_apb <= {24'h00_0000,r_tdatr[7:0]};
end
IER: begin
r_rdat_apb <= {24'h00_0000,r_ier};
end
CLRR: begin
r_rdat_apb <= {24'h00_0000,r_clrr};
end
RLAR: begin
r_rdat_apb <= {24'h00_0000,r_rlar};
end
RDATR: begin
r_rdat_apb <= {24'h00_0000,rdatr};
end
STTR : begin
r_rdat_apb <= {24'h00_0000,sttr};
end
SHFR : begin
r_rdat_apb <= {24'h00_0000,shfr};
end
BCR : begin
r_rdat_apb <= {24'h00_0000,bcr};
end
ISR : begin
r_rdat_apb <= {24'h00_0000,isr};
end
ERR : begin
r_rdat_apb <= {24'h00_0000,err};
end
FFCR : begin
r_rdat_apb <= {24'h00_0000,ffcr};
end
LFCR : begin
r_rdat_apb <= {24'h00_0000,lfcr};
end
endcase
end
assign rdat_apb = r_rdat_apb;
assign enar = r_enar ;
assign modr = r_modr ;
assign ackr = r_ackr ;
assign ctlr = r_ctlr ;
assign pscr = r_pscr ;
assign brhr = r_brhr ;
assign brlr = r_brlr ;
assign funcr = r_funcr ;
assign tmor = r_tmor ;
assign rmitr = r_rmitr ;
assign addrr = r_addrr ;
assign tdatr = r_tdatr ;
assign ier = r_ier ;
assign clrr = r_clrr ;
assign rlar = r_rlar ;
endmodule
module iic
(
clk , // clock
rst_n , // reset
enar , // Enable Register
modr , // Mod Register
ackr , // ACK Register
ctlr , // Control Register
pscr , // Prescaler Register
brhr , // Bit Rate High Register
brlr , // Bit Rate Low Register
funcr , // Function Register
tmor , // Time Out Register
rmitr , // Retransmit Register
addrr , // Address Register
tdatr , // Transmit Data Register
ier , // Interrupt Enable Register
clrr , // Clear Register
rlar , // Receive LIFO Address Register
rdatr , // Receive Data Register
sttr , // Status Register
shfr , // Shift Register
bcr , // Bit Count Register
isr , // Interrupt Status Register
err , // Error Register
ffcr , // FIFO Counter Register
lfcr , // LIFO Counter Register
scl , // scl pin
sda // sda pin
);
input clk ;
input rst_n;
input [31:0] enar ;
input [ 7:0] modr ;
input [ 7:0] ackr ;
input [ 7:0] ctlr ;
input [ 7:0] pscr ;
input [ 7:0] brhr ;
input [ 7:0] brlr ;
input [ 7:0] funcr;
input [15:0] tmor ;
input [ 7:0] rmitr;
input [15:0] addrr;
input [31:0] tdatr;
input [ 7:0] ier ;
input [ 7:0] clrr ;
input [ 7:0] rlar ;
output [ 7:0] rdatr;
output [ 7:0] sttr ;
output [ 7:0] shfr ;
output [ 7:0] bcr ;
output [ 7:0] isr ;
output [ 7:0] err ;
output [ 7:0] ffcr ;
output [ 7:0] lfcr ;
inout scl ;
inout sda ;
wire en ;
wire ms ;
wire tr ;
wire ack ;
wire st ;
wire rs ;
wire sp ;
wire [ 3:0] psc ;
wire [ 7:0] brh ;
wire [ 7:0] brl ;
wire [ 2:0] nfs ;
wire spme ;
wire ale ;
wire rmite ;
wire tmoe ;
wire [15:0] tmo ;
wire [ 3:0] rmit ;
wire [ 9:0] addr ;
wire arhol ;
wire [23:0] tkey ;
wire [ 7:0] tdat ;
wire qemie ;
wire resetie;
wire rmitie ;
wire recvie ;
wire tranie ;
wire fquec ;
wire qflc ;
wire qemc ;
wire lquec ;
wire tmoc ;
wire ackc ;
wire malc ;
wire salc ;
wire [ 3:0] rla ;
wire [ 7:0] rdat ;
wire ino ;
wire sclo ;
wire sdao ;
wire scli ;
wire sdai ;
wire bbsy ;
wire gbsy ;
wire bsy ;
wire [ 7:0] shf ;
wire [ 3:0] bc ;
wire qemi ;
wire reseti;
wire rmiti ;
wire recvi ;
wire trani ;
wire qfle ;
wire qeme ;
wire timoe ;
wire acke ;
wire male ;
wire sale ;
wire oe ; // output enable to avoid artribute
////////////////////
wire tran_dne;
wire recv_dne;
////////////////////
// noisefter //
////////////////////
wire noisefter_en ;
wire [ 2:0] noisefter_nfs ;
wire noisefter_scl_sgi;
wire noisefter_scl_sgo;
wire noisefter_sda_sgi;
wire noisefter_sda_sgo;
////////////////////
// bbsy //
////////////////////
wire bbsy_en ;
wire bbsy_scli;
wire bbsy_sdai;
wire bbsy_sclo;
wire bbsy_sdao;
wire bbsy_ms ;
wire bbsy_bbsy;
wire bbsy_gbsy;
////////////////////
// arbitration //
////////////////////
wire arbitration_en ;
wire arbitration_bbsy ;
wire arbitration_gbsy ;
wire arbitration_sda ;
wire arbitration_msdao;
wire arbitration_ssdao;
wire arbitration_st ;
wire arbitration_ms ;
wire arbitration_ino ;
wire arbitration_malc ;
wire arbitration_salc ;
wire arbitration_male ;
wire arbitration_sale ;
////////////////////
// prescaler //
////////////////////
wire prescaler_en ;
wire [3:0] prescaler_psc;
wire prescaler_dlk;
////////////////////
// timeout //
////////////////////
wire timeout_en ;
wire timeout_scli;
wire timeout_dlk ;
wire [15:0] timeout_tmo ;
wire timeout_tmoc;
wire timeout_limt;
wire [15:0] timeout_cnt ;
////////////////////
// fifo //
////////////////////
wire fifo_en ;
wire fifo_rd ;
wire fifo_clrq;
wire [ 2:0] fifo_clre;
wire [23:0] fifo_tkey;
wire [ 7:0] fifo_data;
wire [ 7:0] fifo_tdat;
wire [ 2:0] fifo_err ;
wire [ 3:0] fifo_ffcr;
////////////////////
// lifo //
////////////////////
wire lifo_en ;
wire lifo_wr ;
wire [ 7:0] lifo_addr;
wire lifo_clrq;
wire [ 7:0] lifo_data;
wire [ 7:0] lifo_rdat;
wire [ 3:0] lifo_lfcr;
////////////////////
// master //
////////////////////
wire master_en ;
wire master_dlki;
wire master_sdai;
wire master_tr ;
wire master_ack ;
wire master_st ;
wire master_rs ;
wire master_sp ;
wire master_dlk ;
wire [ 7:0] master_tdat;
wire master_empt;
wire master_spme;
wire [ 3:0] master_rmit;
wire master_ackc;
wire [ 7:0] master_brh ;
wire [ 7:0] master_brl ;
wire master_bsy ;
wire master_dlko;
wire master_sdao;
wire [ 7:0] master_rdat;
wire [ 7:0] master_shf ;
wire master_ino ;
wire [ 3:0] master_bc ;
wire master_acke;
wire master_rmiti;
wire master_ffrd;
wire master_lfwr;
wire master_tran_dne;
wire master_recv_dne;
////////////////////
// slave //
////////////////////
wire slave_en ;
wire slave_timeo;
wire slave_arhol;
wire [ 9:0] slave_addr ;
wire [ 7:0] slave_tdat ;
wire slave_scli ;
wire slave_sdai ;
wire slave_tr ;
wire slave_bsy ;
wire [ 7:0] slave_rdat ;
wire slave_sclo ;
wire slave_sdao ;
wire slave_reset;
wire [ 7:0] slave_shf ;
wire slave_ino ;
wire [ 3:0] slave_bc ;
wire slave_ffrd ;
wire slave_lfwr ;
wire slave_tran_dne;
wire slave_recv_dne;
assign en = enar[0];
assign {ms,tr} = modr[1:0];
assign ack = ackr[0];
assign {st,rs,sp} = ctlr[2:0];
assign psc = pscr[3:0];
assign brh = brhr;
assign brl = brlr;
assign {nfs,spme,ale,rmite,tmoe} = funcr[6:0];
assign tmo = tmor;
assign rmit = rmitr[3:0];
assign addr = addrr[9:0];
assign arhol = addrr[15];
assign tkey = tdatr[31:8];
assign tdat = tdatr[7:0];
assign {qemie,resetie,rmitie,recvie,tranie} = ier[4:0];
assign {fquec,qflc} = clrr[7:6];
assign {qemc,lquec,tmoc,ackc,malc,salc} = clrr[4:0];
assign rla = rlar[3:0];
////////////////////
// noisefter //
////////////////////
assign noisefter_en = en ;
assign noisefter_nfs = nfs;
assign noisefter_scl_sgi = scl;
assign noisefter_sda_sgi = sda;
noisefter noisefter_scl
(
.clk (clk ),
.rst_n(rst_n ),
.en (noisefter_en ),
.nfs (noisefter_nfs ),
.sgi (noisefter_scl_sgi),
.sgo (noisefter_scl_sgo)
);
noisefter noisefter_sda
(
.clk (clk ),
.rst_n(rst_n ),
.en (noisefter_en ),
.nfs (noisefter_nfs ),
.sgi (noisefter_sda_sgi),
.sgo (noisefter_sda_sgo)
);
////////////////////
// bbsy //
////////////////////
assign bbsy_en = en ;
assign bbsy_scli = scl;
assign bbsy_sdai = sda;
assign bbsy_sclo = master_dlko;
assign bbsy_sdao = master_sdao;
assign bbsy_ms = ms ;
bbsy bbsy_01
(
.clk (clk ),
.rst_n(rst_n ),
.en (bbsy_en ),
.scli (bbsy_scli),
.sdai (bbsy_sdai),
.sclo (bbsy_sclo),
.sdao (bbsy_sdao),
.ms (bbsy_ms ),
.bbsy (bbsy_bbsy),
.gbsy (bbsy_gbsy)
);
////////////////////
// arbitration //
////////////////////
assign arbitration_en = en && ale ;
assign arbitration_bbsy = bbsy_bbsy ;
assign arbitration_gbsy = bbsy_gbsy ;
assign arbitration_sda = sda ;
assign arbitration_msdao = master_sdao;
assign arbitration_ssdao = slave_sdao ;
assign arbitration_ms = ms ;
assign arbitration_st = st || rs ;
assign arbitration_ino = ino ;
assign arbitration_malc = malc ;
assign arbitration_salc = salc ;
arbitration arbitration_01
(
.clk (clk ),
.rst_n(rst_n ),
.en (arbitration_en ),
.bbsy (arbitration_bbsy ),
.gbsy (arbitration_gbsy ),
.sda (arbitration_sda ),
.msdao(arbitration_msdao),
.ssdao(arbitration_ssdao),
.ms (arbitration_ms ),
.st (arbitration_st ),
.ino (arbitration_ino ),
.malc (arbitration_malc ),
.salc (arbitration_salc ),
.male (arbitration_male ),
.sale (arbitration_sale )
);
////////////////////
// prescaler //
////////////////////
assign prescaler_en = en ;
assign prescaler_psc = psc;
prescaler prescaler_01
(
.clk (clk ),
.rst_n(rst_n ),
.en (prescaler_en ),
.psc (prescaler_psc ),
.dlk (prescaler_dlk )
);
////////////////////
// timeout //
////////////////////
assign timeout_en = en && tmoe && (~ms);
assign timeout_scli = scli ;
assign timeout_dlk = prescaler_dlk ;
assign timeout_tmo = tmo ;
assign timeout_tmoc = tmoc ;
timeout timeout_01
(
.clk (clk ),
.rst_n(rst_n ),
.en (timeout_en ),
.scli (timeout_scli),
.dlk (timeout_dlk ),
.tmo (timeout_tmo ),
.tmoc (timeout_tmoc),
.limt (timeout_limt),
.cnt (timeout_cnt )
);
////////////////////
// fifo //
////////////////////
assign fifo_en = en;
assign fifo_rd = (ms == 1'b1) ? master_ffrd : slave_ffrd;
assign fifo_clrq = fquec;
assign fifo_clre = {qflc,2'b00};
assign fifo_tkey = tkey;
assign fifo_data = tdat;
fifo fifo_01
(
.clk (clk ),
.rst_n(rst_n ),
.en (fifo_en ),
.rd (fifo_rd ),
.clrq (fifo_clrq),
.clre (fifo_clre),
.tkey (fifo_tkey),
.data (fifo_data),
.tdat (fifo_tdat),
.err (fifo_err ),
.ffcr (fifo_ffcr)
);
////////////////////
// lifo //
////////////////////
assign lifo_en = en;
assign lifo_wr = (ms == 1'b1) ? master_lfwr : slave_lfwr;
assign lifo_addr = rla;
assign lifo_clrq = lquec;
assign lifo_data = (ms == 1'b1) ? master_rdat : slave_rdat;
lifo lifo_01
(
.clk (clk ),
.rst_n(rst_n ),
.en (lifo_en ),
.wr (lifo_wr ),
.addr (lifo_addr),
.clrq (lifo_clrq),
.data (lifo_data),
.rdat (lifo_rdat),
.lfcr (lifo_lfcr)
);
////////////////////
// master //
////////////////////
assign master_en = (arbitration_male || arbitration_sale) ? 1'b0 : en && ms;
assign master_dlki = scli;
assign master_sdai = sdai;
assign master_tr = tr;
assign master_ack = ack;
assign master_st = (ale == 1'b0) ? ctlr[2]:(ctlr[2] & (~bbsy_bbsy));
assign master_rs = (ale == 1'b0) ? ctlr[1]:(ctlr[1] & bbsy_bbsy & bbsy_gbsy);
assign master_sp = sp;
assign master_dlk = prescaler_dlk;
assign master_tdat = fifo_tdat;
assign master_empt = fifo_err[1];
assign master_spme = spme;
assign master_rmit = (rmite == 1'b1) ? rmit : 4'h0 ;
assign master_ackc = ackc;
assign master_brh = brh;
assign master_brl = brl;
master master_01
(
.clk (clk ),
.rst_n (rst_n ),
.en (master_en ),
.scli (master_dlki ),
.sdai (master_sdai ),
.tr (master_tr ),
.ack (master_ack ),
.st (master_st ),
.rs (master_rs ),
.sp (master_sp ),
.dlk (master_dlk ),
.tdat (master_tdat ),
.empt (master_empt ),
.spme (master_spme ),
.rmit (master_rmit ),
.ackc (master_ackc ),
.brh (master_brh ),
.brl (master_brl ),
.bsy (master_bsy ),
.sclo (master_dlko ),
.sdao (master_sdao ),
.rdat (master_rdat ),
.shf (master_shf ),
.ino (master_ino ),
.bc (master_bc ),
.acke (master_acke ),
.rmiti (master_rmiti ),
.ffrd (master_ffrd ),
.lfwr (master_lfwr ),
.tran_dne(master_tran_dne),
.recv_dne(master_recv_dne)
);
////////////////////
// slave //
////////////////////
assign slave_en = (arbitration_male || arbitration_sale) ? 1'b1:en && (~ms);
assign slave_timeo = timeout_limt;
assign slave_arhol = arhol;
assign slave_addr = addr;
assign slave_tdat = fifo_tdat;
assign slave_scli = scli;
assign slave_sdai = sdai;
slave slave_01
(
.clk (clk ),
.rst_n (rst_n ),
.en (slave_en ),
.timeo (slave_timeo ),
.tr (slave_tr ),
.arhol (slave_arhol ),
.addr (slave_addr ),
.tdat (slave_tdat ),
.scli (slave_scli ),
.sdai (slave_sdai ),
.bsy (slave_bsy ),
.rdat (slave_rdat ),
.sclo (slave_sclo ),
.sdao (slave_sdao ),
.reset (slave_reset ),
.shf (slave_shf ),
.ino (slave_ino ),
.bc (slave_bc ),
.ffrd (slave_ffrd ),
.lfwr (slave_lfwr ),
.tran_dne(slave_tran_dne),
.recv_dne(slave_recv_dne)
);
////////////////////
// inout port //
////////////////////
assign sclo = (ms == 1'b1) ? master_dlko : slave_sclo;
assign sdao = (ms == 1'b1) ? master_sdao : slave_sdao;
assign scli = (ms == 1'b0) ? noisefter_scl_sgo : 1'b1;
assign sdai = (ino == 1'b1) ? noisefter_sda_sgo : 1'b1;
assign scl = ((ms == 1'b1) && (sclo == 1'b0) && (oe == 1'b1)) ? 1'b0 : 1'bz;
assign sda = ((ino == 1'b0) && (sdao == 1'b0) && (oe == 1'b1)) ? 1'b0 : 1'bz;
////////////////////
////////////////////
// pre output //
////////////////////
assign rdat = lifo_rdat;
assign ino = (ms == 1'b1) ? master_ino : slave_ino;
assign bbsy = bbsy_bbsy;
assign gbsy = bbsy_gbsy;
assign bsy = (ms == 1'b1) ? master_bsy : slave_bsy;
assign shf = (ms == 1'b1) ? master_shf : slave_shf;
assign bc = (ms == 1'b1) ? master_bc : slave_bc;
assign reseti = ((resetie == 1'b1) && (ms == 1'b0)) ? slave_reset : 1'b0;
assign qemi = (qemie == 1'b1) ? fifo_err[1] : 1'b0;
assign rmiti = (rmitie) ? master_rmiti : 1'b0 ;
assign recvi = (recvie) ? ((ms) ? master_recv_dne : slave_recv_dne) : 1'b0;
assign trani = (tranie) ? ((ms) ? master_tran_dne : slave_tran_dne) : 1'b0;
assign qfle = fifo_err[2];
assign timoe = timeout_limt;
assign acke = master_acke;
assign male = arbitration_male;
assign sale = arbitration_sale;
assign oe = ((ale == 1'b0) || (ms == 1'b0)) ?
1'b1 : (~bbsy_bbsy || (bbsy_bbsy & bbsy_gbsy));
////////////////////
////////////////////
// output signal //
////////////////////
assign rdatr = rdat;
assign sttr = {ino,sclo,sdao,scli,sdai,bbsy,gbsy,bsy};
assign shfr = shf[7:0];
assign bcr = {4'h0,bc[3:0]};
assign isr = {3'b000,qemi,reseti,rmiti,recvi,trani};
assign err = {1'b0,qfle,2'b00,timoe,acke,male,sale};
assign ffcr = fifo_ffcr;
assign lfcr = lifo_lfcr;
endmodule
module giic
(
// AMBA APB
PCLK ,
PRESETn,
PADDR ,
PWRITE ,
PSEL ,
PENABLE,
PSTRB ,
PWDATA ,
PRDATA ,
PREADY ,
PSLVERR,
// INTERRUPT
qemi ,
reseti ,
rmiti ,
recvi ,
trani ,
// IO
scl,
sda
);
// AMBA APB
input PCLK ;
input PRESETn;
input [ 7:0] PADDR ;
input PWRITE ;
input PSEL ;
input PENABLE;
input [ 3:0] PSTRB ;
input [31:0] PWDATA ;
output [31:0] PRDATA ;
output PREADY ;
output PSLVERR;
// INTERRUPT
output qemi ;
output reseti ;
output rmiti ;
output recvi ;
output trani ;
// IO
inout scl ;
inout sda ;
////////////////////
// APB signal //
////////////////////
// in
wire apbif_PCLK ;
wire apbif_PRESETn;
wire [ 7:0] apbif_PADDR ;
wire apbif_PWRITE ;
wire apbif_PSEL ;
wire apbif_PENABLE;
wire [ 3:0] apbif_PSTRB ;
wire [31:0] apbif_PWDATA ;
// out
wire [31:0] apbif_PRDATA ;
wire apbif_PREADY ;
wire apbif_PSLVERR;
// in
wire [ 7:0] apbif_rdatr ;
wire [ 7:0] apbif_sttr ;
wire [ 7:0] apbif_shfr ;
wire [ 7:0] apbif_bcr ;
wire [ 7:0] apbif_isr ;
wire [ 7:0] apbif_err ;
wire [ 7:0] apbif_ffcr ;
wire [ 7:0] apbif_lfcr ;
// out
wire [31:0] apbif_enar ;
wire [ 7:0] apbif_modr ;
wire [ 7:0] apbif_ackr ;
wire [ 7:0] apbif_ctlr ;
wire [ 7:0] apbif_pscr ;
wire [ 7:0] apbif_brhr ;
wire [ 7:0] apbif_brlr ;
wire [ 7:0] apbif_funcr ;
wire [15:0] apbif_tmor ;
wire [ 7:0] apbif_rmitr ;
wire [15:0] apbif_addrr ;
wire [31:0] apbif_tdatr ;
wire [ 7:0] apbif_ier ;
wire [ 7:0] apbif_clrr ;
wire [ 7:0] apbif_rlar ;
////////////////////
// iic signal //
////////////////////
// in
wire iic_clk ;
wire iic_rst_n;
wire [31:0] iic_enar ;
wire [ 7:0] iic_modr ;
wire [ 7:0] iic_ackr ;
wire [ 7:0] iic_ctlr ;
wire [ 7:0] iic_pscr ;
wire [ 7:0] iic_brhr ;
wire [ 7:0] iic_brlr ;
wire [ 7:0] iic_funcr;
wire [15:0] iic_tmor ;
wire [ 7:0] iic_rmitr;
wire [15:0] iic_addrr;
wire [31:0] iic_tdatr;
wire [ 7:0] iic_ier ;
wire [ 7:0] iic_clrr ;
wire [ 7:0] iic_rlar ;
// out
wire [ 7:0] iic_rdatr;
wire [ 7:0] iic_sttr ;
wire [ 7:0] iic_shfr ;
wire [ 7:0] iic_bcr ;
wire [ 7:0] iic_isr ;
wire [ 7:0] iic_err ;
wire [ 7:0] iic_ffcr ;
wire [ 7:0] iic_lfcr ;
// connect signal APBIF <-> iic
// input -> APB in
assign apbif_PCLK = PCLK ;
assign apbif_PRESETn = PRESETn;
assign apbif_PADDR = PADDR ;
assign apbif_PWRITE = PWRITE ;
assign apbif_PSEL = PSEL ;
assign apbif_PENABLE = PENABLE;
assign apbif_PSTRB = PSTRB ;
assign apbif_PWDATA = PWDATA ;
// APB out -> output
assign PRDATA = apbif_PRDATA ;
assign PREADY = apbif_PREADY ;
assign PSLVERR = apbif_PSLVERR;
// APB out -> iic in
assign iic_clk = PCLK ;
assign iic_rst_n = PRESETn ;
assign iic_enar = apbif_enar ;
assign iic_modr = apbif_modr ;
assign iic_ackr = apbif_ackr ;
assign iic_ctlr = apbif_ctlr ;
assign iic_pscr = apbif_pscr ;
assign iic_brhr = apbif_brhr ;
assign iic_brlr = apbif_brlr ;
assign iic_funcr = apbif_funcr;
assign iic_tmor = apbif_tmor ;
assign iic_rmitr = apbif_rmitr;
assign iic_addrr = apbif_addrr;
assign iic_tdatr = apbif_tdatr;
assign iic_ier = apbif_ier ;
assign iic_clrr = apbif_clrr ;
assign iic_rlar = apbif_rlar ;
// iic out -> APB in
assign apbif_rdatr = iic_rdatr;
assign apbif_sttr = iic_sttr ;
assign apbif_shfr = iic_shfr ;
assign apbif_bcr = iic_bcr ;
assign apbif_isr = iic_isr ;
assign apbif_err = iic_err ;
assign apbif_ffcr = iic_ffcr ;
assign apbif_lfcr = iic_lfcr ;
////////////////////
// APB IF //
////////////////////
apbif apbif_01
(
.PCLK (apbif_PCLK ),
.PRESETn (apbif_PRESETn),
.PADDR (apbif_PADDR ),
.PWRITE (apbif_PWRITE ),
.PSEL (apbif_PSEL ),
.PENABLE (apbif_PENABLE),
.PSTRB (apbif_PSTRB ),
.PWDATA (apbif_PWDATA ),
.PRDATA (apbif_PRDATA ),
.PREADY (apbif_PREADY ),
.PSLVERR (apbif_PSLVERR),
.rdatr (apbif_rdatr ),
.sttr (apbif_sttr ),
.shfr (apbif_shfr ),
.bcr (apbif_bcr ),
.isr (apbif_isr ),
.err (apbif_err ),
.ffcr (apbif_ffcr ),
.lfcr (apbif_lfcr ),
.enar (apbif_enar ),
.modr (apbif_modr ),
.ackr (apbif_ackr ),
.ctlr (apbif_ctlr ),
.pscr (apbif_pscr ),
.brhr (apbif_brhr ),
.brlr (apbif_brlr ),
.funcr (apbif_funcr ),
.tmor (apbif_tmor ),
.rmitr (apbif_rmitr ),
.addrr (apbif_addrr ),
.tdatr (apbif_tdatr ),
.ier (apbif_ier ),
.clrr (apbif_clrr ),
.rlar (apbif_rlar )
);
////////////////////
// IIC CORE //
////////////////////
iic iic_01
(
.clk (iic_clk ),
.rst_n(iic_rst_n),
.enar (iic_enar ),
.modr (iic_modr ),
.ackr (iic_ackr ),
.ctlr (iic_ctlr ),
.pscr (iic_pscr ),
.brhr (iic_brhr ),
.brlr (iic_brlr ),
.funcr(iic_funcr),
.tmor (iic_tmor ),
.rmitr(iic_rmitr),
.addrr(iic_addrr),
.tdatr(iic_tdatr),
.ier (iic_ier ),
.clrr (iic_clrr ),
.rlar (iic_rlar ),
.rdatr(iic_rdatr),
.sttr (iic_sttr ),
.shfr (iic_shfr ),
.bcr (iic_bcr ),
.isr (iic_isr ),
.err (iic_err ),
.ffcr (iic_ffcr ),
.lfcr (iic_lfcr ),
.scl (scl ),
.sda (sda )
);
////////////////////
// ISR CORE //
////////////////////
assign qemi = iic_isr[4];
assign reseti = iic_isr[3];
assign rmiti = iic_isr[2];
assign recvi = iic_isr[1];
assign trani = iic_isr[0];
endmodule
Đăng ký:
Bài đăng (Atom)