indexed one-hot 风格的状态机写法,性能、面积占用和稳定性多半比多数人正在使用的方
如果你不知道标题里说的方法是什么,你来对地方了。这是一个讲状态机怎么写的文档。若干天前在看systemverilog for design是,书里提到了indexed one-hot的风格,然后给了网址说这里有篇文章讲状态机的,就是这个:
点击此处下载 ourdev_571713.pdf(文件大小:266K) (原文件名:CummingsSNUG2003SJ_SystemVerilogFSM.pdf)
非常好的一篇牛文,看完会发现自己以前用的那种伪one-hot居然是最弱的方式。
我转到这种风格有些日子了,写了一些程序后发现占用资源的确是小了很多,而且你可以用诸如 assign module_idle = state; 这样的方式直接输出一些和状态有关的量,和 assign module_idle= (state == IDLE); 相比,能节约多少资源,消除多少毛刺?
另外这种风格的状态机很稳定,可以直接使用某个状态机的位作为组合逻辑的敏感信号,比如 always @(state)。OTL太爽了,状态机居然也能做敏感信号了。(我的板子反正用以前的风格由于毛刺的问题直接用状态做敏感信号必然跑飞,应该不是个案吧,那时还把我愁了2天)。
希望对大家有所帮助。
PS:另外个人觉得中国人太吃亏了,信息传递的太慢。我怎么到现在才知道有这么好的方法呢?直到看原版书了才接触到了此类信息。诶。 最近将公司的东西改变成用状态机的方式,已经觉得条理更清晰、系统更稳定了,还沾沾自喜! 没想到楼主已经更进一步。(注我不是用HDL语言,是用在DSP上的C语言) 贴一个我这两天写的MT9M111数据捕捉打包模块的状态机,已经实现TFT显示摄像头图像了。这里用的就是indexed one-hot
localparam
IDLE = 0,
WAIT_F = 1, //wait frame_valid
LINE_START = 2, //send packet header, includeing startofpacket and line number
WAIT_L = 3, // wait line_valid
PACK_DATA = 4, //pack 8-bit input into 16-bit RGB565 format and send to FIFO
WAIT_ST1 = 5,
LINE_END = 6, //send endofpacket, empty = 2, no data available at this point
WAIT_ST2 = 7;
reg state = 8'b1;
reg next = 8'b1;
reg byte_tag = 2'd0; //decide which half this byte is
always @(posedge csi_clk or negedge csi_reset_n)
if(!csi_reset_n) state <= 8'b1;
else state <= next;
always @(state or coe_frame_valid or coe_line_valid or st_sender_idle) begin
next = 8'b0;
case(1'b1)
state : if(!video_input_enable) next = 1'b1;
else if(!coe_frame_valid) next = 1'b1; //ensure it starts from the begin of a frame
else next = 1'b1;
state : if(coe_frame_valid) next = 1'b1;
else next = 1'b1;
state : next = 1'b1;
state : if(!coe_frame_valid) next = 1'b1;
else if(coe_line_valid)next = 1'b1;
else next = 1'b1;
state : if(!coe_line_valid) next = 1'b1;
else next = 1'b1;
state : if(st_sender_idle) next = 1'b1;
else next = 1'b1;
state : next = 1'b1;
state : if(st_sender_idle) next = 1'b1;
else next = 1'b1;
default : next = 1'b1;
endcase
end mark mark 都是高手 mark 先顶 夸大事实。 mark 回复【8楼】tear086 .COM 缺氧
夸大事实。
-----------------------------------------------------------------------
如何理解? 回复【10楼】eworker
-----------------------------------------------------------------------
独热码、格雷码和二进制码的使用,视状态数之多少而定,不能一概而论。顺便说下,二段式和三段式的FSM各有应用场合,亦不能一概而论。
点击此处下载 ourdev_571862.pdf(文件大小:695K) (原文件名:FSM 设计指导.pdf) 我知道这篇文章的作者,他的职业是一个HDL培训师,经验非常丰富。上大学的时候把他写的所有文章都打印出来学习了一遍,受益匪浅,这篇当然也不例外,文中讲述的状态机编码规则是受到普遍认可的,这一点毋庸置疑。indexed one-hot的风格确实能生成最高效的电路,但是用常规的二段式或三段式编码方式,也是能够生成类似电路的,现在的综合器更加智能了,能够由用户定义状态机的编码方式。
文中还提到了一种用状态位替换输出的编码方式,起初我觉得非常巧妙,后来觉得这种方式用起来不太灵活,因此也懒得用,毕竟也省不了几个寄存器。
另外,为了充分利用综合器的智能,状态机的状态最好用sysverilog中的enum类型定义,这样在综合时综合器就可忽略状态的具体编码,更利于电路的优化(这是我自己的体会,不保证正确哟!) 回复【12楼】fzfh1219
-----------------------------------------------------------------------
呵呵,枚举在哪里都是个好东西。 mark 难道我在不知不觉中就尝试过这种方法了?我还没发觉,不过还没发现这种方法的好处...再研究研究. mark mark 谢谢楼主了,这些都是高层次的东西啊。难得。 就是看英语有点难度 mark mark 应该还有更好的方法,对于一个状态机:
http://cache.amobbs.com/bbs_upload782111/files_36/ourdev_616465XRNVMP.PNG
(原文件名:1.PNG)
http://cache.amobbs.com/bbs_upload782111/files_36/ourdev_616466L5GZ56.PNG
(原文件名:2.PNG)
可以使用simulink建模,然后可以导出成C语言
http://cache.amobbs.com/bbs_upload782111/files_36/ourdev_616467JBOBB9.PNG
(原文件名:c.PNG)
也可以导出成可综合的HDL
http://cache.amobbs.com/bbs_upload782111/files_36/ourdev_616468VLLHXV.PNG
(原文件名:hdl.PNG)
编码方式可选
http://cache.amobbs.com/bbs_upload782111/files_36/ourdev_616469D3TGC9.PNG
(原文件名:config.PNG) 回复【22楼】linhaimi
-----------------------------------------------------------------------
niubility!
如此强悍 占位,向高手学习一下哈 mark Verilog 回复【22楼】linhaimi
-----------------------------------------------------------------------
这个牛逼。 matlab还真强大啊,就是太贵了,只能自用了 mark matlab mark 回复【22楼】linhaimi
-----------------------------------------------------------------------
请教:
按照您图片提示 ,在生成“hdl”文件时 出现错误“Chart Property'Execute(enter) chart at Initialization must be turned on for HDL coder”..
请问我哪里操作错误,请指教,谢谢 module ins (
data,
txd,
//enable,
rst_n,
tx_clk
);
//input enable;
input rst_n;
input data;
input tx_clk;
output txd;
reg txd_reg;
reg cs,ns;
parameter
A = 0,
B = 1,
C = 2,
D = 3,
E = 4,
F = 5;
always@(posedge tx_clk or negedge rst_n)
if(!rst_n)
begin
cs <= 6'b0;cs <= 1'b1;
end
else
cs <= ns;
always@(*)
if(!rst_n)
ns <= 6'b0;
else
begin
case(1'b1)
cs: if(data==1'b0) ns<=1'b1; else ns<=1'b1;
cs: if(data==1'b0) ns<=1'b1; else ns<=1'b1;
cs: if(data==1'b0) ns<=1'b1; else ns<=1'b1;
cs: if(data==1'b0) ns<=1'b1; else ns<=1'b1;
cs: if(data==1'b0) ns<=1'b1; else ns<=1'b1;
cs: if(data==1'b0) ns<=1'b1; else ns<=1'b1;
endcase
end
always@(posedge tx_clk or negedge rst_n)
if(!rst_n)
txd_reg<=1'b0;
else
case(1'b1)
ns,ns,ns,ns : txd_reg<=1'b0;
ns,ns : txd_reg<=1'b1;
default : txd_reg<=1'b0;
endcase
assign txd = txd_reg;
帮忙看看我改的,怎么会得不到了 OK,发现问题了。但是发现占用面积比以前要多啊 Combinational ALUTs 6和8,使用ONE-HOT是8个,使用三段式但是不是ONEHOT模式是6个,使用三段式ONE-HOT模式也是6个,没发现上面的这种有啥优势啊。 module ins (
data,
txd,
//enable,
rst_n,
tx_clk
);
//input enable;
input rst_n;
input data;
input tx_clk;
output txd;
reg txd_reg;
// ONT HOT TYPE
//reg cs,ns;
//
//parameter
// A = 0,
// B = 1,
// C = 2,
// D = 3,
// E = 4,
// F = 5;
//
//always@(posedge tx_clk or negedge rst_n)
// if(!rst_n)
// begin
// cs <= 6'b0;cs <= 1'b1;
// end
// else
// cs <= ns;
//
//always@(*)
// begin
// ns <= 6'b0;
// case(1'b1)
// cs: if(data==1'b0) ns<=1'b1; else ns<=1'b1;
// cs: if(data==1'b0) ns<=1'b1; else ns<=1'b1;
// cs: if(data==1'b0) ns<=1'b1; else ns<=1'b1;
// cs: if(data==1'b0) ns<=1'b1; else ns<=1'b1;
// cs: if(data==1'b0) ns<=1'b1; else ns<=1'b1;
// cs: if(data==1'b0) ns<=1'b1; else ns<=1'b1;
// endcase
// end
//always@(posedge tx_clk or negedge rst_n)
// if(!rst_n)
// txd_reg<=1'b0;
// else
// case(1'b1)
// ns,ns,ns,ns,ns : txd_reg<=1'b0;
// ns : txd_reg<=1'b1;
// default : txd_reg<=1'b0;
// endcase
//reg cs,ns;
//
//parameter
// A = 3'b001,
// B = 3'b010,
// C = 3'b011,
// D = 3'b100,
// E = 3'b101,
// F = 3'b110;
//
//always@(posedge tx_clk or negedge rst_n)
// if(!rst_n)
// begin
// cs <= A;
// end
// else
// cs <= ns;
//
//always@(*)
// begin
//// ns <= 6'b0;
// case(cs)
// A: if(data==1'b0) ns<=B; else ns<=A;
// B: if(data==1'b0) ns<=C; else ns<=A;
// C: if(data==1'b0) ns<=D; else ns<=A;
// D: if(data==1'b0) ns<=E; else ns<=A;
// E: if(data==1'b0) ns<=F; else ns<=A;
// F: if(data==1'b0) ns<=B; else ns<=A;
// endcase
// end
//always@(posedge tx_clk or negedge rst_n)
// if(!rst_n)
// txd_reg<=1'b0;
// else
// case(ns)
// A,B,C,D,E: txd_reg<=1'b0;
// F : txd_reg<=1'b1;
// default : txd_reg<=1'b0;
// endcase
//
//
reg cs,ns;
parameter
A = 6'b000001,
B = 6'b000010,
C = 6'b000100,
D = 6'b001000,
E = 6'b010000,
F = 6'b100000;
always@(posedge tx_clk or negedge rst_n)
if(!rst_n)
begin
cs <= A;
end
else
cs <= ns;
always@(*)
begin
// ns <= 6'b0;
case(cs)
A: if(data==1'b0) ns<=B; else ns<=A;
B: if(data==1'b0) ns<=C; else ns<=A;
C: if(data==1'b0) ns<=D; else ns<=A;
D: if(data==1'b0) ns<=E; else ns<=A;
E: if(data==1'b0) ns<=F; else ns<=A;
F: if(data==1'b0) ns<=B; else ns<=A;
endcase
end
always@(posedge tx_clk or negedge rst_n)
if(!rst_n)
txd_reg<=1'b0;
else
case(ns)
A,B,C,D,E: txd_reg<=1'b0;
F : txd_reg<=1'b1;
default : txd_reg<=1'b0;
endcase
assign txd = txd_reg; 上面三种都试验了下,我的版本是10.1,请高人指点下 中国就是这样,好的东西都不愿拿出来分享,所有祖先好多好的东西都没有很好的留下来,让我共同努力改变这些吧 mark 回复【22楼】linhaimi
-----------------------------------------------------------------------
22楼亮了~!!请问这里simulink里面用的是DSPbuilder吗?这部分有没有教程 mark! 学好英语是必须的。下个学期要努力的啊 mark mark mark, 状态机。 获益匪浅啊 mark mark 马甲 标记一下 手机上.Mark mark mark mark
页:
[1]