赞
踩
几个星期没有更新了,最近一直忙,现在能抽点时间继续补充了。其次我就是想吐槽一下这个csdn自带的文章编辑,已经习惯了撤销是ctrl+z,谁知道这里是从头到尾都撤销了,相当于删除了所有,已经两次了,想要恢复已经来不及了。心态直接炸了,没办法,再重新写吧,害!
1,多个三目运算用法的转换
VHDL中单个三目运算还是能看来出来的,但是多个在一起的用法可能对于新手来说不是很友好,所以在这里遇到了就顺便提及一下,直接上代码
A <= '0' when (B = '0') else '1' when (B = '1') else '0';
其实理解了它想表达的意思,转换过来就不是很难,大体可以这样理解:当B = '0' 时,A <= '0' ;当B = '1' 时,A <= '1';else A <= '0',(反正我是这样理解的,有错误或者有异议的可以在评论区指点一下)转换后如下
assign A = ((B == 1'b0)) ? 1'b0 : ((B == 1'b1)) ? 1'b1 : 1'b0;
注意点就是转换过来时是assign赋值语句。
当然,为其他值的情况也一样,如下
A <= C when (B = '0') else D when (B = '1') else C;
assign A = ((B == 1'b0)) ? C: ((B == 1'b1)) ? D : C;
2,process和always
process相当于verilog中的always语句,直接转换就行,要注意的是上下沿的变化。
- process (clk,rst_n) begin
- if (rst_n='1') then
- data <= '0';
- elsif (clk'Event and clk='1') then
- if (data_d1 = '0' and data_d2 = '1') then
- data <= '1';
- else
- data <= '0';
- end if;
- end if;
- end process;
上面这里process后面括号里面都为上升沿所以转换过来就是always@(posedge clk or posedge rst_n), 之后的(clk'Event and clk='1') then的意思可以理解为clk'event是指信号clk是否发生跳变,若发生了则返回ture,否则为假,clk=‘1’是跳变后clk为高电平。合起来就是当clk信号的上升沿则.... 都说VHDL严谨,从这里就可以看得出,但转换成verilog后这句基本是省略掉的,if条件语句变化不大,这里就不做过多的赘述,所以转换后的如下
- always @(posedge clk or posedge rst_n)begin
- if (rst_n== 1'b1)
- data <= 1'b0;
- else begin
- if (data_d1 == 1'b0 && data_d2 == 1'b1)
- data <= 1'b1;
- else
- data <= 1'b0;
- end
- end
转换过来后就比较清晰明了了,VHDL注重严谨,所以看起来就很繁琐,verilog只要逻辑语法正确,很好掌握的,对初学者也很友好。
3、case语句
在always语句也有经常会遇到多路条件分支的形式,一般用的就是case语句
- process (sclk,rst_n) begin
- if (rst_n='1') then
- data1 <= (others => '0');
- data2 <= (others => '0');
- data3 <= (others => '0');
- elsif (clk'event and clk='1') then
- case (sel) is
- when "00" =>
- data1 <= channel0;
- data2 <= channel0;
- data3 <= channel0;
- when "01" =>
- data1 <= channel1;
- data2 <= channel1;
- data3 <= channel1;
- when "10" =>
- data1 <= channel2;
- data2 <= channel2;
- data3 <= channel2;
- when "11" =>
- data1 <= channel3;
- data2 <= channel3;
- data3 <= channel3;
- when others =>
- data1 <= (others => '0');
- data2 <= (others => '0');
- data3 <= (others => '0');
- end case;

这里data1 <= (others => '0');它的意思是将data1的所有位都设为‘0’,前面也有提及到,这里就再补充一下另外一种写法,倘若data1定义为8位的数据,则转换成verilog后为:data1 <= {8{1'b0}};当然也可以用之前说过的写法,看个人喜好来理解。最终整个语句转换后如下
- always @(posedge clk or posedge rst_n)
- if (rst_n== 1'b1)
- begin
- data1 <= {8{1'b0}};
- data2 <= {8{1'b0}};
- data3 <= {8{1'b0}};
- end
- else
- case (sel)
- 2'b00 :
- begin
- data1 <= channel0;
- data2 <= channel0;
- data3 <= channel0;
- end
-
- 2'b01 :
- begin
- data1 <= channel1;
- data2 <= channel1;
- data3 <= channel1;
- end
-
- 2'b10 :
- begin
- data1 <= channel2;
- data2 <= channel2;
- data3 <= channel2;
- end
-
- 2'b11 :
- begin
- data1 <= channel3;
- data2 <= channel3;
- data3 <= channel3;
- end
-
- default :
- begin
- data1 <= {8{1'b0}};
- data2 <= {8{1'b0}};
- data3 <= {8{1'b0}};
- end
- endcase

另一种常见的用法
- process (clk,rst_n) begin
- if (rst_n='1') then
- data <= (others => '0'); //16位的数据
- elsif (clk'Event and clk='1') then
- case sel (3 downto 0) is
- when x"0" => data <= x"0" & channel0;
- when x"1" => data <= x"0" & channel1;
- when x"2" => data <= x"0" & channel2;
- when x"3" => data <= x"0" & channel3;
- when x"4" => data <= x"0" & channel4;
- when x"5" => data <= x"0" & channel5;
- when others => data <= (others => '0');
- end case;
- end if;
- end process;
转换后
- always @(posedge clk or posedge rst_n)
- if (rst_n == 1'b1)
- data <= {16{1'b0}};
- else
- case (sel[3:0])
- 4'h0 :
- data <= {4'h0, channel0};
- 4'h1 :
- data <= {4'h0, channel1};
- 4'h2 :
- data <= {4'h0, channel2};
- 4'h3 :
- data <= {4'h0, channel3};
- 4'h4 :
- data <= {4'h0, channel4};
- 4'h5 :
- data <= {4'h0, channel5};
- default :
- data <= {16{1'b0}};
- endcase

4、VHDL数据类型(Data Types)
VHDL中共有4类类型:标量类型、复合类型、访问类型、文件类型。你可以基于上述类型的基础上自定义自己的类型,或者使用subtype关键字来约束已存在的类型。感兴趣的可以去了解一下,这里用到的是标量类型中的枚举类型。
枚举类型:枚举类型是一组具有明确值的集合。枚举中的值是一个命名项或者一个字符。 语法(Syntax)
type 枚举名 is ( 枚举元素, 枚举元素, ... );
type new_name is ( type_element, type_element, ... );
这里用来作为状态机的定义,很简单的用法
- type FSM is (
- IDLE ,
- WRITE_1 ,
- READ_1 ,
- WRITE_2 ,
- READ_2 ,
- READ_WAIT
- );
转换后就是这样
- parameter [2:0] FSM_IDLE = 3'd0,
- FSM_WRITE_1 = 3'd1,
- FSM_READ_1 = 3'd2,
- FSM_WRITE_2 = 3'd3,
- FSM_READ_2 = 3'd4,
- FSM_READ_WAIT = 3'd5;
这章就到这里吧,目前遇到的几个常用的语法也就这么多了,这只是字面上的转换,具体还得读懂代码会用代码,那样的话遇到或者用到就比较方便了,最后还是那句话,有错误或者异议的欢迎各位大佬在评论区留言探讨。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。