wsypaul 发表于 2010-7-29 21:15:00

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:另外个人觉得中国人太吃亏了,信息传递的太慢。我怎么到现在才知道有这么好的方法呢?直到看原版书了才接触到了此类信息。诶。

youxin2004 发表于 2010-7-29 21:18:57

最近将公司的东西改变成用状态机的方式,已经觉得条理更清晰、系统更稳定了,还沾沾自喜! 没想到楼主已经更进一步。(注我不是用HDL语言,是用在DSP上的C语言)

wsypaul 发表于 2010-7-29 21:27:30

贴一个我这两天写的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

bad_fpga 发表于 2010-7-29 22:21:23

mark

D.lovers 发表于 2010-7-29 23:24:32

mark

eworker 发表于 2010-7-29 23:30:00

都是高手

wangff2531 发表于 2010-7-30 07:57:53

mark

fshunj 发表于 2010-7-30 08:04:12

先顶

tear086 发表于 2010-7-30 08:37:53

夸大事实。

wanwzy 发表于 2010-7-30 10:26:15

mark

eworker 发表于 2010-7-30 10:32:16

回复【8楼】tear086 .COM 缺氧
夸大事实。
-----------------------------------------------------------------------

如何理解?

tear086 发表于 2010-7-30 10:58:15

回复【10楼】eworker
-----------------------------------------------------------------------

独热码、格雷码和二进制码的使用,视状态数之多少而定,不能一概而论。顺便说下,二段式和三段式的FSM各有应用场合,亦不能一概而论。
点击此处下载 ourdev_571862.pdf(文件大小:695K) (原文件名:FSM 设计指导.pdf)

fzfh1219 发表于 2010-7-30 11:09:45

我知道这篇文章的作者,他的职业是一个HDL培训师,经验非常丰富。上大学的时候把他写的所有文章都打印出来学习了一遍,受益匪浅,这篇当然也不例外,文中讲述的状态机编码规则是受到普遍认可的,这一点毋庸置疑。indexed one-hot的风格确实能生成最高效的电路,但是用常规的二段式或三段式编码方式,也是能够生成类似电路的,现在的综合器更加智能了,能够由用户定义状态机的编码方式。
文中还提到了一种用状态位替换输出的编码方式,起初我觉得非常巧妙,后来觉得这种方式用起来不太灵活,因此也懒得用,毕竟也省不了几个寄存器。
另外,为了充分利用综合器的智能,状态机的状态最好用sysverilog中的enum类型定义,这样在综合时综合器就可忽略状态的具体编码,更利于电路的优化(这是我自己的体会,不保证正确哟!)

tear086 发表于 2010-7-30 11:15:24

回复【12楼】fzfh1219
-----------------------------------------------------------------------

呵呵,枚举在哪里都是个好东西。

ofdm_pa 发表于 2010-7-30 23:25:27

mark

yvhksovo 发表于 2010-8-2 17:33:09

难道我在不知不觉中就尝试过这种方法了?我还没发觉,不过还没发现这种方法的好处...再研究研究.

avic 发表于 2010-8-2 17:40:14

mark

ksniper 发表于 2010-8-2 17:55:49

mark

songtaosunboy 发表于 2010-8-6 10:02:22

谢谢楼主了,这些都是高层次的东西啊。难得。

shexujia 发表于 2011-2-16 16:36:50

就是看英语有点难度

cwfboy 发表于 2011-2-16 17:30:29

mark

qianhng 发表于 2011-2-16 17:45:39

mark

linhaimi 发表于 2011-2-16 18:14:29

应该还有更好的方法,对于一个状态机:
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)

fishplj2000 发表于 2011-2-16 18:37:06

回复【22楼】linhaimi
-----------------------------------------------------------------------

niubility!
如此强悍

smiler 发表于 2011-2-16 20:34:11

占位,向高手学习一下哈

HYFAVR 发表于 2011-2-16 21:56:02

mark

Jigsaw 发表于 2011-2-16 22:25:31

Verilog

syuanwang 发表于 2011-2-17 08:40:40

回复【22楼】linhaimi
-----------------------------------------------------------------------

这个牛逼。

pontiff 发表于 2011-5-16 09:40:34

matlab还真强大啊,就是太贵了,只能自用了

jlhgold 发表于 2011-5-16 22:37:17

mark matlab

zhanshenguilai 发表于 2011-5-17 09:47:07

mark

amote 发表于 2011-5-20 12:45:19

回复【22楼】linhaimi
-----------------------------------------------------------------------

请教:
按照您图片提示 ,在生成“hdl”文件时 出现错误“Chart Property'Execute(enter) chart at Initialization must be turned on for HDL coder”..
请问我哪里操作错误,请指教,谢谢

wgy596 发表于 2011-5-22 11:18:40

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;
               
帮忙看看我改的,怎么会得不到了

wgy596 发表于 2011-5-22 11:30:23

OK,发现问题了。但是发现占用面积比以前要多啊

wgy596 发表于 2011-5-22 12:02:03

Combinational ALUTs 6和8,使用ONE-HOT是8个,使用三段式但是不是ONEHOT模式是6个,使用三段式ONE-HOT模式也是6个,没发现上面的这种有啥优势啊。

wgy596 发表于 2011-5-22 12:06:15

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;

wgy596 发表于 2011-5-22 12:07:18

上面三种都试验了下,我的版本是10.1,请高人指点下

finelei2002 发表于 2011-8-2 09:58:17

中国就是这样,好的东西都不愿拿出来分享,所有祖先好多好的东西都没有很好的留下来,让我共同努力改变这些吧

yuzr 发表于 2011-8-2 10:48:19

mark

gaoyukun 发表于 2011-8-2 14:22:46

回复【22楼】linhaimi

-----------------------------------------------------------------------
22楼亮了~!!请问这里simulink里面用的是DSPbuilder吗?这部分有没有教程

huang_wei 发表于 2011-8-10 17:28:48

mark!

seazhui 发表于 2011-8-10 18:35:29

学好英语是必须的。下个学期要努力的啊

chahu1227 发表于 2011-11-1 11:58:21

mark

wwqq 发表于 2011-11-1 12:43:27

mark

get500wan 发表于 2011-11-1 14:51:08

mark, 状态机。

cngg123456 发表于 2011-11-3 13:51:15

获益匪浅啊

SDbeijixing 发表于 2011-11-4 16:33:17

mark

aikimi7 发表于 2011-12-15 23:32:26

mark

edaworld 发表于 2011-12-16 04:46:36

马甲

xuxi2009 发表于 2011-12-16 08:02:07

标记一下

stm8s 发表于 2011-12-16 08:24:50

手机上.Mark

kanerier 发表于 2011-12-16 09:42:33

mark

fengyuwuzu11 发表于 2011-12-31 15:03:31

mark

fpga2009 发表于 2012-1-1 23:03:00

mark
页: [1]
查看完整版本: indexed one-hot 风格的状态机写法,性能、面积占用和稳定性多半比多数人正在使用的方