2011年2月27日 星期日
ENERGY GLOBE World Award
1. ENERGY GLOBE World Award
http://www.energyglobe.com/en/award/latest-winners/nominierte-world-awards/air/
http://www.energyglobe.com/en/award/latest-winners/nominierte-world-awards/air/
[ some interesting projects]
2010年5月6日 星期四
[Digest] 打造綠建築的5個關鍵技術
工業技術與資訊 2010/05/06
http://mag.udn.com/mag/newsstand/storypage.jsp?f_MAIN_ID=77&f_SUB_ID=4319&f_ART_ID=246618
綠建築的九大指標:生物多樣化、綠化量、基地保水、日常節能、二氧化碳減量、廢棄物減量、水資源、污水與垃圾改善、室內健康與環境。
技術1:高透光太陽能窗發電模組
技術2:晝光導光板
技術3:Smart window(可調光液晶玻璃)
技術4:軟性電致變色製程/軟性節能膜技術
技術5:REDDEX(防火材料)
http://mag.udn.com/mag/newsstand/storypage.jsp?f_MAIN_ID=77&f_SUB_ID=4319&f_ART_ID=246618
綠建築的九大指標:生物多樣化、綠化量、基地保水、日常節能、二氧化碳減量、廢棄物減量、水資源、污水與垃圾改善、室內健康與環境。
技術1:高透光太陽能窗發電模組
技術2:晝光導光板
技術3:Smart window(可調光液晶玻璃)
技術4:軟性電致變色製程/軟性節能膜技術
技術5:REDDEX(防火材料)
2009年9月10日 星期四
是軟體、還是硬體設計?SW programmability of FPGA
2009-09-10
關於FPGA的SOC化,一直是話題不斷,尤其是FPGA Vendors老是鼓吹ASIC設計終將被FPGA超越。的確,因研發成本、設計生產力(軟硬體)、工具等無法趕上先進製程的腳步,使得SOC的投入成本 高不可攀且回收風險充滿了不確定。未來的SOC,是否真的只有少數人能入場,其他人就只能停在成熟製程技術(據說經濟風暴已使得2nd tier foundry fab 產能滿載)或是靠向FPGA。雖然,直到今日FPGA仍然在cost, power, performance等因素上苦苦追趕主流SOC,當然所謂cost並不以單一售價來計算,FPGA仍有其優勢,尤其是非主流的小量開發。我看到也有一 些new startup,希望能做出GHz 的FPGA,可惜恐怕敵不過冰風暴。另外,如Atmel則推出hard core CPU+FPGA array, 客戶可以較低投入成本來設計ASIC。
EEtimes有一篇文章,作者把SOC做了如下的類分;並給了一個術語,所謂Software Programmable Integrated Circuits。
>> pure porcessor(multi-core)
>> processor+HW accelerators
>> SOC+FPGA companion
>> FPGA+HW accelerators
>> pure FPGA SOC
所 謂的Software Programmable指的是系統設計技術的變革,ESL?,傳統上所謂HW accelerators是指掛載於SOC bus 上之週邊,是獨立於processor之外的模組,這種設計方法需要做軟硬界面劃分,硬體實現大都使用RTL,軟體則以C語言為主。一般而言,如果不用現 成IP,會非常耗時。作者做了一個類比,說RTL設計相當於組合語言的等級,也就是說那是石器時代的技術了。有一種技術,類似於customized processor design, user定義功能、運算法則,比方用C語言, 工具自動生成對應的新指令及所需的HW accelerators,這將大大改變所謂SOC的設計方法。
目前已經有一些公司在推廣這一類的工具了。影響所及,未來業界將不需要那麼多硬體工程師。今天的硬體(或系統)工程師未來可能只要使用C語言即可,就像今日只有極少數的軟體工程師會用組合語言一樣。
當然,FPGA Vendors面臨的挑戰之一是當FPGA越來越大越複雜,在應用面,如何幫助User快速上手,或擴大User的domain base,使今日的軟體工程師或實驗室裡的科學家(量測,大量資料快速運算)或其他領域的工程師,都能利用FPGA的優點。 我注意到National Instrument 已經推出相對應的產品,號稱不用 HDL/RTL,即可做出所需硬體功能。 沒親身體驗過,細節不詳,但NI工具似乎皆以GUI設計,果如此將是一大變革。
看來,未來不論是SOC 或 FPGA User 皆需要好的軟體工具及平台,幫助他們快速、便利地完成工作。
關於FPGA的SOC化,一直是話題不斷,尤其是FPGA Vendors老是鼓吹ASIC設計終將被FPGA超越。的確,因研發成本、設計生產力(軟硬體)、工具等無法趕上先進製程的腳步,使得SOC的投入成本 高不可攀且回收風險充滿了不確定。未來的SOC,是否真的只有少數人能入場,其他人就只能停在成熟製程技術(據說經濟風暴已使得2nd tier foundry fab 產能滿載)或是靠向FPGA。雖然,直到今日FPGA仍然在cost, power, performance等因素上苦苦追趕主流SOC,當然所謂cost並不以單一售價來計算,FPGA仍有其優勢,尤其是非主流的小量開發。我看到也有一 些new startup,希望能做出GHz 的FPGA,可惜恐怕敵不過冰風暴。另外,如Atmel則推出hard core CPU+FPGA array, 客戶可以較低投入成本來設計ASIC。
EEtimes有一篇文章,作者把SOC做了如下的類分;並給了一個術語,所謂Software Programmable Integrated Circuits。
>> pure porcessor(multi-core)
>> processor+HW accelerators
>> SOC+FPGA companion
>> FPGA+HW accelerators
>> pure FPGA SOC
所 謂的Software Programmable指的是系統設計技術的變革,ESL?,傳統上所謂HW accelerators是指掛載於SOC bus 上之週邊,是獨立於processor之外的模組,這種設計方法需要做軟硬界面劃分,硬體實現大都使用RTL,軟體則以C語言為主。一般而言,如果不用現 成IP,會非常耗時。作者做了一個類比,說RTL設計相當於組合語言的等級,也就是說那是石器時代的技術了。有一種技術,類似於customized processor design, user定義功能、運算法則,比方用C語言, 工具自動生成對應的新指令及所需的HW accelerators,這將大大改變所謂SOC的設計方法。
目前已經有一些公司在推廣這一類的工具了。影響所及,未來業界將不需要那麼多硬體工程師。今天的硬體(或系統)工程師未來可能只要使用C語言即可,就像今日只有極少數的軟體工程師會用組合語言一樣。
當然,FPGA Vendors面臨的挑戰之一是當FPGA越來越大越複雜,在應用面,如何幫助User快速上手,或擴大User的domain base,使今日的軟體工程師或實驗室裡的科學家(量測,大量資料快速運算)或其他領域的工程師,都能利用FPGA的優點。 我注意到National Instrument 已經推出相對應的產品,號稱不用 HDL/RTL,即可做出所需硬體功能。 沒親身體驗過,細節不詳,但NI工具似乎皆以GUI設計,果如此將是一大變革。
看來,未來不論是SOC 或 FPGA User 皆需要好的軟體工具及平台,幫助他們快速、便利地完成工作。
2009年7月9日 星期四
Measurment Accuracy and Precision
2009-07-09
所謂 Accuracy and Precision 中文議成準確度與精確度,卻很難望文生義。
參考維基百科,http://en.wikipedia.org/wiki/Accuracy_and_precision,以圖說明較為清楚。
文字可翻譯為:Accuracy 指與true value接近之程度;Precision 指量測之可重複(製)性。似乎仍不清楚,沒關係,看統計圖說,量測值分佈之平均值與true value之差距表示Accuracy ;而Precision 則是該分佈之偏差(deviation) 。
另以打靶來比喻,比如說射擊1000發子彈後,觀察其子彈分佈,有幾種可能:
1. accurate and precise: 命中點集中在紅心附近,且集中
2. accurate but not precise: 命中點集中在紅心附近,但分散
3. not accurate but precise: 命中點偏離紅心,且集中
4. not accurate and not precise: 命中點偏離紅心,且分散
故好的量測需要 accurate and precise。即不要有bias,且隨機性愈小愈好。
DMM規格
==Display Count(與resolution有關)
*3-3/4 digits, 6000 counts, (此地3/4指5, 0-000~5-999)
*4-1/2 digits, 20,000 counts(0-0000~1-9999)
==Accuracy
*±(0.3% + 1) Fluke 77 IV
*±(0.05%+1) Fluke 87 V
(此處±1 位可視為隨機量,%是相對於滿刻度,故訊號遠小於滿刻度時,accuracy將變差,且大檔位,如200V vs 20V,其誤差絕對值將變大)
實務上,我們會關心accuracy,卻不一定重視precision。
所謂 Accuracy and Precision 中文議成準確度與精確度,卻很難望文生義。
參考維基百科,http://en.wikipedia.org/wiki/Accuracy_and_precision,以圖說明較為清楚。
文字可翻譯為:Accuracy 指與true value接近之程度;Precision 指量測之可重複(製)性。似乎仍不清楚,沒關係,看統計圖說,量測值分佈之平均值與true value之差距表示Accuracy ;而Precision 則是該分佈之偏差(deviation) 。
另以打靶來比喻,比如說射擊1000發子彈後,觀察其子彈分佈,有幾種可能:
1. accurate and precise: 命中點集中在紅心附近,且集中
2. accurate but not precise: 命中點集中在紅心附近,但分散
3. not accurate but precise: 命中點偏離紅心,且集中
4. not accurate and not precise: 命中點偏離紅心,且分散
故好的量測需要 accurate and precise。即不要有bias,且隨機性愈小愈好。
DMM規格
==Display Count(與resolution有關)
*3-3/4 digits, 6000 counts, (此地3/4指5, 0-000~5-999)
*4-1/2 digits, 20,000 counts(0-0000~1-9999)
==Accuracy
*±(0.3% + 1) Fluke 77 IV
*±(0.05%+1) Fluke 87 V
(此處±1 位可視為隨機量,%是相對於滿刻度,故訊號遠小於滿刻度時,accuracy將變差,且大檔位,如200V vs 20V,其誤差絕對值將變大)
實務上,我們會關心accuracy,卻不一定重視precision。
2009年6月15日 星期一
I2C Slave
2009-06-15
/*
modified I2C salve design from
http://www.fpga4fun.com/I2C_2.html
1. Asynchronous design: ASIC or FPGA design option
2. 8 bits CSR RW interface: 0~15, address and control
3. PAD not included
4. Altera CPLD verified
RTL model
Module: i2c_salve, a I2C slave device which only supports sdt mode
Ref spec: Rev 03, 2007
This module is from www.fpga4fun.com
SDA HOLD TIME: ref NXP's spec.
A device must internally provide a hold time of at least 300 ns for the SDA signal (with respect to the
VIH(min) of the SCL signal) to bridge the undefined region of the falling edge of SCL.
*/
`timescale 1ns/10ps
`define D #1
module i2c_slave (porn, SCL, SDAin, SDA_OUT, i2c_writing, i2c_debug, csr_din, csr_dout, i2c_data_ptr, i2c_wr, rstn);
parameter I2C_ADR = 7'h27;
input porn;
input SCL;
input SDAin;
input [7:0] csr_dout;
input rstn;
output SDA_OUT;
output i2c_writing;
output [7:0] i2c_debug;
output [7:0] csr_din;
output [4:0] i2c_data_ptr;
output i2c_wr;
reg [4:0] i2c_data_ptr; // address pointer
reg incycle;
wire I2C_rstn, incycle_rstn, i2c_writing_i;
// Delay Line Here, this has to be taken care by manual
`ifdef FPGA // FPGA
wire SDA_in_d;
assign #300 SDA_in_d = SDAin;
/*
I2C start and stop conditions detection logic
That's the "black magic" part of this design...
We use two wires with a combinatorial loop
to detect the start and stop conditions
making sure these two wires don't get optimized away
*/
wire SDA_shadow /* synthesis keep = 1 */; // FPGA directive
wire start_or_stop /* synthesis keep = 1 */; // FPGA directive
assign #5 SDA_shadow =
(!porn) ? 1'b1 : (~SCL | start_or_stop) ? SDA_in_d : SDA_shadow;
assign start_or_stop =
~SCL? 1'b0 : (SDA_in_d ^ SDA_shadow);
`else // ASIC
i2c_line_det U_i2c_line_det
(.porn(porn), .SDAin(SDAin), .SDA_in_d(SDA_in_d), .SCL(SCL), .start_or_stop(start_or_stop));
`endif
// I2C reset, pure async, note: I2C is not a always-running clock.
assign I2C_rstn = porn & rstn & ~start_or_stop;
// incycle: starting from 1st neg SCL
always @(negedge SCL or negedge I2C_rstn)
if(!I2C_rstn)
incycle <= `D 1'b0; // either S or P or Sr
else if(~SDA_in_d) // detection bits sequence following start bit
incycle <= `D 1'b1;
// Now we are ready to count the I2C bits coming in
reg [3:0] bitcnt;// counts the I2C bits from 7 downto 0, plus an ACK bit
wire bit_DATA = ~bitcnt[3];// the DATA bits are the first 8 bits sent
wire bit_ACK = bitcnt[3]; // the ACK bit is the 9th bit sent
reg data_phase;
always @(negedge SCL or negedge I2C_rstn)
if(!I2C_rstn)
begin
bitcnt <= `D 4'h7; // the bit 7 is received first
data_phase <= `D 0;
end
else
begin
if(bit_ACK)
begin
bitcnt <= `D 4'h7; // reset to 0111 after 1000
data_phase <= `D 1; // 1st bit_ACK followed by data phase
end
else if (incycle)
bitcnt <= `D bitcnt - 4'h1;
end
// and detect if the I2C address matches our own
wire adr_phase = ~data_phase;
reg adr_match, op_read, got_ACK;
reg SDAr, i2c_writing;
// sample SDA on posedge since the I2C spec
// specifies as low as 0us hold-time on negedge
always @(posedge SCL) SDAr<=SDA_in_d;
reg [7:0] mem;
wire op_write = ~op_read;
always @(negedge SCL or negedge I2C_rstn)
if(!I2C_rstn) begin
got_ACK <= 0;
adr_match <= 1;
op_read <= 0;
i2c_data_ptr <= 0;
i2c_writing <= 0; // to aviod combi glitch
end
else if (incycle) begin // only active while incycle
if((adr_phase & bitcnt==7) && (SDAr!=I2C_ADR[6])) adr_match<=0;
if((adr_phase & bitcnt==6) && (SDAr!=I2C_ADR[5])) adr_match<=0;
if((adr_phase & bitcnt==5) && (SDAr!=I2C_ADR[4])) adr_match<=0;
if((adr_phase & bitcnt==4) && (SDAr!=I2C_ADR[3])) adr_match<=0;
if((adr_phase & bitcnt==3) && (SDAr!=I2C_ADR[2])) adr_match<=0;
if((adr_phase & bitcnt==2) && (SDAr!=I2C_ADR[1])) adr_match<=0;
if((adr_phase & bitcnt==1) && (SDAr!=I2C_ADR[0])) adr_match<=0;
if(adr_phase & bitcnt==0) op_read <= SDAr;
/* we monitor the ACK to be able to free the bus
when the master doesn't ACK during a read operation
HOST will send NACK prior to STOP according to spec.
*/
if(bit_ACK) got_ACK <= ~SDAr;
// shift register write
if((adr_match) & bit_DATA & data_phase & op_write)
mem[bitcnt] <= SDAr;
// inc ptr after add phase
if((adr_match) & bit_ACK & data_phase )
i2c_data_ptr <= i2c_data_ptr + 1;
i2c_writing <= i2c_writing_i;
end
assign i2c_wr = adr_match & data_phase & op_write & bit_ACK;
// changed to SCL sync design
assign csr_din = mem;
// and drive the SDA line when necessary.
wire data_bit_low = ~csr_dout[bitcnt[2:0]];
wire SDA_assert_low =
adr_match & bit_DATA & data_phase & op_read & data_bit_low & got_ACK;
wire SDA_assert_ACK = (adr_match ) & bit_ACK & (adr_phase | op_write);
wire SDA_low = SDA_assert_low | SDA_assert_ACK;
assign SDA_OUT = SDA_low;
// PAD Implementation
// assign SDA = SDA_low ? 1'b0 : 1'bz;
assign i2c_writing_i = adr_match & data_phase & op_write & incycle;
// ref spec section, I2C interface. i2c_writing will go back to standby.
assign i2c_debug = {bitcnt[3:0], 2'b00, op_read, start_or_stop};
endmodule
module i2c_line_det ( SDAin, SDA_in_d, SCL, start_or_stop, porn );
input SDAin, SCL, porn;
output SDA_in_d, start_or_stop;
wire SDA_shadow, n2, n3;
wire n2d, n2d1, n2d2, n2dd;
`ifdef _RTL // for RTL sim only, since w/o delay in gate lib
assign #10 SDA_in_d = SDAin;
assign #5 SDA_shadow = (!porn) ? 1'b1 : (~SCL | start_or_stop) ? SDA_in_d : SDA_shadow;
assign start_or_stop = ~SCL? 1'b0 : (SDA_in_d ^ SDA_shadow);
`else
DEL5 U11 ( .A(SDAin), .Y(SDA_in_d1) );
DEL5 U12 ( .A(SDA_in_d1), .Y(SDA_in_d2));
DEL5 U13 ( .A(SDA_in_d2), .Y(SDA_in_d));
// latch with active low preset
LATCH_1X SDA_shadow_reg ( .PRSTN(porn), .D(SDA_in_d), .EN(n3), .Q(SDA_shadow) );
INV_1X U9 (.A(SCL), .Y(SLCn));
NAND2_1X U10 ( .A(SCLn), .B(n2), .Y(start_or_stop) );
// to keep minimum pulse width
DEL5 U1 (.A(n2), .Y(n2d));
BUF1 U2 (.A(n2d), .Y(n2d1));
BUF1 U3 (.A(n2d1), .Y(n2d2));
BUF1 U4 (.A(n2d2), .Y(n2d3));
BUF1 U5 (.A(n2d3), .Y(n2d4));
BUF1 U6 (.A(n2d4), .Y(n2dd));
//
AND2_1X U7 ( .A(n2dd), .B(SCL), .Y(n3) );
NOR2_1X U8 ( .A(SDA_in_d), .B(SDA_shadow), .Y(n2) );
`endif
endmodule
module LATCH_1X(PRSTN, D, EN, Q);
input PRSTN, D, EN;
output Q;
udp_ldlatch_p0 P1 (.q(Q), .d(D), .en(EN), .clear(1'b1), .preset(PRSTN));
endmodule
primitive udp_ldlatch_p0(q, d, en, clear, preset);
output q;
input d, en, clear, preset;
reg q;
table
// d en clear preset : state : q
? ? 0 ? : ? : 0;// clear to 0
? ? 1 0 : ? : 1;// preset to 1
0 1 1 1 : ? : 0;// on enable, transmit d
1 1 1 1 : ? : 1;// on enable, transmit d
? 0 1 1 : ? : -;// not enable, no change
? ? p 1 : ? : -;// ignore positive edge of clear
? ? 1 p : ? : -;// ignore positive edge of preset
endtable
endprimitive
module NOR2_1X (A, B, Y);
input A, B;
output Y;
assign #1 Y=!(A | B);
endmodule
module NAND2_1X (A, B, Y);
input A, B;
output Y;
assign #1 Y=!(A & B);
endmodule
module AND2_1X (A, B, Y);
input A, B;
output Y;
assign #1 Y=A &B;
endmodule
module INV_1X (A, Y);
input A;
output Y;
assign #1 Y=!A;
endmodule
module BUF1 (A, Y);
input A;
output Y;
assign #1 Y=A;
endmodule
module DEL5(A, Y);
input A;
output Y;
assign #5 Y= A;
endmodule
// CSR example
//
// write enable
assign csr_wr = i2c_wr;
assign csr_w_add = i2c_data_ptr;
assign csr_clk = SCL;
assign wr_csr00 = csr_wr & (csr_w_add == 5'h0);
// CSR00
always @(negedge porn or posedge csr_clk)
if (!porn)
csr00 <= `D cr00_iv;
else if (wr_csr00)
csr00 <= `D csr_din;
/*
modified I2C salve design from
http://www.fpga4fun.com/I2C_2.html
1. Asynchronous design: ASIC or FPGA design option
2. 8 bits CSR RW interface: 0~15, address and control
3. PAD not included
4. Altera CPLD verified
RTL model
Module: i2c_salve, a I2C slave device which only supports sdt mode
Ref spec: Rev 03, 2007
This module is from www.fpga4fun.com
SDA HOLD TIME: ref NXP's spec.
A device must internally provide a hold time of at least 300 ns for the SDA signal (with respect to the
VIH(min) of the SCL signal) to bridge the undefined region of the falling edge of SCL.
*/
`timescale 1ns/10ps
`define D #1
module i2c_slave (porn, SCL, SDAin, SDA_OUT, i2c_writing, i2c_debug, csr_din, csr_dout, i2c_data_ptr, i2c_wr, rstn);
parameter I2C_ADR = 7'h27;
input porn;
input SCL;
input SDAin;
input [7:0] csr_dout;
input rstn;
output SDA_OUT;
output i2c_writing;
output [7:0] i2c_debug;
output [7:0] csr_din;
output [4:0] i2c_data_ptr;
output i2c_wr;
reg [4:0] i2c_data_ptr; // address pointer
reg incycle;
wire I2C_rstn, incycle_rstn, i2c_writing_i;
// Delay Line Here, this has to be taken care by manual
`ifdef FPGA // FPGA
wire SDA_in_d;
assign #300 SDA_in_d = SDAin;
/*
I2C start and stop conditions detection logic
That's the "black magic" part of this design...
We use two wires with a combinatorial loop
to detect the start and stop conditions
making sure these two wires don't get optimized away
*/
wire SDA_shadow /* synthesis keep = 1 */; // FPGA directive
wire start_or_stop /* synthesis keep = 1 */; // FPGA directive
assign #5 SDA_shadow =
(!porn) ? 1'b1 : (~SCL | start_or_stop) ? SDA_in_d : SDA_shadow;
assign start_or_stop =
~SCL? 1'b0 : (SDA_in_d ^ SDA_shadow);
`else // ASIC
i2c_line_det U_i2c_line_det
(.porn(porn), .SDAin(SDAin), .SDA_in_d(SDA_in_d), .SCL(SCL), .start_or_stop(start_or_stop));
`endif
// I2C reset, pure async, note: I2C is not a always-running clock.
assign I2C_rstn = porn & rstn & ~start_or_stop;
// incycle: starting from 1st neg SCL
always @(negedge SCL or negedge I2C_rstn)
if(!I2C_rstn)
incycle <= `D 1'b0; // either S or P or Sr
else if(~SDA_in_d) // detection bits sequence following start bit
incycle <= `D 1'b1;
// Now we are ready to count the I2C bits coming in
reg [3:0] bitcnt;// counts the I2C bits from 7 downto 0, plus an ACK bit
wire bit_DATA = ~bitcnt[3];// the DATA bits are the first 8 bits sent
wire bit_ACK = bitcnt[3]; // the ACK bit is the 9th bit sent
reg data_phase;
always @(negedge SCL or negedge I2C_rstn)
if(!I2C_rstn)
begin
bitcnt <= `D 4'h7; // the bit 7 is received first
data_phase <= `D 0;
end
else
begin
if(bit_ACK)
begin
bitcnt <= `D 4'h7; // reset to 0111 after 1000
data_phase <= `D 1; // 1st bit_ACK followed by data phase
end
else if (incycle)
bitcnt <= `D bitcnt - 4'h1;
end
// and detect if the I2C address matches our own
wire adr_phase = ~data_phase;
reg adr_match, op_read, got_ACK;
reg SDAr, i2c_writing;
// sample SDA on posedge since the I2C spec
// specifies as low as 0us hold-time on negedge
always @(posedge SCL) SDAr<=SDA_in_d;
reg [7:0] mem;
wire op_write = ~op_read;
always @(negedge SCL or negedge I2C_rstn)
if(!I2C_rstn) begin
got_ACK <= 0;
adr_match <= 1;
op_read <= 0;
i2c_data_ptr <= 0;
i2c_writing <= 0; // to aviod combi glitch
end
else if (incycle) begin // only active while incycle
if((adr_phase & bitcnt==7) && (SDAr!=I2C_ADR[6])) adr_match<=0;
if((adr_phase & bitcnt==6) && (SDAr!=I2C_ADR[5])) adr_match<=0;
if((adr_phase & bitcnt==5) && (SDAr!=I2C_ADR[4])) adr_match<=0;
if((adr_phase & bitcnt==4) && (SDAr!=I2C_ADR[3])) adr_match<=0;
if((adr_phase & bitcnt==3) && (SDAr!=I2C_ADR[2])) adr_match<=0;
if((adr_phase & bitcnt==2) && (SDAr!=I2C_ADR[1])) adr_match<=0;
if((adr_phase & bitcnt==1) && (SDAr!=I2C_ADR[0])) adr_match<=0;
if(adr_phase & bitcnt==0) op_read <= SDAr;
/* we monitor the ACK to be able to free the bus
when the master doesn't ACK during a read operation
HOST will send NACK prior to STOP according to spec.
*/
if(bit_ACK) got_ACK <= ~SDAr;
// shift register write
if((adr_match) & bit_DATA & data_phase & op_write)
mem[bitcnt] <= SDAr;
// inc ptr after add phase
if((adr_match) & bit_ACK & data_phase )
i2c_data_ptr <= i2c_data_ptr + 1;
i2c_writing <= i2c_writing_i;
end
assign i2c_wr = adr_match & data_phase & op_write & bit_ACK;
// changed to SCL sync design
assign csr_din = mem;
// and drive the SDA line when necessary.
wire data_bit_low = ~csr_dout[bitcnt[2:0]];
wire SDA_assert_low =
adr_match & bit_DATA & data_phase & op_read & data_bit_low & got_ACK;
wire SDA_assert_ACK = (adr_match ) & bit_ACK & (adr_phase | op_write);
wire SDA_low = SDA_assert_low | SDA_assert_ACK;
assign SDA_OUT = SDA_low;
// PAD Implementation
// assign SDA = SDA_low ? 1'b0 : 1'bz;
assign i2c_writing_i = adr_match & data_phase & op_write & incycle;
// ref spec section, I2C interface. i2c_writing will go back to standby.
assign i2c_debug = {bitcnt[3:0], 2'b00, op_read, start_or_stop};
endmodule
module i2c_line_det ( SDAin, SDA_in_d, SCL, start_or_stop, porn );
input SDAin, SCL, porn;
output SDA_in_d, start_or_stop;
wire SDA_shadow, n2, n3;
wire n2d, n2d1, n2d2, n2dd;
`ifdef _RTL // for RTL sim only, since w/o delay in gate lib
assign #10 SDA_in_d = SDAin;
assign #5 SDA_shadow = (!porn) ? 1'b1 : (~SCL | start_or_stop) ? SDA_in_d : SDA_shadow;
assign start_or_stop = ~SCL? 1'b0 : (SDA_in_d ^ SDA_shadow);
`else
DEL5 U11 ( .A(SDAin), .Y(SDA_in_d1) );
DEL5 U12 ( .A(SDA_in_d1), .Y(SDA_in_d2));
DEL5 U13 ( .A(SDA_in_d2), .Y(SDA_in_d));
// latch with active low preset
LATCH_1X SDA_shadow_reg ( .PRSTN(porn), .D(SDA_in_d), .EN(n3), .Q(SDA_shadow) );
INV_1X U9 (.A(SCL), .Y(SLCn));
NAND2_1X U10 ( .A(SCLn), .B(n2), .Y(start_or_stop) );
// to keep minimum pulse width
DEL5 U1 (.A(n2), .Y(n2d));
BUF1 U2 (.A(n2d), .Y(n2d1));
BUF1 U3 (.A(n2d1), .Y(n2d2));
BUF1 U4 (.A(n2d2), .Y(n2d3));
BUF1 U5 (.A(n2d3), .Y(n2d4));
BUF1 U6 (.A(n2d4), .Y(n2dd));
//
AND2_1X U7 ( .A(n2dd), .B(SCL), .Y(n3) );
NOR2_1X U8 ( .A(SDA_in_d), .B(SDA_shadow), .Y(n2) );
`endif
endmodule
module LATCH_1X(PRSTN, D, EN, Q);
input PRSTN, D, EN;
output Q;
udp_ldlatch_p0 P1 (.q(Q), .d(D), .en(EN), .clear(1'b1), .preset(PRSTN));
endmodule
primitive udp_ldlatch_p0(q, d, en, clear, preset);
output q;
input d, en, clear, preset;
reg q;
table
// d en clear preset : state : q
? ? 0 ? : ? : 0;// clear to 0
? ? 1 0 : ? : 1;// preset to 1
0 1 1 1 : ? : 0;// on enable, transmit d
1 1 1 1 : ? : 1;// on enable, transmit d
? 0 1 1 : ? : -;// not enable, no change
? ? p 1 : ? : -;// ignore positive edge of clear
? ? 1 p : ? : -;// ignore positive edge of preset
endtable
endprimitive
module NOR2_1X (A, B, Y);
input A, B;
output Y;
assign #1 Y=!(A | B);
endmodule
module NAND2_1X (A, B, Y);
input A, B;
output Y;
assign #1 Y=!(A & B);
endmodule
module AND2_1X (A, B, Y);
input A, B;
output Y;
assign #1 Y=A &B;
endmodule
module INV_1X (A, Y);
input A;
output Y;
assign #1 Y=!A;
endmodule
module BUF1 (A, Y);
input A;
output Y;
assign #1 Y=A;
endmodule
module DEL5(A, Y);
input A;
output Y;
assign #5 Y= A;
endmodule
// CSR example
//
// write enable
assign csr_wr = i2c_wr;
assign csr_w_add = i2c_data_ptr;
assign csr_clk = SCL;
assign wr_csr00 = csr_wr & (csr_w_add == 5'h0);
// CSR00
always @(negedge porn or posedge csr_clk)
if (!porn)
csr00 <= `D cr00_iv;
else if (wr_csr00)
csr00 <= `D csr_din;
2009年4月1日 星期三
訂閱:
文章 (Atom)