牛客网 VL1 四选一多路器
多路器一般考虑用三目运算符=A?B:C;超过2路的考虑用基本两路复用器级联
timescale 1ns/1ns
module mux4_1(
input [1:0]d1,d2,d3,d0,
input [1:0]sel,
output[1:0]mux_out
);
//*************code***********//
wire [1:0] mux_out1,mux_out2;
assign mux_out=sel[1]?mux_out1:mux_out2;
assign mux_out1=sel[0]?d0:d1;
assign mux_out2=sel[0]?d2:d3;
//*************code***********//
endmodule`
牛客网 VL2 异步复位的串连T触发器
这题需要注意的是串连的是T触发器而不是D触发器,审题很重要
同时不要忘记阻塞赋值的习惯
`timescale 1ns/1ns
module Tff_2 (
input wire data, clk, rst,
output reg q
);
//*************code***********//
reg q_mid;
always@(posedge clk,negedge rst)
if(!rst)
q_mid<=0;
else
if(data==1)
q_mid<=~q_mid;
else
q_mid<=q_mid;
always@(posedge clk,negedge rst)
if(!rst)
q<=0;
else
if(q_mid==1)
q<=~q;
else
q<=q;
//*************code***********//
endmodule
牛客网 VL3 奇偶校验
本题难在1.审题,sel的功能是当sel为0时输出check取反
2.奇偶校验本质上是一个数按位异或^bus
原理 只有1 xor 0=1因此当1 xor 0 时不变号,忽略0在xor中的作用。当1遇到奇数个1互相xor时结果为1,而1xor 偶数个1时结果为0,而中间遇到多少个0并不影响结果。
`timescale 1ns/1ns
module odd_sel(
input [31:0] bus,
input sel,
output check
);
//*************code***********//
wire check_mid;
assign check_mid=^bus;
assign check=sel?check_mid:~check_mid;
//*************code***********//
endmodule
牛客网 VL4 移位运算与乘法
由于这题状态转换并不复杂,因此仅仅设立单状态mini_state,而不用状态转换模型。
需要注意的是每次时钟脉冲到来时,判断的是前一瞬间的值。
`timescale 1ns/1ns
module multi_sel(
input [7:0]d ,
input clk,
input rst,
output reg input_grant,
output reg [10:0]out,
output reg [1:0] mini_state
);
//*************code***********//
reg [7:0]data;
always@(posedge clk,negedge rst)
if(!rst)
mini_state<=2'b00;
else
mini_state<=mini_state+1;//时钟上升沿到来状态+1
always@(posedge clk)
if(mini_state==2'b00)
data<=d;//锁存输入数据
always@(posedge clk,negedge rst)
if(!rst)
begin
out<=10'b00_0000_0000;
input_grant<=0;
end
else
case(mini_state)
2'b00:
begin
out<=d;
input_grant<=1;
end
2'b01:
begin
out<=data*3;
input_grant<=0;
end
2'b10:
begin
out<=data*7;
input_grant<=0;
end
2'b11:
begin
out<=data*8;
input_grant<=0;
end
endcase
//*************code***********//
endmodule
牛客网 VL5 位拆分与运算
观察题目波形,本题异步性较强,观察到输出out随输入sel同时改变,因此主要通过assign语句实现组合逻辑,然后用always语句实现输入锁存的时序逻辑。
`timescale 1ns/1ns
module data_cal(
input clk,
input rst,
input [15:0]d,
input [1:0]sel,
output [4:0]out,
output validout
);
//*************code***********//
reg [15:0]d_lock;//锁存输入
wire [15:0]d1,d2,d3,out1,out2;
assign d1=d_lock[3:0]+d_lock[7:4];
assign d2=d_lock[3:0]+d_lock[11:8];
assign d3=d_lock[3:0]+d_lock[15:12];
assign validout=sel[0]|sel[1];
assign out1=sel[0]?d1:0;
assign out2=sel[0]?d3:d2;
assign out=sel[1]?out2:out1;
always@(posedge clk,negedge rst)
if(~rst)
d_lock<=d_lock;//复位操作
else
begin
if(~(sel[0]|sel[1]))
d_lock<=d;//锁存
end
//*************code***********//
endmodule