VL25 输入序列连续的序列检测
`timescale 1ns/1ns
module sequence_detect(
input clk,
input rst_n,
input a,
output reg match
);
reg [2:0]cnt;
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
cnt<=3'b000;
else if(cnt==3'd7)
cnt<=0;
else
cnt<=cnt+3'b1;
end
reg sig1,sig2,sig3,sig4,sig5,sig6,sig7,sig8;
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
sig1<=1'b0;
sig2<=1'b0;
sig3<=1'b0;
sig4<=1'b0;
sig5<=1'b0;
sig6<=1'b0;
sig7<=1'b0;
sig8<=1'b0;
end
else
case(cnt)
3'b000: sig1=(a==0)?1:0;
3'b001: sig2=(a==1)?1:0;
3'b010: sig3=(a==1)?1:0;
3'b011: sig4=(a==1)?1:0;
3'b100: sig5=(a==0)?1:0;
3'b101: sig6=(a==0)?1:0;
3'b110: sig7=(a==0)?1:0;
3'b111: sig8=(a==1)?1:0;
default: begin
sig1<=1'b0;
sig2<=1'b0;
sig3<=1'b0;
sig4<=1'b0;
sig5<=1'b0;
sig6<=1'b0;
sig7<=1'b0;
sig8<=1'b0;
end
endcase
end
always@(*)
if(!rst_n)
match<=1'b0;
else
match=sig1&sig2&sig3&sig4&sig5&sig6&sig7;
endmodule
我用这种方法进行计算,但是数据不对,经过debug可知,实际输入数据是一长串,而并非简单的输入8位判断8位,因此需要换一种思路去求解。
官方解答方案:
`timescale 1ns/1ns
module sequence_detect(
input clk,
input rst_n,
input a,
output reg match
);
reg [7:0] a_tem;
always @(posedge clk or negedge rst_n)
if (!rst_n)
begin
match <= 1'b0;
end
else if (a_tem == 8'b0111_0001)
begin
match <= 1'b1;
end
else
begin
match <= 1'b0;
end
always @(posedge clk or negedge rst_n)
if (!rst_n)
begin
a_tem <= 8'b0;
end
else
begin
a_tem <= {a_tem[6:0],a};
end
endmodule
按照官方思路,利用状态机进行求解:
`timescale 1ns/1ns
module sequence_detect(
input clk,
input rst_n,
input a,
output reg match
);
reg [3:0]state;
reg matchbuf;
always@(posedge clk or negedge rst_n)
if(!rst_n)begin
match<=1'b0;
state<=1'b0;
end
else
case(state)
4'b0000: begin matchbuf=(a==0)?1:0; state=(a==0)?4'b0001:4'b000; match=0; end
4'b0001: begin matchbuf=(a==1)?1:0; state=(a==1)?4'b0010:4'b000; match=0; end
4'b0010: begin matchbuf=(a==1)?1:0; state=(a==1)?4'b0011:4'b000; match=0; end
4'b0011: begin matchbuf=(a==1)?1:0; state=(a==1)?4'b0100:4'b000; match=0; end
4'b0100: begin matchbuf=(a==0)?1:0; state=(a==0)?4'b0101:4'b000; match=0; end
4'b0101: begin matchbuf=(a==0)?1:0; state=(a==0)?4'b0110:4'b000; match=0; end
4'b0110: begin matchbuf=(a==0)?1:0; state=(a==0)?4'b0111:4'b000; match=0; end
4'b0111: begin matchbuf=(a==1)?1:0; state=(a==1)?4'b1000:4'b000; match=0; end
4'b1000: begin match=1;state=4'b0000;end
default: begin state=4'b0000;match=0;end
endcase
endmodule
VL26 含有无关项的序列检测
与上一题类似,直接照抄修改即可:
`timescale 1ns/1ns
module sequence_detect(
input clk,
input rst_n,
input a,
output reg match
);
reg [3:0]state;
reg matchbuf;
always@(posedge clk or negedge rst_n)
if(!rst_n)begin
match<=1'b0;
state<=1'b0;
end
else
case(state)
4'b0000: begin matchbuf=(a==0)?1:0; state=(a==0)?4'b0001:4'b000; match=0; end
4'b0001: begin matchbuf=(a==1)?1:0; state=(a==1)?4'b0010:4'b000; match=0; end
4'b0010: begin matchbuf=(a==1)?1:0; state=(a==1)?4'b0011:4'b000; match=0; end
// 4'b0011: begin matchbuf=(a==1)?1:0; state=(a==1)?4'b0100:4'b000; match=0; end
// 4'b0100: begin matchbuf=(a==0)?1:0; state=(a==0)?4'b0101:4'b000; match=0; end
// 4'b0101: begin matchbuf=(a==0)?1:0; state=(a==0)?4'b0110:4'b000; match=0; end
4'b0011: begin state=4'b0100; match=0; end
4'b0100: begin state=4'b0101; match=0; end
4'b0101: begin state=4'b0110; match=0; end
4'b0110: begin matchbuf=(a==1)?1:0; state=(a==1)?4'b0111:4'b000; match=0; end
4'b0111: begin matchbuf=(a==1)?1:0; state=(a==1)?4'b1000:4'b000; match=0; end
4'b1000: begin matchbuf=(a==0)?1:0; state=(a==0)?4'b1001:4'b000; match=0; end
4'b1001: begin match=1;state=4'b0000;end
// 4'b1000: begin match=1;state=4'b0000;end
default: begin state=4'b0000;match=0;end
endcase
endmodule
为了能够合理使用三段式状态机,因此我按照三段式状态机进行重新编写。
`timescale 1ns/1ns
module sequence_detect(
input clk,
input rst_n,
input a,
output reg match
);
reg [3:0]state;
reg [3:0]nextstate;
reg matchbuf;
//状态转换状态机
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
state<=4'b0000;
else
state<=nextstate;
end
//输出状态机
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
match<=0;
else if(state==4'b1001)
match<=1;
else
match<=0;
end
//组合逻辑状态机,描述不同状态的不同性能
always@(*)begin
case(state)
4'b0000: begin nextstate=(a==0)?4'b0001:4'b000; matchbuf=0;end
4'b0001: begin nextstate=(a==1)?4'b0010:4'b000; matchbuf=0;end
4'b0010: begin nextstate=(a==1)?4'b0011:4'b000; matchbuf=0;end
4'b0011: begin nextstate=4'b0100; matchbuf=0;end
4'b0100: begin nextstate=4'b0101; matchbuf=0;end
4'b0101: begin nextstate=4'b0110; matchbuf=0;end
4'b0110: begin nextstate=(a==1)?4'b0111:4'b000; matchbuf=0;end
4'b0111: begin nextstate=(a==1)?4'b1000:4'b000; matchbuf=0;end
4'b1000: begin nextstate=(a==0)?4'b1001:4'b000; matchbuf=0;end
4'b1001: begin nextstate=4'b0000;matchbuf=1;end
default: nextstate=4'b0000;
endcase
end
endmodule
费了点劲儿,不过感觉熟练了不少。妈的女朋友还在生气,13点04分,不想睡觉了继续做吧。
VL27 不重叠序列检测
`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
通过写状态机来解决这个问题。
VL28 输入序列不连续的序列检测
暂时先不做这个了,妈的有点麻最近,tp简历挂,劳资双九也能挂?
`timescale 1ns/1ns
module sequence_detect(
input clk,
input rst_n,
input data,
input data_valid,
output reg match
);
reg [2:0] state;
reg matchbuf;
always@(posedge clk or negedge rst_n)
if(!rst_n)begin
match<=0;
state<=3'b000;
end
else if(data_valid)begin
case(state)
3'b000: begin state=(data==0)?3'b001:3'b000; match=0;end
3'b001: begin state=(data==1)?3'b010:3'b000; match=0;end
3'b010: begin state=(data==1)?3'b011:3'b000; match=0;end
3'b011: begin match=(data==0)?1:0; state=3'b100; end
3'b100: begin state=3'b000; match=0;end
default: begin state=3'b000; match=0;end
// 3'b100: state=(data==1)?3'b011:3'b000;
endcase
end
else
match<=0;
endmodule
按照波形图实现该功能,测试一下用tb来调试这个程序。
`timescale 1ns/1ns
module testbench();
reg clk,rst_n;
reg data;
reg data_valid;
wire match;
always#1 clk = ~clk;
initial begin
$dumpfile("out.vcd");
$dumpvars(0,testbench);
clk = 1;
rst_n = 0;
data = 0;
data_valid = 0;
#20;
rst_n = 1;
#2;
data = 0;
#2;
data = 1;
#2;
data = 1;
#2;
data_valid = 1;
#2;
data = 1;
#2;
data = 0;
#2;
data = 1;
#2;
data = 0;
#2;
data = 0;
#2;
data_valid = 0;
#2;
data_valid = 1;
data = 1;
#2;
data = 1;
#2;
data = 0;
#80;
$finish;
end
sequence_detect dut(
.clk(clk),
.rst_n(rst_n),
.data(data),
.data_valid(data_valid),
.match(match)
);
endmodule
tb测试结果如下:
可见,在正确的位置出现了脉冲波形,证明了算法的可行性。
VL29 信号发生器
在波形图上提供出一个信息:
//方波的周期是20,锯齿波的周期是21,三角波的周期是40,且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 flag;
// 方波模式下,计数器控制
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
// 三角波模式下,标志位控制
always@(posedge clk or negedge rst_n) begin
if(~rst_n)
flag <= 0;
else
flag <= wave_choise!=2 ? 0:
wave ==1 ? 1:
wave ==19? 0:
flag;
end
// 更新wave信号
always@(posedge clk or negedge rst_n) begin
if(~rst_n)
wave <= 0;
else
case(wave_choise)
0 : wave <= cnt == 9? 20 :
cnt ==19? 0 :
wave;
1 : wave <= wave==20? 0 : wave+1;
2 : wave <= flag==0 ? wave-1: wave+1;
default: wave <= 0;
endcase
end
endmodule
VL30 数据串转并电路
图中波形有一些问题,按照官方解法如下:
`timescale 1ns/1ns
module s_to_p(
input clk ,
input rst_n ,
input valid_a ,
input data_a ,
output reg ready_a ,
output reg valid_b ,
output reg [5:0] data_b
);
reg [5:0] data_reg;
reg [2:0] data_cnt;
always @(posedge clk or negedge rst_n ) begin
if(!rst_n)
ready_a <= 'd0;
else
ready_a <= 1'd1;
end
always @(posedge clk or negedge rst_n ) begin
if(!rst_n)
data_cnt <= 'd0;
else if(valid_a && ready_a)
data_cnt <= (data_cnt == 3'd5) ? 'd0 : (data_cnt + 1'd1);
end
always @(posedge clk or negedge rst_n ) begin
if(!rst_n)
data_reg <= 'd0;
else if(valid_a && ready_a)
data_reg <= {data_a, data_reg[5:1]};
end
always @(posedge clk or negedge rst_n ) begin
if(!rst_n)begin
valid_b <= 'd0;
data_b <= 'd0;
end
else if(data_cnt == 3'd5)begin
valid_b <= 1'd1;
data_b <= {data_a, data_reg[5:1]};
end
else
valid_b <= 'd0;
end
endmodule
VL32 非整数倍数据位宽转换24to128
麻了,这个位置是不固定的,需要修改不同的位数,解法如题,后续需要再仔细思考思考。
`timescale 1ns/1ns
module width_24to128(
input clk ,
input rst_n ,
input valid_in ,
input [23:0] data_in ,
output reg valid_out ,
output reg [127:0] data_out
);
reg [3:0] cnt;
reg [127:0] data_lock;
always@(posedge clk or negedge rst_n) begin
if(~rst_n)
cnt <= 0;
else
cnt <= ~valid_in? cnt:cnt+1;
end
always@(posedge clk or negedge rst_n) begin
if(~rst_n)
valid_out <= 0;
else
valid_out <= (cnt==5 || cnt==10 || cnt==15)&&valid_in;
end
always@(posedge clk or negedge rst_n) begin
if(~rst_n)
data_lock <= 0;
else
data_lock <= valid_in? {data_lock[103:0], data_in}: data_lock;
end
always@(posedge clk or negedge rst_n) begin
if(~rst_n)
data_out <= 0;
else if(cnt==5)
data_out <= valid_in? {data_lock[119:0], data_in[23:16]}: data_out;
else if(cnt==10)
data_out <= valid_in? {data_lock[111:0], data_in[23: 8]}: data_out;
else if(cnt==15)
data_out <= valid_in? {data_lock[103:0], data_in[23: 0]}: data_out;
else
data_out <= data_out;
end
endmodule
lv38 自动贩卖机
`timescale 1ns/1ns
module seller1(
input wire clk ,
input wire rst ,
input wire d1 ,
input wire d2 ,
input wire d3 ,
output reg out1,
output reg [1:0]out2
);
//*************code***********//
reg [2:0]money;
always@(posedge clk or negedge rst)
if(!rst)
money<=0;
else if(d1)
money<=money+3'd1;
else if(d2)
money<=money+3'd2;
else if(d3)
money<=money+3'd4;
else if(money>3||money==3)
money<=0;
always@(posedge clk or negedge rst)
if(!rst)
out1<=0;
else if(money>3||money==3)
out1<=1;
else
out1<=0;
always@(posedge clk or negedge rst)
if(!rst)
out2<=0;
else if(money>3||money==3)
out2<=money-3'd3;
else
out2<=0;
//*************code***********//
endmodule
喜极而泣,第一次一遍过,没有用debug。
LV39 自动贩卖机2
`timescale 1ns/1ns
module seller2(
input wire clk ,
input wire rst ,
input wire d1 ,
input wire d2 ,
input wire sel ,
output reg out1,
output reg out2,
output reg out3
);
//*************code***********//
//0.17-0.192
reg [7:0]money;
always@(posedge clk or negedge rst)
if(!rst)
money<=0;
else if(d1)
money<=money+3'd1;
else if(d2)
money<=money+3'd2;
else if(~sel&&money==3)begin
money<=0;end
else if(~sel&&money==4)begin
money<=0;end
else if(sel&&money==5)begin
money<=0;end
else if(sel&&money==6)begin
money<=0;end
always@(posedge clk or negedge rst)
if(!rst)begin
out1<=0;
out2<=0;
out3<=0;
end
else if(~sel&&money==3)begin
out1<=1;out2<=0;out3<=0;end
else if(~sel&&money==4)begin
out1<=1;out2<=0;out3<=1;end
else if(sel&&money==5)begin
out1<=0;out2<=1;out3<=0;end
else if(sel&&money==6)begin
out1<=0;out2<=1;out3<=1;end
else
begin
out1<=0;out2<=0;out3<=0;
end
//*************code***********//
endmodule
LV40 奇数分频
奇数分频通过设置上升沿和下降沿的两组分频后的时钟信号,进行or取并集,从而实现奇数分频。
代码如图:
`timescale 1ns/1ns
module odo_div_or
#(parameter N = 7)
(
input wire rst ,
input wire clk_in,
output wire clk_out7
);
reg [3:0] cnt ;
always @(posedge clk_in or negedge rst) begin
if (!rst) begin
cnt <= 'b0 ;
end
else if (cnt == N-1) begin
cnt <= 'b0 ;
end
else begin
cnt <= cnt + 1'b1 ;
end
end
reg clkp ;
always @(posedge clk_in or negedge rst) begin
if (!rst) begin
clkp <= 1'b0 ;
end
else if (cnt == (N>>1)) begin
clkp <= 1 ;
end
else if (cnt == N-1) begin
clkp <= 0 ;
end
end
reg clkn ;
always @(negedge clk_in or negedge rst) begin
if (!rst) begin
clkn <= 1'b0 ;
end
else if (cnt == (N>>1) ) begin
clkn <= 1 ;
end
else if (cnt == N-1) begin
clkn <= 0 ;
end
end
assign clk_out7 = clkp | clkn ;
endmodule
按照同样的逻辑进行修改,代码为:
`timescale 1ns/1ns
module odo_div_or
#(parameter N = 7)
(
input wire rst ,
input wire clk_in,
output wire clk_out7
);
reg [2:0]cnt;
always@(posedge clk_in or negedge rst)
if(!rst)
cnt<=0;
else if(cnt==6)
cnt<=0;
else
cnt<=cnt+3'd1;
reg clkp;
always@(posedge clk_in or negedge rst)
if(!rst)
clkp<=0;
else if(cnt==3)
clkp<=1'd1;
else if(cnt==6)
clkp<=1'd0;
reg clkn;
always@(negedge clk_in or negedge rst)
if(!rst)
clkn<=0;
else if(cnt==3)
clkn<=1'd1;
else if(cnt==6)
clkn<=1'd0;
assign clk_out7=clkn||clkp;
endmodule
经测试能够实现功能。
LV42 无占空比要求
奇奇怪怪,没啥意思,题目要求和答案不符合、。
`timescale 1ns/1ns
module odd_div (
input wire rst ,
input wire clk_in,
output wire clk_out5
);
//*************code***********//
reg [2:0]cnt;
always@(posedge clk_in or negedge rst)
if(!rst)
cnt<=0;
else if(cnt==4)
cnt<=0;
else
cnt<=cnt+3'd1;
reg clkn;
always@(posedge clk_in or negedge rst)
if(!rst)
clkn<=0;
else if(cnt==0)
clkn<=1;
else if(cnt==2)
clkn<=0;
reg clkp;
always@(negedge clk_in or negedge rst)
if(!rst)
clkp<=0;
else if(cnt==1)
clkp<=1;
else if(cnt==2)
clkp<=0;
assign clk_out5=clkn||clkp;
//*************code***********//
endmodule