我的芯片之路3

admin发布

我的芯片之路3

上回说到write&read module 的FSM

还是按主代码FSM顺序写:

l S0:初始化,

always@(posedge sha_clk)

if(sha_reset_b == 1’b0)

begin

//current_state= S1;

current_state=S0;

end

else

*/

begin

case(current_state)

S0:begin

sign0=1’b0;//重置延时标记

……

sha_ipen=1’b0;

sha_rw_b=1’b1;

sha_addr=5’b00000;

sha_wdata=8’b0;

pre=2’b00;

……

current_state=S1;

end

l S1:

以下标注部分为套用counter实现延时的语句模板

S1:

if(startS1==1’b0)//标志字

begin

delaystart =1’b1;//counter控制信号赋值

delay =16’h0040;

if(delaystop==1)//完成延时

begin

delaystart=1’b0;// counter控制信号重置

delay=1;

startS1=1’b1;//延时后操作

sign0=1’b1;

counter_reset=1;//清零counter***这个并不是个非常好的做法,应该是不清零也可以的(这句删除掉也没事,但没试过,具体到具体电路不太清楚区别),但是写上是可以用的

end

end

//信号sign0,对应 #500 sha_ipen=1’b1;

else if(sign0==1’b1)

begin

counter_reset=0;//=1时reset

begin

delaystart=1’b1;

delay=24;

if(delaystop==1)//完成延时

begin

delaystart=1’b0;

delay=2;

sha_ipen=1’b1;

sign0=1’b0;

sign1=1’b1;

counter_reset=1;

end

end

end

//信号sign1,对应#500

else if(sign1==1’b1)

begin

counter_reset=0;

if(reuse==1)

begin

delaystart=1’b1;

delay=26;

if(delaystop==1)//完成延时

begin

delaystart=1’b0;

delay=3;

sign1=1’b0;

current_state=S2;

counter_reset=1;

end

end

l 实现w/r模块的尝试

在实现S2过程中出现了以下问题:

n Task中是不可以有时序电路的(实现不了延时);

n S1的实现方法,实际上是一个二叉树条件,并不是多路选择器

我的芯片之路3

当面对S2,S3当中

W32(SHADI0,32’h61626364); //S3状态,W32数据

W32(SHADI1,32’h62636465);

W32(SHADI2,32’h63646566);

W32(SHADI3,32’h64656667);//read(SHADI3);

W32(SHADI4,32’h65666768);//read(SHADI4);

W32(SHADI5,32’h66676869);//read(SHADI5);

W32(SHADI6,32’h6768696a);//read(SHADI6);

W32(SHADI7,32’h68696a6b);//read(SHADI7);

W32(SHADI8,32’h696a6b6c);//read(SHADI8);

W32(SHADI9,32’h6a6b6c6d);//read(SHADI9);

W32(SHADIA,32’h6b6c6d6e);//read(SHADIA);

W32(SHADIB,32’h6c6d6e6f);//read(SHADIB);

W32(SHADIC,32’h6d6e6f70);//read(SHADIC);

W32(SHADID,32’h6e6f7071);//read(SHADID);

W32(SHADIE,32’h80000000);//read(SHADIE);

W32(SHADIF,32’h00000000);//read(SHADIF);

read(SHADI0);

read(SHADI1);

read(SHADI2);

read(SHADI3);

read(SHADI4);

read(SHADI5);

read(SHADI6);

read(SHADI7);

read(SHADI8);

read(SHADI9);

read(SHADIA);

read(SHADIB);

read(SHADIC);

read(SHADID);

read(SHADIE);

read(SHADIF);

这些代码,需要的选择过多,且不好维护

实现方法我想的第一个思路是多路选择器,每次always@(posedge sha_clk)时判断信号进行下一步。

但这种方法的实现貌似和上面一样,也是多路选择,或者就是状态机。

那就不如把read(addr【0:4】)和w32(addr【0:4】,data32‘hxxxx)分别封装为module调用

l 实现w/r module

首先,还是要搞清楚结构,仔细观察原来的tb代码,

Write模块需要什么input,输出什么

Read模块需要什么input,输出什么

这步我觉得很重要,从原先的代码并不是那么容易的一眼可以看出来输入输出关系

从原来的task入手

task W32(input [4:0] adr,input [31:0] data );

begin

W8(2’b00,data[7:0]);

W8(2’b01,data[15:8]);

W8(2’b10,data[23:16]);

W8(2’b11,data[31:24]);

#100;

sha_rw_b=1’b0;

sha_addr=adr;

@(posedge sha_clk);

#100 sha_rw_b=1’b1;

end

endtask

task W32be(input [4:0] adr,input [31:0] data );

begin

W8(2’b00,data[7:0]);

W8(2’b01,data[15:8]);

W8(2’b10,data[23:16]);

W8(2’b11,data[31:24]);

#100;

sha_rw_b=1’b0;

sha_addr=adr;

@(posedge sha_clk);

//#5 sha_rw_b=1’b1;

end

endtask

task W8(input [1:0] adr,input [7:0] data );

begin

#100;

pre=adr;

sha_wdata=data;

@(posedge sha_clk);

end

endtask

task read( input [4:0] adr );

begin

#100;

sha_wdata=8’b0;

sha_rw_b=1’b1;

sha_addr=adr;

pre=2’b00;//试试

@(posedge sha_clk);

#200 pre=2’b00;

#200 pre=2’b01;

#200 pre=2’b10;

#200 pre=2’b11;

#200;

end

endtask

我的芯片之路3

仔细分析

n 关于sha_reset_b&w32_reset,貌似并不需要sha_reset_b直接控制w32,只要sha_reset_b启动后在主代码state.v中将w32_reset,一并打开即可

n 时钟应该是一直要给的,不考虑功耗等,最好让w32一直有时钟

n Pre需要么,貌似不太需要,不过可以一直留着,和主代码中pre连接

n sha_rw_b需要么,只是个使能信号,w32模块最好像counter那样有start有stop控制,用状态机实现,我们只要在S2/S3开始时主代码中打开sha_rw_b就好

n 也就是说,从sha_state module中给w32模块data和sha addr就好,可以加上pre,其余的为时钟,rst,和其他的start,stop等复用信号。

版本shasha_12

module W32be(clk,rst,start,addr,data,pre,sha_wdata,stop,reuse);

input clk,rst,start;//clk是给counter用的。rst是自己用的,在state.v中module state中调用复用

input [4:0] addr;

input [31:0] data;//相比较原本的那个tb(不可综合的),原来的data 8位要慢一个周期给到sha_wdata,pre也要晚一个周期传输到,感觉应该不会出问题

//原来w32be 的task中的#100都有在本文件中状态机中实现

//output,复用部分信号

output wire stop;//stop=1时,本次计时结束

output wire reuse;//resure=1时,可以开始下一次计数周期

reg stop_reg=1’b0;

reg reuse_reg=1’b0;

assign stop = stop_reg;

assign reuse = reuse_reg;

//output,正常的信号控制部分

output wire [1:0]pre;

output wire [7:0]sha_wdata;

reg [1:0]pre_reg=2’b00;

reg [7:0]sha_wdata_reg=8’b0;

assign pre=pre_reg;

assign sha_wdata=sha_wdata_reg;

//给counter的控制信号

reg counter_start=0;

reg [15:0]counter_delay=0;

reg counter_reset=0;

wire counter_stop;

wire counter_reuse;

//状态信号

reg sign0=1’b0;

reg sign1=1’b0;

reg sign2=1’b0;

reg sign3=1’b0;

reg sign4=1’b0;

reg sign5=1’b0;

reg [2:0] state=3’b000;

counter w0(.clk(clk),//读stop,stop=1时结束

.rst(counter_reset),

.start(counter_start),

.delay(counter_delay),

.stop(counter_stop),

.reuse(counter_reuse));

always @ (posedge clk or posedge rst)//rst这个项目用不上。。

begin

if (rst)//rst=1置位。正常下rst=0

begin

counter_reset=1;

stop_reg = 1’b0;

reuse_reg= 1’b1;

state = 3’b000;

counter_start=0;

end

else

begin

case(state)

3’b000:

begin

counter_reset=0;

stop_reg =1’b0;

reuse_reg=1’b1;

if(start == 1’b1)

begin

state = 3’b001;

reuse_reg=1’b0;

sign0=1;

end

else

begin

state = 3’b000;

end

end

3’b001:

begin

//#100; pre=adr; sha_wdata=data;

if(sign0==1’b1)

begin

counter_start=1’b1;

counter_delay=5;

if(counter_stop==1)//完成延时

begin

counter_start=1’b0;

counter_delay=16’h3201;//随便一个标示

pre_reg=2’b00;

sha_wdata_reg=data[7:0];

sign0=1’b0;

sign1=1’b1;

state = 3’b010;

counter_reset=1;

end

end

end

3’b010:

begin

//#100; pre=adr; sha_wdata=data;

if(sign1==1’b1)

begin

counter_reset=0;//=1时reset

begin

counter_start=1’b1;

counter_delay=5;

if(counter_stop==1)//完成延时

begin

counter_start=1’b0;

counter_delay=16’h3302;//随便一个标示

pre_reg=2’b01;

sha_wdata_reg=data[15:8];

sign1=1’b0;

sign2=1’b1;

counter_reset=1;

state = 3’b011;

end

end

end

end

3’b011:

begin

//#100; pre=adr; sha_wdata=data;

if(sign2==1’b1)

begin

counter_reset=0;//=1时reset

begin

counter_start=1’b1;

counter_delay=5;

if(counter_stop==1)//完成延时

begin

counter_start=1’b0;

counter_delay=16’h3203;//随便一个标示

pre_reg=2’b10;

sha_wdata_reg=data[23:16];

sign2=1’b0;

sign3=1’b1;

counter_reset=1;

state = 3’b100;

end

end

end

end

3’b100:

begin

//#100; pre=adr; sha_wdata=data;

if(sign3==1’b1)

begin

counter_reset=0;//=1时reset

begin

counter_start=1’b1;

counter_delay=5;

if(counter_stop==1)//完成延时

begin

counter_start=1’b0;

counter_delay=16’h3204;//随便一个标示

pre_reg=2’b11;

sha_wdata_reg=data[31:24];

sign3=1’b0;

sign4=1’b1;

counter_reset=1;

state = 3’b101;

end

end

end

end

3’b101:

begin

//#100; sha_rw_b=1’b0;(这个改交给module state控制,在运行w32be结束后) sha_addr=adr;(这个不用了)

if(sign4==1’b1)

begin

counter_reset=0;//=1时reset

begin

counter_start=1’b1;

counter_delay=5;

if(counter_stop==1)//完成延时

begin

counter_start=1’b0;

counter_delay=16’h3232;//随便一个标示

sign4=1’b0;

sign5=1’b1;

counter_reset=1;

state = 3’b110;

end

end

end

end

3’b110:

begin

state <=3’b111;

stop_reg <= 1’b1;

end

3’b111:

begin

state <=3’b000;

end

endcase

end

end

endmodule

W32模块集成一个counter w0.

Read模块同上,分析来回信号,比w32少一个data,甚至不需要用(在主代码中指定就好)

module read(clk,rst,start,addr,pre,stop,reuse);

input clk,rst,start;//clk是自己用&给counter用的。rst是自己用的,在state.v中module state中调用复用

input [4:0] addr;

//output,复用部分信号

output wire stop;//stop=1时,本次计时结束

output wire reuse;//resure=1时,可以开始下一次计数周期

reg stop_reg=1’b0;

reg reuse_reg=1’b0;

assign stop = stop_reg;

assign reuse = reuse_reg;

//output,正常的信号控制部分

output wire [1:0]pre;

reg [1:0]pre_reg=2’b00;

assign pre=pre_reg;

//给counter的控制信号

reg counter_start=0;

reg [15:0]counter_delay=0;

reg counter_reset=0;

wire counter_stop;

wire counter_reuse;

//状态信号

reg sign0=1’b0;

reg sign1=1’b0;

reg sign2=1’b0;

reg sign3=1’b0;

reg sign4=1’b0;

reg sign5=1’b0;

reg [2:0] state=3’b000;

counter r0(.clk(clk),//读stop,stop=1时结束

.rst(counter_reset),

.start(counter_start),

.delay(counter_delay),

.stop(counter_stop),

.reuse(counter_reuse));

//从这开始改20160817

always @ (posedge clk or posedge rst)//rst这个项目用不上。。

begin

if (rst)//rst=1置位。正常下rst=0

begin

counter_reset<=1;

stop_reg <= 1’b0;

reuse_reg<= 1’b1;

state <= 3’b000;

counter_start<=0;

end

else

begin

case(state)

3’b000:

begin

counter_reset<=0;

stop_reg <=1’b0;

reuse_reg<=1’b1;

pre_reg=2’b00;

if(start == 1’b1)

begin

state = 3’b001;

reuse_reg=1’b0;

sign0=1;

end

else

begin

state = 3’b000;

end

end

3’b001:

begin

//#100; sha_addr=addr; pre=2’b00;

if(sign0==1’b1)

begin

counter_start=1’b1;

counter_delay=10;

if(counter_stop==1)//完成延时

begin

counter_start=1’b0;

counter_delay=16’h4401;//随便一个标示

pre_reg=2’b00;

sign0=1’b0;

sign1=1’b1;

state = 3’b010;

counter_reset=1;

end

end

end

3’b010:

begin

//#200; pre=2’b01;

if(sign1==1’b1)

begin

counter_reset=0;//=1时reset

begin

counter_start=1’b1;

counter_delay=10;

if(counter_stop==1)//完成延时

begin

counter_start=1’b0;

counter_delay=16’h4402;//随便一个标示

pre_reg=2’b01;

sign1=1’b0;

sign2=1’b1;

counter_reset=1;

state = 3’b011;

end

end

end

end

3’b011:

begin

// #200 pre=2’b10;//’001状态

if(sign2==1’b1)

begin

counter_reset=0;//=1时reset

begin

counter_start=1’b1;

counter_delay=10;

if(counter_stop==1)//完成延时

begin

counter_start=1’b0;

counter_delay=16’h4403;//随便一个标示

pre_reg=2’b10;

sign2=1’b0;

sign3=1’b1;

counter_reset=1;

state = 3’b100;

end

end

end

end

3’b100:

begin

// #200 pre=2’b11;

if(sign3==1’b1)

begin

counter_reset=0;//=1时reset

begin

counter_start=1’b1;

counter_delay=5;

if(counter_stop==1)//完成延时

begin

counter_start=1’b0;

counter_delay=16’h4404;//随便一个标示

pre_reg=2’b11;

sign3=1’b0;

sign4=1’b1;

counter_reset=1;

state = 3’b101;

end

end

end

end

3’b101:

begin

//#200;

if(sign4==1’b1)

begin

counter_reset=0;//=1时reset

begin

counter_start=1’b1;

counter_delay=10;

if(counter_stop==1)//完成延时

begin

counter_start=1’b0;

counter_delay=16’h4405;//随便一个标示

sign4=1’b0;

sign5=1’b1;

counter_reset=1;

state = 3’b110;

end

end

end

end

3’b110:

begin

state <=3’b111;

stop_reg <= 1’b1;

end

3’b111:

begin

state <=3’b000;

end

endcase

end

end

endmodule

l 在sha_state.v中调用两模块/S2,S3等的实现

// S2:W32be(SHACTRL,32’h0000000a);#8000;

S2:begin

if(startS2==1’b0)//S2控制字

begin

assign pre=w32be_pre;//初始化控制

assign sha_wdata=w32be_sha_wdata;

sha_addr=SHACTRL;//w32部分信号处理

w32be_addr=sha_addr;

w32be_start=1’b1;

w32be_data=32’h0000000a;

if(w32be_stop==1)//瀹屾垚寤舵椂

begin

w32be_start=1’b0; //w32和控制字的处理

sha_rw_b=1’b0;

startS2=1’b1;

sign2_0=1’b1;

w32be_reset=1;

end

end

else if(sign2_0==1’b1)

begin

w32be_reset=0;

sign2_0=0;

sign2_1=1;

deassign pre;

deassign sha_wdata;

end

//淇″彿sign2_1锛屽搴#8000

else if(sign2_1==1’b1)

begin

counter_reset=0;//=1鏃秗eset

begin

counter_start=1’b1;

delay=16’h0190;//#400;

if(counter_stop==1)//瀹屾垚寤舵椂

begin

counter_start=1’b0;

delay=16’h2200;

sign2_1=1’b0;

sign2_2=1’b1;

current_state=S3;

counter_reset=1;

end

end

end

end

S3:begin

//read(SHACTRL);

if(startS3==1’b0)

begin

assign pre=read_pre;

sha_rw_b=1’b1;

read_start=1’b1;

sha_addr=SHACTRL;

read_addr=sha_addr;

if(read_stop==1)//瀹屾垚寤舵椂

begin

read_start=1’b0;

startS3=1’b1;

sign3_0=1’b1;

read_reset=1;

end

end

// read(SHADO0);

else if(sign3_0==1’b1)

begin

read_reset=0;//=1鏃秗eset

begin

read_start=1’b1;

sha_addr=SHADO0;

read_addr=sha_addr;

if(read_stop==1)//瀹屾垚寤舵椂

begin

read_start=1’b0;

sign3_0=1’b0;

sign3_1=1’b1;

read_reset=1;

end

end

end

// read(SHADO1);

else if(sign3_1==1’b1)

begin

read_reset=0;//=1鏃秗eset

begin

read_start=1’b1;

sha_addr=SHADO1;

read_addr=sha_addr;

if(read_stop==1)//瀹屾垚寤舵椂

begin

read_start=1’b0;

sign3_1=1’b0;

sign3_2=1’b1;

read_reset=1;

end

end

end

// read(SHADO2);

else if(sign3_2==1’b1)

begin

read_reset=0;//=1鏃秗eset

begin

read_start=1’b1;

sha_addr=SHADO2;

read_addr=sha_addr;

if(read_stop==1)//瀹屾垚寤舵椂

begin

read_start=1’b0;

sign3_2=1’b0;

sign3_3=1’b1;

read_reset=1;

end

end

end

// read(SHADO3);

else if(sign3_3==1’b1)

begin

read_reset=0;//=1鏃秗eset

begin

read_start=1’b1;

sha_addr=SHADO3;

read_addr=sha_addr;

if(read_stop==1)//瀹屾垚寤舵椂

begin

read_start=1’b0;

sign3_3=1’b0;

sign3_4=1’b1;

read_reset=1;

end

end

end

// read(SHADO4);

else if(sign3_4==1’b1)

begin

read_reset=0;//=1鏃秗eset

begin

read_start=1’b1;

sha_addr=SHADO4;

read_addr=sha_addr;

if(read_stop==1)//瀹屾垚寤舵椂

begin

read_start=1’b0;

sign3_4=1’b0;

sign3_5=1’b1;

read_reset=1;

end

end

end

// read(SHADO5);

else if(sign3_5==1’b1)

begin

read_reset=0;//=1鏃秗eset

begin

read_start=1’b1;

sha_addr=SHADO5;

read_addr=sha_addr;

if(read_stop==1)//瀹屾垚寤舵椂

begin

read_start=1’b0;

sign3_5=1’b0;

sign3_6=1’b1;

read_reset=1;

end

end

end

// read(SHADO6);

else if(sign3_6==1’b1)

begin

read_reset=0;//=1鏃秗eset

begin

read_start=1’b1;

sha_addr=SHADO6;

read_addr=sha_addr;

if(read_stop==1)//瀹屾垚寤舵椂

begin

read_start=1’b0;

sign3_6=1’b0;

sign3_7=1’b1;

read_reset=1;

end

end

end

// read(SHADO7);

else if(sign3_7==1’b1)

begin

read_reset=0;//=1鏃秗eset

begin

read_start=1’b1;

sha_addr=SHADO7;

read_addr=sha_addr;

if(read_stop==1)//瀹屾垚寤舵椂

begin

read_start=1’b0;

sign3_7=1’b0;

sign3_8=1’b1;

current_state=S4;

deassign pre;

read_reset=1;

end

end

end

end

实际上,w32和read模块的sha_addr部分并没有什么特别的用(应该是),占用了寄存器,但是能用,我一直用到了最后,没有怎么修改了。

确实仿真时方便看。。。

有看到这的读者可以试着改改,去掉两个模块的input addr【4:0】,应该仿真结果是一样的。

下期将完成前仿

——————————–

微博@georgeuser,一枚很可能要搞硬件的喵控的专业记录日记。

记录我所走过的路,愿我的分享能予人一些借鉴,也愿我某日再回头时能再拾起细节。