2011年7月16日 星期六

數位IC設計的基本元件(四)-async-fifo

將以前作APB-Bridge的Fifo剪出來,給大家作參考
ASIC/FPGA都可以合成

對Async-Fifo有興趣的人可以參考
http://www.sunburst-design.com/papers/CummingsSNUG2002SJ_FIFO1.pdf

http://www.sunburst-design.com/papers/CummingsSNUG2002SJ_FIFO2.pdf
裡面講到自己如何設計一個Async-FIFO

如果懶得看paper,就用我寫的吧
基本上目前用起來沒問題

module asfifo_65x16(
//------------------------------
// system port
//------------------------------
rd_clk,
wr_clk,
reset_n,

//------------------------------
// input port
//------------------------------
data_in,

push,
pop,
//------------------------------
// output port
//------------------------------
data_out,

full,
empty,
);

parameter WIDTH = 65;
parameter VSIZE = 16; //number of entry
parameter ADDSIZE = 4; // number of address line

parameter DEL1 = 1;
parameter DEL0 = 0.5;
//---------------------------------------------------------
// system
//---------------------------------------------------------
input rd_clk, wr_clk;
input reset_n;

//---------------------------------------------------------
// input port
//---------------------------------------------------------
input [WIDTH-1:0] data_in;

input push;
input pop;

//---------------------------------------------------------
// output port
//---------------------------------------------------------
output [WIDTH-1:0] data_out;
output full;
output empty;
//output de; //data enable

//---------------------------------------------------------
// input wire
//---------------------------------------------------------
//---------------------------------------------------------
// output reg
//---------------------------------------------------------
reg full;
reg empty;
//---------------------------------------------------------
// output wire
//---------------------------------------------------------
wire [WIDTH-1:0] data_out;

//---------------------------------------------------------
// normal reg
//---------------------------------------------------------
reg [ADDSIZE-1:0] rd_ptr,wr_ptr;
reg empty_i;

reg pop_d, push_d;
//---------------------------------------------------------
// normal wire
//---------------------------------------------------------
wire [ADDSIZE-1:0] wr_ptr_sync2;
wire [ADDSIZE-1:0] rd_ptr_sync2;

wire [ADDSIZE-1:0] rd_addr;
wire [ADDSIZE-1:0] wr_addr;

wire [WIDTH-1:0] sram_out;

//wire pushq;

wire [ADDSIZE-1:0] rd_ptr_next;
wire [ADDSIZE-1:0] wr_ptr_next;
//wire [ADDSIZE-1:0] wr_ptr_next2;

//---------------------------------------------------------
// Design Core
//---------------------------------------------------------
//wire mem_rd = !empty_i && (empty || pop);
//assign pushq = push && !full;

always @(posedge wr_clk or negedge reset_n) begin
if (~reset_n)
wr_ptr <= #DEL1 0;
else if (push && ~full)
wr_ptr <= #DEL1 wr_ptr + 1;
else
wr_ptr <= #DEL1 wr_ptr;
end

always @(posedge rd_clk or negedge reset_n) begin
if (~reset_n)
rd_ptr <= #DEL1 0;
else if (pop && ~empty)
rd_ptr <= #DEL1 rd_ptr + 1;
else
rd_ptr <= #DEL1 rd_ptr;
end

always @(posedge rd_clk or negedge reset_n) begin
if (~reset_n)
pop_d <= #DEL0 1'b0;
else
pop_d <= #DEL0 pop;
end

/*
always @(posedge wr_clk) begin
push_d <= #`DEL0 push;
end
*/

assign #DEL1 rd_ptr_next = rd_ptr + 1;
assign #DEL1 wr_ptr_next = wr_ptr + 1;
//assign #DEL1 wr_ptr_next2 = wr_ptr + 2;

assign rd_addr = rd_ptr;
assign wr_addr = wr_ptr;

dbflop #(ADDSIZE) dbflop0(.rstn(reset_n),
.clk(rd_clk),
.in(wr_ptr),
.out(wr_ptr_sync2));

dbflop #(ADDSIZE) dbflop1(.rstn(reset_n),
.clk(wr_clk),
.in(rd_ptr),
.out(rd_ptr_sync2));

always @(posedge wr_clk or negedge reset_n) begin
if (~reset_n)
full <= #DEL1 1'b0;
else if (wr_ptr_next == rd_ptr_sync2)
full <= #DEL1 1'b1;
else if (full && (wr_ptr_next == rd_ptr_sync2 + 1))
full <= #DEL1 1'b1;
else
full <= #DEL1 1'b0;
end

always @(posedge rd_clk or negedge reset_n) begin
if (~reset_n)
empty <= #DEL0 1'b1;
else if (wr_ptr_sync2 != rd_ptr || full )
empty <= #DEL0 1'b0;
else
empty <= #DEL0 1'b1;
end

assign #DEL0 data_out = pop_d ? sram_out : 0;

此處使用TSMC的memory compiler作出來的2port-ram
rf2sh_65x16 U_rf2sh_65x16(
.QA(sram_out),
.AA(rd_addr),
.CLKA(rd_clk),
.CENA(~pop),
.AB(wr_addr),
.DB(data_in),
.CLKB(wr_clk),
.CENB(~push)
);

endmodule


//double flops
module dbflop(rstn, clk, in, out);
parameter WD=1;

input rstn;
input clk;
input[WD-1:0] in;
output[WD-1:0] out;

reg[WD-1:0] out_p, out;

parameter DLY =1;
always @(posedge clk or negedge rstn)

if (~rstn) begin
out_p <= 0;
out <= 0;
end
else begin
out_p <=#DLY in;
out <=#DLY out_p;
end
endmodule

2011年7月15日 星期五

數位IC設計的基本元件(三)-AHB2APB Bridge

先貼一個Cadence的範例,
它是將APB的MUX作在這個module內

已前我的寫法會把它放在另一個moduel
並且加上一個小fifo
有機會再把自己作過的類似Design整理上來

`define APB_SLAVE0
...

module ahb2apb
(
// AHB signals
hclk,
hreset_n,
hsel,
haddr,
htrans,
hwdata,
hwrite,
hrdata,
hready,
hresp,

// APB signals common to all APB slaves
pclk,
preset_n,
paddr,
penable,
pwrite,
pwdata

// Slave 0 signals
`ifdef APB_SLAVE0
,psel0
,pready0
,prdata0
`endif

// Slave 1 signals
`ifdef APB_SLAVE1
,psel1
,pready1
,prdata1
`endif

// Slave 2 signals
`ifdef APB_SLAVE2
,psel2
,pready2
,prdata2
`endif

// Slave 3 signals
`ifdef APB_SLAVE3
,psel3
,pready3
,prdata3
`endif

// Slave 4 signals
`ifdef APB_SLAVE4
,psel4
,pready4
,prdata4
`endif

// Slave 5 signals
`ifdef APB_SLAVE5
,psel5
,pready5
,prdata5
`endif

// Slave 6 signals
`ifdef APB_SLAVE6
,psel6
,pready6
,prdata6
`endif

// Slave 7 signals
`ifdef APB_SLAVE7
,psel7
,pready7
,prdata7
`endif

// Slave 8 signals
`ifdef APB_SLAVE8
,psel8
,pready8
,prdata8
`endif

// Slave 9 signals
`ifdef APB_SLAVE9
,psel9
,pready9
,prdata9
`endif

// Slave 10 signals
`ifdef APB_SLAVE10
,psel10
,pready10
,prdata10
`endif

// Slave 11 signals
`ifdef APB_SLAVE11
,psel11
,pready11
,prdata11
`endif

// Slave 12 signals
`ifdef APB_SLAVE12
,psel12
,pready12
,prdata12
`endif

// Slave 13 signals
`ifdef APB_SLAVE13
,psel13
,pready13
,prdata13
`endif

// Slave 14 signals
`ifdef APB_SLAVE14
,psel14
,pready14
,prdata14
`endif

// Slave 15 signals
`ifdef APB_SLAVE15
,psel15
,pready15
,prdata15
`endif

);

parameter
APB_SLAVE0_START_ADDR = 32'h00800000,
APB_SLAVE0_END_ADDR = 32'h0080FFFF,
APB_SLAVE1_START_ADDR = 32'h00810000,
APB_SLAVE1_END_ADDR = 32'h0081FFFF,
APB_SLAVE2_START_ADDR = 32'h00820000,
APB_SLAVE2_END_ADDR = 32'h0082FFFF,
APB_SLAVE3_START_ADDR = 32'h00830000,
APB_SLAVE3_END_ADDR = 32'h0083FFFF,
APB_SLAVE4_START_ADDR = 32'h00840000,
APB_SLAVE4_END_ADDR = 32'h0084FFFF,
APB_SLAVE5_START_ADDR = 32'h00850000,
APB_SLAVE5_END_ADDR = 32'h0085FFFF,
APB_SLAVE6_START_ADDR = 32'h00860000,
APB_SLAVE6_END_ADDR = 32'h0086FFFF,
APB_SLAVE7_START_ADDR = 32'h00870000,
APB_SLAVE7_END_ADDR = 32'h0087FFFF,
APB_SLAVE8_START_ADDR = 32'h00880000,
APB_SLAVE8_END_ADDR = 32'h0088FFFF,
APB_SLAVE9_START_ADDR = 32'h00890000,
APB_SLAVE9_END_ADDR = 32'h0089FFFF,
APB_SLAVE10_START_ADDR = 32'h008A0000,
APB_SLAVE10_END_ADDR = 32'h008AFFFF,
APB_SLAVE11_START_ADDR = 32'h008B0000,
APB_SLAVE11_END_ADDR = 32'h008BFFFF,
APB_SLAVE12_START_ADDR = 32'h008C0000,
APB_SLAVE12_END_ADDR = 32'h008CFFFF,
APB_SLAVE13_START_ADDR = 32'h008D0000,
APB_SLAVE13_END_ADDR = 32'h008DFFFF,
APB_SLAVE14_START_ADDR = 32'h008E0000,
APB_SLAVE14_END_ADDR = 32'h008EFFFF,
APB_SLAVE15_START_ADDR = 32'h008F0000,
APB_SLAVE15_END_ADDR = 32'h008FFFFF;

// AHB signals
input hclk;
input hreset_n;
input hsel;
input[31:0] haddr;
input[1:0] htrans;
input[31:0] hwdata;
input hwrite;
output[31:0] hrdata;
reg [31:0] hrdata;
output hready;
output[1:0] hresp;

// APB signals common to all APB slaves
output pclk;
output preset_n;
output[31:0] paddr;
reg [31:0] paddr;
output penable;
reg penable;
output pwrite;
reg pwrite;
output[31:0] pwdata;

// Slave 0 signals
`ifdef APB_SLAVE0
output psel0;
input pready0;
input[31:0] prdata0;
`endif

// Slave 1 signals
`ifdef APB_SLAVE1
output psel1;
input pready1;
input[31:0] prdata1;
`endif

// Slave 2 signals
`ifdef APB_SLAVE2
output psel2;
input pready2;
input[31:0] prdata2;
`endif

// Slave 3 signals
`ifdef APB_SLAVE3
output psel3;
input pready3;
input[31:0] prdata3;
`endif

// Slave 4 signals
`ifdef APB_SLAVE4
output psel4;
input pready4;
input[31:0] prdata4;
`endif

// Slave 5 signals
`ifdef APB_SLAVE5
output psel5;
input pready5;
input[31:0] prdata5;
`endif

// Slave 6 signals
`ifdef APB_SLAVE6
output psel6;
input pready6;
input[31:0] prdata6;
`endif

// Slave 7 signals
`ifdef APB_SLAVE7
output psel7;
input pready7;
input[31:0] prdata7;
`endif

// Slave 8 signals
`ifdef APB_SLAVE8
output psel8;
input pready8;
input[31:0] prdata8;
`endif

// Slave 9 signals
`ifdef APB_SLAVE9
output psel9;
input pready9;
input[31:0] prdata9;
`endif

// Slave 10 signals
`ifdef APB_SLAVE10
output psel10;
input pready10;
input[31:0] prdata10;
`endif

// Slave 11 signals
`ifdef APB_SLAVE11
output psel11;
input pready11;
input[31:0] prdata11;
`endif

// Slave 12 signals
`ifdef APB_SLAVE12
output psel12;
input pready12;
input[31:0] prdata12;
`endif

// Slave 13 signals
`ifdef APB_SLAVE13
output psel13;
input pready13;
input[31:0] prdata13;
`endif

// Slave 14 signals
`ifdef APB_SLAVE14
output psel14;
input pready14;
input[31:0] prdata14;
`endif

// Slave 15 signals
`ifdef APB_SLAVE15
output psel15;
input pready15;
input[31:0] prdata15;
`endif

reg ahb_addr_phase;
reg ahb_data_phase;
wire valid_ahb_trans;
wire pready_muxed;
wire [31:0] prdata_muxed;
reg [31:0] haddr_reg;
reg hwrite_reg;
reg [2:0] apb_state;
wire [2:0] apb_state_idle;
wire [2:0] apb_state_setup;
wire [2:0] apb_state_access;
reg [15:0] slave_select;
wire [15:0] pready_vector;
reg [15:0] psel_vector;
wire [31:0] prdata0_q;
wire [31:0] prdata1_q;
wire [31:0] prdata2_q;
wire [31:0] prdata3_q;
wire [31:0] prdata4_q;
wire [31:0] prdata5_q;
wire [31:0] prdata6_q;
wire [31:0] prdata7_q;
wire [31:0] prdata8_q;
wire [31:0] prdata9_q;
wire [31:0] prdata10_q;
wire [31:0] prdata11_q;
wire [31:0] prdata12_q;
wire [31:0] prdata13_q;
wire [31:0] prdata14_q;
wire [31:0] prdata15_q;

assign pclk = hclk;
assign preset_n = hreset_n;
assign hready = ahb_addr_phase;
assign pwdata = hwdata;
assign hresp = 2'b00;

// Respond to NONSEQ or SEQ transfers
assign valid_ahb_trans = ((htrans == 2'b10) || (htrans == 2'b11)) && (hsel == 1'b1);

always @(posedge hclk) begin
if (hreset_n == 1'b0) begin
ahb_addr_phase <= 1'b1;
ahb_data_phase <= 1'b0;
haddr_reg <= 'b0;
hwrite_reg <= 1'b0;
hrdata <= 'b0;
end
else begin
if (ahb_addr_phase == 1'b1 && valid_ahb_trans == 1'b1) begin
ahb_addr_phase <= 1'b0;
ahb_data_phase <= 1'b1;
haddr_reg <= haddr;
hwrite_reg <= hwrite;
end
if (ahb_data_phase == 1'b1 && pready_muxed == 1'b1 && apb_state == apb_state_access) begin
ahb_addr_phase <= 1'b1;
ahb_data_phase <= 1'b0;
hrdata <= prdata_muxed;
end
end
end

// APB state machine state definitions
assign apb_state_idle = 3'b001;
assign apb_state_setup = 3'b010;
assign apb_state_access = 3'b100;

// APB state machine
always @(posedge hclk or negedge hreset_n) begin
if (hreset_n == 1'b0) begin
apb_state <= apb_state_idle;
psel_vector <= 1'b0;
penable <= 1'b0;
paddr <= 1'b0;
pwrite <= 1'b0;
end
else begin

// IDLE -> SETUP
if (apb_state == apb_state_idle) begin
if (ahb_data_phase == 1'b1) begin
apb_state <= apb_state_setup;
psel_vector <= { slave_select[15], slave_select[14], slave_select[13], slave_select[12], slave_select[11], slave_select[10],
slave_select[9], slave_select[8], slave_select[7], slave_select[6], slave_select[5], slave_select[4],
slave_select[3], slave_select[1], slave_select[1], slave_select[0] };
paddr <= haddr_reg;
pwrite <= hwrite_reg;
end
end

// SETUP -> TRANSFER
if (apb_state == apb_state_setup) begin
apb_state <= apb_state_access;
penable <= 1'b1;
end

// TRANSFER -> SETUP or
// TRANSFER -> IDLE
if (apb_state == apb_state_access) begin
if (pready_muxed == 1'b1) begin

// TRANSFER -> SETUP
if (valid_ahb_trans == 1'b1) begin
apb_state <= apb_state_setup;
penable <= 1'b0;
psel_vector <= { slave_select[15], slave_select[14], slave_select[13], slave_select[12], slave_select[11], slave_select[10],
slave_select[9], slave_select[8], slave_select[7], slave_select[6], slave_select[5], slave_select[4],
slave_select[3], slave_select[2], slave_select[1], slave_select[0] };
paddr <= haddr_reg;
pwrite <= hwrite_reg;
end

// TRANSFER -> IDLE
else begin
apb_state <= apb_state_idle;
penable <= 1'b0;
psel_vector <= 'b0;
end
end
end

end
end

always @(posedge hclk or negedge hreset_n) begin
if (hreset_n == 1'b0)
slave_select <= 'b0;
else begin
`ifdef APB_SLAVE0
slave_select[0] <= valid_ahb_trans && (haddr >= APB_SLAVE0_START_ADDR) && (haddr <= APB_SLAVE0_END_ADDR);
`else
slave_select[0] <= 1'b0;
`endif

`ifdef APB_SLAVE1
slave_select[1] <= valid_ahb_trans && (haddr >= APB_SLAVE1_START_ADDR) && (haddr <= APB_SLAVE1_END_ADDR);
`else
slave_select[1] <= 1'b0;
`endif

`ifdef APB_SLAVE2
slave_select[2] <= valid_ahb_trans && (haddr >= APB_SLAVE2_START_ADDR) && (haddr <= APB_SLAVE2_END_ADDR);
`else
slave_select[2] <= 1'b0;
`endif

`ifdef APB_SLAVE3
slave_select[3] <= valid_ahb_trans && (haddr >= APB_SLAVE3_START_ADDR) && (haddr <= APB_SLAVE3_END_ADDR);
`else
slave_select[3] <= 1'b0;
`endif

`ifdef APB_SLAVE4
slave_select[4] <= valid_ahb_trans && (haddr >= APB_SLAVE4_START_ADDR) && (haddr <= APB_SLAVE4_END_ADDR);
`else
slave_select[4] <= 1'b0;
`endif

`ifdef APB_SLAVE5
slave_select[5] <= valid_ahb_trans && (haddr >= APB_SLAVE5_START_ADDR) && (haddr <= APB_SLAVE5_END_ADDR);
`else
slave_select[5] <= 1'b0;
`endif

`ifdef APB_SLAVE6
slave_select[6] <= valid_ahb_trans && (haddr >= APB_SLAVE6_START_ADDR) && (haddr <= APB_SLAVE6_END_ADDR);
`else
slave_select[6] <= 1'b0;
`endif

`ifdef APB_SLAVE7
slave_select[7] <= valid_ahb_trans && (haddr >= APB_SLAVE7_START_ADDR) && (haddr <= APB_SLAVE7_END_ADDR);
`else
slave_select[7] <= 1'b0;
`endif

`ifdef APB_SLAVE8
slave_select[8] <= valid_ahb_trans && (haddr >= APB_SLAVE8_START_ADDR) && (haddr <= APB_SLAVE8_END_ADDR);
`else
slave_select[8] <= 1'b0;
`endif

`ifdef APB_SLAVE9
slave_select[9] <= valid_ahb_trans && (haddr >= APB_SLAVE9_START_ADDR) && (haddr <= APB_SLAVE9_END_ADDR);
`else
slave_select[9] <= 1'b0;
`endif

`ifdef APB_SLAVE10
slave_select[10] <= valid_ahb_trans && (haddr >= APB_SLAVE10_START_ADDR) && (haddr <= APB_SLAVE10_END_ADDR);
`else
slave_select[10] <= 1'b0;
`endif

`ifdef APB_SLAVE11
slave_select[11] <= valid_ahb_trans && (haddr >= APB_SLAVE11_START_ADDR) && (haddr <= APB_SLAVE11_END_ADDR);
`else
slave_select[11] <= 1'b0;
`endif

`ifdef APB_SLAVE12
slave_select[12] <= valid_ahb_trans && (haddr >= APB_SLAVE12_START_ADDR) && (haddr <= APB_SLAVE12_END_ADDR);
`else
slave_select[12] <= 1'b0;
`endif

`ifdef APB_SLAVE13
slave_select[13] <= valid_ahb_trans && (haddr >= APB_SLAVE13_START_ADDR) && (haddr <= APB_SLAVE13_END_ADDR);
`else
slave_select[13] <= 1'b0;
`endif

`ifdef APB_SLAVE14
slave_select[14] <= valid_ahb_trans && (haddr >= APB_SLAVE14_START_ADDR) && (haddr <= APB_SLAVE14_END_ADDR);
`else
slave_select[14] <= 1'b0;
`endif

`ifdef APB_SLAVE15
slave_select[15] <= valid_ahb_trans && (haddr >= APB_SLAVE15_START_ADDR) && (haddr <= APB_SLAVE15_END_ADDR);
`else
slave_select[15] <= 1'b0;
`endif
end
end

assign pready_muxed = |(psel_vector & pready_vector);
assign prdata_muxed = prdata0_q | prdata1_q | prdata2_q | prdata3_q |
prdata4_q | prdata5_q | prdata6_q | prdata7_q |
prdata8_q | prdata9_q | prdata10_q | prdata11_q |
prdata12_q | prdata13_q | prdata14_q | prdata15_q ;

`ifdef APB_SLAVE0
assign psel0 = psel_vector[0];
assign pready_vector[0] = pready0;
assign prdata0_q = (psel0 == 1'b1) ? prdata0 : 'b0;
`else
assign pready_vector[0] = 1'b0;
assign prdata0_q = 'b0;
`endif

`ifdef APB_SLAVE1
assign psel1 = psel_vector[1];
assign pready_vector[1] = pready1;
assign prdata1_q = (psel1 == 1'b1) ? prdata1 : 'b0;
`else
assign pready_vector[1] = 1'b0;
assign prdata1_q = 'b0;
`endif

`ifdef APB_SLAVE2
assign psel2 = psel_vector[2];
assign pready_vector[2] = pready2;
assign prdata2_q = (psel2 == 1'b1) ? prdata2 : 'b0;
`else
assign pready_vector[2] = 1'b0;
assign prdata2_q = 'b0;
`endif

`ifdef APB_SLAVE3
assign psel3 = psel_vector[3];
assign pready_vector[3] = pready3;
assign prdata3_q = (psel3 == 1'b1) ? prdata3 : 'b0;
`else
assign pready_vector[3] = 1'b0;
assign prdata3_q = 'b0;
`endif

`ifdef APB_SLAVE4
assign psel4 = psel_vector[4];
assign pready_vector[4] = pready4;
assign prdata4_q = (psel4 == 1'b1) ? prdata4 : 'b0;
`else
assign pready_vector[4] = 1'b0;
assign prdata4_q = 'b0;
`endif

`ifdef APB_SLAVE5
assign psel5 = psel_vector[5];
assign pready_vector[5] = pready5;
assign prdata5_q = (psel5 == 1'b1) ? prdata5 : 'b0;
`else
assign pready_vector[5] = 1'b0;
assign prdata5_q = 'b0;
`endif

`ifdef APB_SLAVE6
assign psel6 = psel_vector[6];
assign pready_vector[6] = pready6;
assign prdata6_q = (psel6 == 1'b1) ? prdata6 : 'b0;
`else
assign pready_vector[6] = 1'b0;
assign prdata6_q = 'b0;
`endif

`ifdef APB_SLAVE7
assign psel7 = psel_vector[7];
assign pready_vector[7] = pready7;
assign prdata7_q = (psel7 == 1'b1) ? prdata7 : 'b0;
`else
assign pready_vector[7] = 1'b0;
assign prdata7_q = 'b0;
`endif

`ifdef APB_SLAVE8
assign psel8 = psel_vector[8];
assign pready_vector[8] = pready8;
assign prdata8_q = (psel8 == 1'b1) ? prdata8 : 'b0;
`else
assign pready_vector[8] = 1'b0;
assign prdata8_q = 'b0;
`endif

`ifdef APB_SLAVE9
assign psel9 = psel_vector[9];
assign pready_vector[9] = pready9;
assign prdata9_q = (psel9 == 1'b1) ? prdata9 : 'b0;
`else
assign pready_vector[9] = 1'b0;
assign prdata9_q = 'b0;
`endif

`ifdef APB_SLAVE10
assign psel10 = psel_vector[10];
assign pready_vector[10] = pready10;
assign prdata10_q = (psel10 == 1'b1) ? prdata10 : 'b0;
`else
assign pready_vector[10] = 1'b0;
assign prdata10_q = 'b0;
`endif

`ifdef APB_SLAVE11
assign psel11 = psel_vector[11];
assign pready_vector[11] = pready11;
assign prdata11_q = (psel11 == 1'b1) ? prdata11 : 'b0;
`else
assign pready_vector[11] = 1'b0;
assign prdata11_q = 'b0;
`endif

`ifdef APB_SLAVE12
assign psel12 = psel_vector[12];
assign pready_vector[12] = pready12;
assign prdata12_q = (psel12 == 1'b1) ? prdata12 : 'b0;
`else
assign pready_vector[12] = 1'b0;
assign prdata12_q = 'b0;
`endif

`ifdef APB_SLAVE13
assign psel13 = psel_vector[13];
assign pready_vector[13] = pready13;
assign prdata13_q = (psel13 == 1'b1) ? prdata13 : 'b0;
`else
assign pready_vector[13] = 1'b0;
assign prdata13_q = 'b0;
`endif

`ifdef APB_SLAVE14
assign psel14 = psel_vector[14];
assign pready_vector[14] = pready14;
assign prdata14_q = (psel14 == 1'b1) ? prdata14 : 'b0;
`else
assign pready_vector[14] = 1'b0;
assign prdata14_q = 'b0;
`endif

`ifdef APB_SLAVE15
assign psel15 = psel_vector[15];
assign pready_vector[15] = pready15;
assign prdata15_q = (psel15 == 1'b1) ? prdata15 : 'b0;
`else
assign pready_vector[15] = 1'b0;
assign prdata15_q = 'b0;
`endif



// Add the one hot psel assertion here,
// note that pselx signals are derived from psel_vector signal,
// so use psel_vector to write this assertion
// No more than 1 psel output signal should ever be asserted at the same time


endmodule

2011年7月14日 星期四

DelayLine的設計

想不出要寫甚麼,把很久以前的東東貼出來分享

一個很簡單的delay line的電路設計

// DLY4X1 : 0.536;0.728;1.238
// DLY3X1 : 0.394;0.536;0.916
// DLY1X1 : 1.167;0.225;0.382

module dly_line(line_in,
dly_sel,
src_sel,
line_out);

input line_in;
input [1:0] dly_sel;
input [1:0] src_sel;
output line_out;

wire line_in;
//wire dly_0;
wire dly_1;
wire dly_2;
wire dly_3;
wire dly_4;

wire out_4;
reg out_3;
wire out_2;
wire out_1;

reg line_out;

//DLY2X1 u_dly_0 (.A(line_in), .Y(dly_0));
//DLY4X1 u_dly_1 (.A(dly_0), .Y(dly_1));
DLY4X1 u_dly_1 (.A(line_in), .Y(dly_1));
DLY4X1 u_dly_2 (.A(dly_1), .Y(dly_2));
DLY4X1 u_dly_3 (.A(dly_2), .Y(dly_3));
DLY4X1 u_dly_4 (.A(dly_3), .Y(dly_4));

assign out_4 = ~out_3;
assign out_1 = line_in;
assign out_2 = ~line_in;



always @(dly_sel or dly_1 or dly_2 or dly_3 or dly_4 or out_4)
case(dly_sel)
2'b00 : out_3 = dly_1;
2'b01 : out_3 = dly_2;
2'b10 : out_3 = dly_3;
2'b11 : out_3 = dly_4;
endcase

always @(src_sel or out_1 or out_2 or out_3 or out_4 or line_out)
case(src_sel)
2'b00 : line_out = out_1;
2'b01 : line_out = out_2;
2'b10 : line_out = out_3;
2'b11 : line_out = out_4;
endcase

endmodule

2011年7月13日 星期三

fsdb技巧(三)

使用fsdbAutoSwitchDumpfile的範例

$fsdbAutoSwitchDumpfile(500,"./fsdb/fsdbdump.fsdb", 10,"fsdb.log");//放在第一個
$fsdbDumpvars(0, tb_top);

//$fsdbDumpflush ; 不必使用




TetraMAX再了解(二)

DFT compiler to TetraMax


2011年7月12日 星期二

Design Compiler再了解(五)

current_design RISC_CORE
link
source golden.scr
report_timing


nreport_design
lReports design attributes such as operating conditions and wire load models

nreport_clock and report_clock -skew
lReports all clocks and their attributes as well as skew information
n
check_timing
lReports any timing path that is not constrained for max timing
lWill also generate a warning if there are unmapped cells in a design
n
report_port -verbose
lDisplays all port attributes and constraints

TetraMAX再了解(一)

從DC產出的
TetraMAX所需要的檔案

write_test_protocol –out design.stil

*.spf ( STIL Protocol File),提供給
TetraMAX知道電路在測試過程中的signal
, timing, load and unload 等資訊

2011年7月11日 星期一

Design Compiler再了解(四)

一個抽出的範例
Wire Load Model


wire_load (“10x10”) {
resistance : 5.0
capacitance : 1.1
area : 0.05
slope : 0.5
fanout_length (1, 2.6)
fanout_length (2, 2.9)
fanout_length (3, 3.6)
fanout_length (4, 3.9)
fanout_length (5, 4.1)
fanout_length (6. 4.7)
}












Wireloadmodel的作用
•Estimate capacitance/resistance of nets.
•Statistically average length of a net for # of
fanouts.



















Length = 4.7+((8-6)x 0.5) = 5.7 length
Capacitance =5.7(length) x1.1 (cap coeff.)=6.27 load units



Design Compiler再了解(三)

Example Constraints for Exploration
set CLK_PER 10
create_clock -period $CLK_PER [get_ports CLK]
set_dont_touch_network [get_clocks CLK]
set_clock_uncertainty -setup 0.8 CLK
set_operating_conditions SLOW_COMMERCIAL

# Wireload model of MAJOR_BLOCK_A. Assume layout tool ungroups smaller blocks
set_wire_load -mode top 40_SQ_MIL

# Assume inputs not register driven
set all_in_but_clk [remove_from_collection [all_inputs] [get_ports CLK]]

set_input_delay -max [expr $CLK_PER * 0.5] -clock CLK $all_in_but_clk
set_driving_cell -lib_cell NAND2 -pin Y $all_in_but_clk
set_load [expr [load_of TECH_LIB/NAND2/A] * 4] $all_in_but_clk

# Constrain the outputs
set_output_delay -max [expr $CLK_PER * 0.5] -clock CLK [all_outputs]
set_load [expr [load_of TECH_LIB/NAND2/A] * 6] [all_outputs]

# Remove area goals if it is a lower priority and for a quick compile
# set_max_area 100




另一個例子
# Define clock
create_clock -period 10 [get_ports CLK]
set_dont_touch_network [all_clocks]
# Delay and drive strength on input ports
set all_inputs_but_clk [remove_from_collection [all_inputs] CLK]
set_input_delay $clk_to_q -clock CLK $all_inputs_but_clk
set_driving_cell -lib_cell $my_register $all_inputs_but_clk
# Delay and load on output ports
set_output_delay [expr 10 - $clk_to_q] -clock CLK [all_outputs]
set_load [expr $pessimistic_load * 3] [all_outputs]
# Describe environment
set_operating_conditions WCCOM
set_wire_load_mode top
set auto_wire_load_selection false
set_wire_load_model -name 100k_WLM

2011年7月10日 星期日

Design Compiler再了解(二)

Use Test-Ready Scan Synthesis
n1. Regular registers are replaced with scannable ones, but not chained

n2. Include the scan style in the constraint script file
set_scan_configuration -style multiplexed_flip_flop

n3. Perform a test-ready compile
compile -scan -map_effort medium

Design Compiler再了解(一)

dcsh mode vs. Tcl mode

dcsh mode script
/* myscript */
target_library = {mylib.db}
link_library = {“*”, mylib.db}
read -f db TOP.db
current_design TOP
link
period = 10.0
create_clock -per period \
find(port, “CLK”) -name CLK
set_input_delay 5 -clock CLK \
all_inputs() - find(port CLK)
include timing_exceptions.scr
compile


Tcl mode script

# myscript

set target_library mylib.db
set link_library * mylib.db

read_db TOP.db
current_design TOP
link

set period 10.0
create_clock -per $period \
[get_port “CLK”] -name CLK

set_input_delay 5 -clock CLK \
[remove_from_collection \
[all_inputs] [get_port “CLK”]]

source timing_exceptions.tcl

compile

APR files

ICC是基于Milkyway对库来进行设计的,这就要用Milkyway到库来支持。
FRAM,这个是Design中STD或者MACRO的框架,如果工具都不知道设计中的东西长得怎样,怎么做Place啊?
TIM, 这个包含了Cell的Timing信息,优化用的。
LM, Logic module
PWR: power