單端口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
交通燈
競爭與險象