单端口RAM
`timescale 1ns/1nsmodule RAM_1port(input clk,input rst,input enb,input [6:0]addr,input [3:0]w_data,output wire [3:0]r_data
);reg [6:0]mem[127:0];integer i;always @(posedge clk or negedge rst) beginif(!rst) beginfor (i=0; i<127 ; i=i+1) beginmem[i] <= 'b0;endendelse if (enb) beginmem[addr] <= w_data;endendassign r_data = (!enb)?mem[addr]:'b0;endmodule
JS计数器
`timescale 1ns/1nsmodule JC_counter(input clk ,input rst_n,output reg [3:0] Q
);always@(posedge clk or negedge rst_n)beginif(!rst_n) Q <= 'd0;else Q <= {~Q[0], Q[3 : 1]};end
endmodule
流水线乘法器
assign mul_1 = mul_b[0]? mul_a: 0;assign mul_2 = mul_b[1]? mul_a<<1: 0;assign mul_3 = mul_b[2]? mul_a<<2: 0;assign mul_4 = mul_b[3]? mul_a<<3: 0;
这步就是竖式乘法,认为是b个a相加在一起,b的最低位上的数字意味着有1个a,b[1]位上的数字意味着有2个a,b[2]意味有4个,B【3】意味有8个。所以就采用移位方式。
assign sum_1 = {size*(1'b0),mul_r1} + {size*(1'b0),mul_r2};assign sum_2 = {size*(1'b0),mul_r3} + {size*(1'b0),mul_r4};
`timescale 1ns/1nsmodule multi_pipe#(parameter size = 4
)(input clk , input rst_n ,input [size-1:0] mul_a ,input [size-1:0] mul_b ,output reg [size*2-1:0] mul_out
);//parameter parameter N = size * 2;//definationwire [N - 1 : 0] temp [0 : 3];reg [N - 1 : 0] adder_0;reg [N - 1 : 0] adder_1;//output genvar i;generatefor(i = 0; i < 4; i = i + 1)begin : loopassign temp[i] = mul_b[i] ? mul_a << i : 'd0;endendgeneratealways@(posedge clk or negedge rst_n)beginif(!rst_n) adder_0 <= 'd0;else adder_0 <= temp[0] + temp[1];endalways@(posedge clk or negedge rst_n)beginif(!rst_n) adder_1 <= 'd0;else adder_1 <= temp[2] + temp[3];endalways@(posedge clk or negedge rst_n)beginif(!rst_n) mul_out <= 'd0;else mul_out <= adder_0 + adder_1;end
endmodule
这里注意temp[]的位数是N-1.即两倍的乘法位数。
变量名前的【】表示变量的位宽,每位的位宽。变量名后的【】表示数组长度,相同变量的个数,串在一起。
不重叠序列检测
状态机
`timescale 1ns/1ns
module sequence_detect(input clk,input rst_n,input data,output reg match,output reg not_match);parameter ZERO=0, ONE=1, TWO=2, THREE=3, FOUR=4, FIVE=5, SIX=6, FAIL=7;reg [2:0] state, nstate;reg [2:0] cnt;always@(posedge clk or negedge rst_n) beginif(~rst_n)cnt <= 0;elsecnt <= cnt==6? 1: cnt+1; endalways@(posedge clk or negedge rst_n) beginif(~rst_n)state <= ZERO;elsestate <= nstate;endalways@(*) beginif(~rst_n)nstate = ZERO;elsecase(state)ZERO : nstate = data? FAIL : ONE;ONE : nstate = data? TWO : FAIL;TWO : nstate = data? THREE: FAIL;THREE: nstate = data? FOUR : FAIL;FOUR : nstate = data? FAIL : FIVE;FIVE : nstate = data? FAIL : SIX;SIX : nstate = data? FAIL : ONE;FAIL : nstate = cnt==6&&data==0? ONE: FAIL;default: nstate = ZERO;endcaseendalways@(*) beginif(~rst_n) beginmatch = 0;not_match = 0;endelse beginmatch = cnt==6&&state==SIX;not_match = cnt==6&&state==FAIL;endendendmodule
FAIL : nstate = cnt==6&&data==0? ONE: FAIL;
移位寄存器
`timescale 1ns/1ns
module sequence_detect(input clk,input rst_n,input data,output reg match,output reg not_match);reg [2:0] cnt;reg [5:0] data_r;always@(posedge clk or negedge rst_n) beginif(~rst_n)cnt <= 0;else cnt <= cnt==5? 0: cnt+1;endalways@(posedge clk or negedge rst_n) beginif(~rst_n)data_r <= 6'b0; elsedata_r <= {data_r[4:0], data};endalways@(posedge clk or negedge rst_n) beginif(~rst_n) beginmatch <= 1'b0;not_match <= 1'b0;endelse beginmatch <= (cnt==5) && ({data_r[4:0], data}==6'b011100);not_match <= (cnt==5) && ({data_r[4:0], data}!=6'b011100);endendendmodule
判断必须要这样判断,不可写为~match。
因为要match时,是要取反的是当下周期,但是由于是非阻塞,此时macth是上个周期的,但非阻塞,就会导致下个Not_match取反的就是上个周期的match而不是当下周期的,下个周期的match取反才是需要的
需要注意由于是非阻塞,所以当前进入的数据会在下一个周期里才会进入寄存器,所以在本周期中如果要输出,就需要额外再移位判断一下
信号发生器
在方波时,
// 仅在方波模式工作的计数器
always@(posedge clk or negedge rst_n) beginif(~rst_n)cnt <= 0;elsecnt <= wave_choise!=0 ? 0:cnt ==19? 0:cnt + 1;
end
如果波形选择不是0,即!=0成立,那么cnt就一直保持为0;不然就是==0成立,然后判断cnt是不是等于19,如果是的话,就复位,重新计数,不然就+1
wave <= cnt ==9 ? 20: cnt ==19? 0 :wave;
就是cnt是只在方波模式下才工作的,先判断cnt是否==9,是的话就让wave=20;不是的话,就判断是不是等于19,是的话复位到0,不然就保持,这样实现出来的话,每个周期下,前半个周期是低电平,只有到cnt==9时,wave在下个周期设置为20,才会在后半个周期显示为高电平。
`timescale 1ns/1ns
module signal_generator(input clk,input rst_n,input [1:0] wave_choise,output reg [4:0]wave);reg [4:0]cnt;reg up;always @(posedge clk or negedge rst_n)if (!rst_n)begin wave <= 0;cnt <= 0;endelse case (wave_choise)2'b00: //产生方波,保持0十个时钟,保持20十个时钟beginif (cnt == 19)begin wave <= 0;cnt <= 0;endelse if(cnt == 9)begin wave <= 20;cnt <= cnt + 1;endelsebeginwave <= wave;cnt <= cnt + 1;endend2'b01: //产生锯齿,0递增到20beginif (wave == 20)beginwave <= 0;endelse beginwave <= wave + 1;endend2'b10:beginif (wave == 20)beginwave <= wave - 1;up <= 0;endelse if (wave == 0)beginwave <= wave + 1;up <= 1;endelse if (up)beginwave <= wave + 1;endelse beginwave <= wave - 1;endenddefault:beginwave <= 1;endendcase
endmodule
交通灯
竞争与险象