单端口RAM
`timescale 1ns/1ns
module 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) begin
if(!rst) begin
for (i=0; i<127 ; i=i+1) begin
mem[i] <= 'b0;
end
end
else if (enb) begin
mem[addr] <= w_data;
end
end
assign r_data = (!enb)?mem[addr]:'b0;
endmodule
JS计数器
`timescale 1ns/1ns
module JC_counter(
input clk ,
input rst_n,
output reg [3:0] Q
);
always@(posedge clk or negedge rst_n)begin
if(!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/1ns
module 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;
//defination
wire [N - 1 : 0] temp [0 : 3];
reg [N - 1 : 0] adder_0;
reg [N - 1 : 0] adder_1;
//output
genvar i;
generate
for(i = 0; i < 4; i = i + 1)begin : loop
assign temp[i] = mul_b[i] ? mul_a << i : 'd0;
end
endgenerate
always@(posedge clk or negedge rst_n)begin
if(!rst_n) adder_0 <= 'd0;
else adder_0 <= temp[0] + temp[1];
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n) adder_1 <= 'd0;
else adder_1 <= temp[2] + temp[3];
end
always@(posedge clk or negedge rst_n)begin
if(!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) begin
if(~rst_n)
cnt <= 0;
else
cnt <= cnt==6? 1: cnt+1;
end
always@(posedge clk or negedge rst_n) begin
if(~rst_n)
state <= ZERO;
else
state <= nstate;
end
always@(*) begin
if(~rst_n)
nstate = ZERO;
else
case(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;
endcase
end
always@(*) begin
if(~rst_n) begin
match = 0;
not_match = 0;
end
else begin
match = cnt==6&&state==SIX;
not_match = cnt==6&&state==FAIL;
end
end
endmodule
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) begin
if(~rst_n)
cnt <= 0;
else
cnt <= cnt==5? 0: cnt+1;
end
always@(posedge clk or negedge rst_n) begin
if(~rst_n)
data_r <= 6'b0;
else
data_r <= {data_r[4:0], data};
end
always@(posedge clk or negedge rst_n) begin
if(~rst_n) begin
match <= 1'b0;
not_match <= 1'b0;
end
else begin
match <= (cnt==5) && ({data_r[4:0], data}==6'b011100);
not_match <= (cnt==5) && ({data_r[4:0], data}!=6'b011100);
end
end
endmodule
判断必须要这样判断,不可写为~match。
因为要match时,是要取反的是当下周期,但是由于是非阻塞,此时macth是上个周期的,但非阻塞,就会导致下个Not_match取反的就是上个周期的match而不是当下周期的,下个周期的match取反才是需要的
需要注意由于是非阻塞,所以当前进入的数据会在下一个周期里才会进入寄存器,所以在本周期中如果要输出,就需要额外再移位判断一下
信号发生器
在方波时,
// 仅在方波模式工作的计数器
always@(posedge clk or negedge rst_n) begin
if(~rst_n)
cnt <= 0;
else
cnt <= 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;
end
else case (wave_choise)
2'b00: //产生方波,保持0十个时钟,保持20十个时钟
begin
if (cnt == 19)
begin
wave <= 0;
cnt <= 0;
end
else if(cnt == 9)
begin
wave <= 20;
cnt <= cnt + 1;
end
else
begin
wave <= wave;
cnt <= cnt + 1;
end
end
2'b01: //产生锯齿,0递增到20
begin
if (wave == 20)
begin
wave <= 0;
end
else
begin
wave <= wave + 1;
end
end
2'b10:
begin
if (wave == 20)
begin
wave <= wave - 1;
up <= 0;
end
else if (wave == 0)
begin
wave <= wave + 1;
up <= 1;
end
else if (up)
begin
wave <= wave + 1;
end
else
begin
wave <= wave - 1;
end
end
default:
begin
wave <= 1;
end
endcase
endmodule
交通灯
竞争与险象