搜索
bottom↓
回复: 53

indexed one-hot 风格的状态机写法,性能、面积占用和稳定性多半比多数人正在使用的方

[复制链接]

出0入0汤圆

发表于 2010-7-29 21:15:00 | 显示全部楼层 |阅读模式
如果你不知道标题里说的方法是什么,你来对地方了。

这是一个讲状态机怎么写的文档。若干天前在看systemverilog for design是,书里提到了indexed one-hot的风格,然后给了网址说这里有篇文章讲状态机的,就是这个:

点击此处下载 ourdev_571713.pdf(文件大小:266K) (原文件名:CummingsSNUG2003SJ_SystemVerilogFSM.pdf)

非常好的一篇牛文,看完会发现自己以前用的那种伪one-hot居然是最弱的方式。
我转到这种风格有些日子了,写了一些程序后发现占用资源的确是小了很多,而且你可以用诸如 assign module_idle = state[IDLE]; 这样的方式直接输出一些和状态有关的量,和 assign module_idle  = (state == IDLE); 相比,能节约多少资源,消除多少毛刺?
另外这种风格的状态机很稳定,可以直接使用某个状态机的位作为组合逻辑的敏感信号,比如 always @(state[IDLE])。OTL太爽了,状态机居然也能做敏感信号了。(我的板子反正用以前的风格由于毛刺的问题直接用状态做敏感信号必然跑飞,应该不是个案吧,那时还把我愁了2天)。

希望对大家有所帮助。

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

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

发表于 2010-7-29 21:18:57 | 显示全部楼层
最近将公司的东西改变成用状态机的方式,已经觉得条理更清晰、系统更稳定了,还沾沾自喜! 没想到楼主已经更进一步。(注我不是用HDL语言,是用在DSP上的C语言)

出0入0汤圆

 楼主| 发表于 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 [7:0] state = 8'b1;
reg [7:0] next = 8'b1;
reg [1:0] 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[IDLE]         :   if(!video_input_enable)     next[IDLE] = 1'b1;
                                    else    if(!coe_frame_valid)    next[WAIT_F] = 1'b1; //ensure it starts from the begin of a frame
                                            else                        next[IDLE] = 1'b1;
        state[WAIT_F]       :   if(coe_frame_valid)         next[LINE_START] = 1'b1;   
                                    else                                next[WAIT_F] = 1'b1;
        state[LINE_START]   :                                       next[WAIT_L] = 1'b1;
        state[WAIT_L]       :   if(!coe_frame_valid)            next[IDLE] = 1'b1;
                                    else    if(coe_line_valid)  next[PACK_DATA] = 1'b1;
                                            else                        next[WAIT_L] = 1'b1;   
        state[PACK_DATA]    :   if(!coe_line_valid)         next[WAIT_ST1] = 1'b1;
                                    else                                next[PACK_DATA] = 1'b1;
        state[WAIT_ST1] :   if(st_sender_idle)          next[LINE_END] = 1'b1;
                                    else                                next[WAIT_ST1] = 1'b1;      
        state[LINE_END] :                                       next[WAIT_ST2] = 1'b1;
        state[WAIT_ST2] :   if(st_sender_idle)          next[LINE_START] = 1'b1;
                                    else                                next[WAIT_ST2] = 1'b1;
        default             :                                       next[IDLE] = 1'b1;
    endcase
end

出0入0汤圆

发表于 2010-7-29 22:21:23 | 显示全部楼层
mark

出0入4汤圆

发表于 2010-7-29 23:24:32 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-7-29 23:30:00 | 显示全部楼层
都是高手

出0入0汤圆

发表于 2010-7-30 07:57:53 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-7-30 08:04:12 | 显示全部楼层
先顶

出0入0汤圆

发表于 2010-7-30 08:37:53 | 显示全部楼层
夸大事实。

出0入0汤圆

发表于 2010-7-30 10:26:15 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-7-30 10:32:16 | 显示全部楼层
回复【8楼】tear086 .COM 缺氧
夸大事实。
-----------------------------------------------------------------------

如何理解?

出0入0汤圆

发表于 2010-7-30 10:58:15 | 显示全部楼层
回复【10楼】eworker  
-----------------------------------------------------------------------

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

出0入0汤圆

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

出0入0汤圆

发表于 2010-7-30 11:15:24 | 显示全部楼层
回复【12楼】fzfh1219  
-----------------------------------------------------------------------

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

出0入0汤圆

发表于 2010-7-30 23:25:27 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-8-2 17:33:09 | 显示全部楼层
难道我在不知不觉中就尝试过这种方法了?我还没发觉,不过还没发现这种方法的好处...再研究研究.

出0入0汤圆

发表于 2010-8-2 17:40:14 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-8-2 17:55:49 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-8-6 10:02:22 | 显示全部楼层
谢谢楼主了,这些都是高层次的东西啊。难得。

出0入0汤圆

发表于 2011-2-16 16:36:50 | 显示全部楼层
就是看英语有点难度

出0入0汤圆

发表于 2011-2-16 17:30:29 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-2-16 17:45:39 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-2-16 18:14:29 | 显示全部楼层
应该还有更好的方法,对于一个状态机:

(原文件名:1.PNG)

(原文件名:2.PNG)
可以使用simulink建模,然后可以导出成C语言

(原文件名:c.PNG)
也可以导出成可综合的HDL

(原文件名:hdl.PNG)
编码方式可选

(原文件名:config.PNG)

出0入0汤圆

发表于 2011-2-16 18:37:06 | 显示全部楼层
回复【22楼】linhaimi
-----------------------------------------------------------------------

niubility!
如此强悍

出0入0汤圆

发表于 2011-2-16 20:34:11 | 显示全部楼层
占位,向高手学习一下哈

出0入0汤圆

发表于 2011-2-16 21:56:02 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-2-16 22:25:31 | 显示全部楼层
Verilog

出0入0汤圆

发表于 2011-2-17 08:40:40 | 显示全部楼层
回复【22楼】linhaimi  
-----------------------------------------------------------------------

这个牛逼。

出0入0汤圆

发表于 2011-5-16 09:40:34 | 显示全部楼层
matlab还真强大啊,就是太贵了,只能自用了

出0入0汤圆

发表于 2011-5-16 22:37:17 | 显示全部楼层
mark matlab

出0入0汤圆

发表于 2011-5-17 09:47:07 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-5-20 12:45:19 | 显示全部楼层
回复【22楼】linhaimi  
-----------------------------------------------------------------------

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

出0入0汤圆

发表于 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[5:0]        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[A]        <=        1'b1;
                end
        else
                cs        <=        ns;
       
always@(*)
        if(!rst_n)
        ns        <= 6'b0;
        else
        begin
        case(1'b1)
        cs[A]: if(data==1'b0) ns[B]<=1'b1; else ns[A]<=1'b1;
        cs[B]: if(data==1'b0) ns[C]<=1'b1; else ns[A]<=1'b1;
        cs[C]: if(data==1'b0) ns[D]<=1'b1; else ns[A]<=1'b1;
        cs[D]: if(data==1'b0) ns[E]<=1'b1; else ns[A]<=1'b1;
        cs[E]: if(data==1'b0) ns[F]<=1'b1; else ns[A]<=1'b1;
        cs[F]: if(data==1'b0) ns[B]<=1'b1; else ns[A]<=1'b1;
        endcase
        end
always@(posedge tx_clk or negedge rst_n)
        if(!rst_n)
        txd_reg<=1'b0;
        else
                case(1'b1)
                ns[B],ns[C],ns[D],ns[E] : txd_reg<=1'b0;
                ns[F],ns[A]                 :        txd_reg<=1'b1;
                default         : txd_reg<=1'b0;
                endcase

assign txd = txd_reg;
               
帮忙看看我改的,怎么会得不到了

出0入0汤圆

发表于 2011-5-22 11:30:23 | 显示全部楼层
OK,发现问题了。但是发现占用面积比以前要多啊

出0入0汤圆

发表于 2011-5-22 12:02:03 | 显示全部楼层
Combinational ALUTs 6和8,使用ONE-HOT是8个,使用三段式但是不是ONEHOT模式是6个,使用三段式ONE-HOT模式也是6个,没发现上面的这种有啥优势啊。

出0入0汤圆

发表于 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[5:0]        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[A]        <=        1'b1;
//                end
//        else
//                cs        <=        ns;
//       
//always@(*)
//        begin
//        ns        <= 6'b0;
//        case(1'b1)
//        cs[A]: if(data==1'b0) ns[B]<=1'b1; else ns[A]<=1'b1;
//        cs[B]: if(data==1'b0) ns[C]<=1'b1; else ns[A]<=1'b1;
//        cs[C]: if(data==1'b0) ns[D]<=1'b1; else ns[A]<=1'b1;
//        cs[D]: if(data==1'b0) ns[E]<=1'b1; else ns[A]<=1'b1;
//        cs[E]: if(data==1'b0) ns[F]<=1'b1; else ns[A]<=1'b1;
//        cs[F]: if(data==1'b0) ns[B]<=1'b1; else ns[A]<=1'b1;
//        endcase
//        end
//always@(posedge tx_clk or negedge rst_n)
//        if(!rst_n)
//        txd_reg<=1'b0;
//        else
//                case(1'b1)
//                ns[A],ns[B],ns[C],ns[D],ns[E] : txd_reg<=1'b0;
//                ns[F]                 :        txd_reg<=1'b1;
//                default         : txd_reg<=1'b0;
//                endcase




//reg[2:0]        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[5:0]        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;

出0入0汤圆

发表于 2011-5-22 12:07:18 | 显示全部楼层
上面三种都试验了下,我的版本是10.1,请高人指点下

出0入0汤圆

发表于 2011-8-2 09:58:17 | 显示全部楼层
中国就是这样,好的东西都不愿拿出来分享,所有祖先好多好的东西都没有很好的留下来,让我共同努力改变这些吧

出50入0汤圆

发表于 2011-8-2 10:48:19 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-8-2 14:22:46 | 显示全部楼层
回复【22楼】linhaimi  

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

出0入0汤圆

发表于 2011-8-10 17:28:48 | 显示全部楼层
mark!

出0入0汤圆

发表于 2011-8-10 18:35:29 | 显示全部楼层
学好英语是必须的。下个学期要努力的啊

出0入0汤圆

发表于 2011-11-1 11:58:21 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-11-1 12:43:27 | 显示全部楼层
mark

出0入4汤圆

发表于 2011-11-1 14:51:08 | 显示全部楼层
mark, 状态机。

出0入0汤圆

发表于 2011-11-3 13:51:15 | 显示全部楼层
获益匪浅啊

出0入0汤圆

发表于 2011-11-4 16:33:17 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-12-15 23:32:26 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-12-16 04:46:36 | 显示全部楼层
马甲

出0入0汤圆

发表于 2011-12-16 08:02:07 | 显示全部楼层
标记一下

出0入0汤圆

发表于 2011-12-16 08:24:50 | 显示全部楼层
手机上.  Mark

出0入0汤圆

发表于 2011-12-16 09:42:33 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-12-31 15:03:31 | 显示全部楼层
mark

出0入0汤圆

发表于 2012-1-1 23:03:00 | 显示全部楼层
mark
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-24 11:17

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表